Was sind einige Standardentwurfsmethoden zum Hinzufügen einer GUI zu einer Befehlszeilen-App? [geschlossen]


8

Ich habe eine eingebettete Linux C-Anwendung, die mit einer einfachen CLI ausgeführt wird. Ich bin jetzt damit beauftragt, eine GUI zu erstellen, die die gleiche Funktionalität wie das Befehlszeilenprogramm bietet. Ich bin kein versierter GUI-Designer und die Mehrheit, wenn meine Erfahrung in tief eingebetteter C-Codierung liegt.

Mein erster Gedanke ist, qtcreator zum Erstellen der GUI zu verwenden, aber es gibt einige Probleme, über die ich nachdenke.

  • In Zukunft möchte ich sowohl das CL-Programm als auch das GUI-Programm beibehalten und vorzugsweise sogar genau dieselbe ausführbare Datei haben, die in beiden Modi gestartet werden kann. Es sei denn, das ist eine schlechte Idee?
  • Mein Code ist bisher in C und qt ist nativ c ++
  • Ich möchte eine direkte Korrelation, bei der das Drücken von Tasten in der GUI dieselben Funktionen aufruft, die ich von der CLI aus aufrufe
  • Wie mache ich das am besten sauber und effizient? Gibt es eine andere Theologie oder Bibliothek, die dies vereinfacht? Ich muss qt nicht verwenden, wenn es etwas Besseres gibt.

Gegebenenfalls hängt es ziemlich stark von den Latenzanforderungen ab. Für einfache GUIs können Sie Skriptsprachen (Yad / Zenity / GTKdialog / TclTk / ... und so weiter) verwenden, um das Look & Feel schnell zu prototypisieren. Normalerweise müssen Sie eine 1-zu-1-Korrespondenz zwischen der GUI und dem Code vermeiden. Die Idee ist, die Benutzeroberfläche benutzerfreundlich und intuitiv zu gestalten und den Benutzer nicht zu zwingen, die Interna Ihrer Anwendung zu lernen.
Deer Hunter

Dieser Artikel objectmentor.com/resources/articles/TheHumbleDialogBox.pdf wird Ihnen höchstwahrscheinlich helfen - er erklärt "Model View Presenter", den besten Ansatz, den ich kenne, um die Benutzeroberfläche austauschbar zu machen.
Doc Brown

Antworten:


11

Ich könnte Ihnen einige grobe Richtlinien geben, wie Sie die entsprechende Benutzeroberfläche für eine CLI-App in Bezug auf das Design erstellen können. Wie Sie die Anrufe tatsächlich tätigen würden, ist nicht Gegenstand dieser Antwort.

  • Schalter wie -p -v usw. sind Kontrollkästchen

Geben Sie hier die Bildbeschreibung ein

  • sich gegenseitig ausschließende Optionen sind eine Gruppe von Optionsfeldern

Geben Sie hier die Bildbeschreibung ein

  • Parameter, die ein Dateiname sind, sind ein Textfeld mit einer Schaltfläche "Auswählen", in der beim Drücken ein Dialogfeld "Datei auswählen" angezeigt wird

Geben Sie hier die Bildbeschreibung ein

  • Zeichenfolgenparameter sind im Allgemeinen Textfelder
  • Zahlenparameter können Textfelder, Kombinationsfelder oder Drehfelder sein, abhängig von den bekannten Werten, die in einem Bereich oder in freier Form eingeschränkt sind.

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

  • Völlig unterschiedliche Verwendungen werden in Registerkarten unterteilt (z. B. Hinzufügen des Meta-Switches "Commit" zu Git, Änderung des gesamten Satzes erwarteter / zulässiger Switches und Parameter)

Geben Sie hier die Bildbeschreibung ein

  • Sobald die Parameter eingegeben wurden, führt eine Schaltfläche die Aktion aus

Geben Sie hier die Bildbeschreibung ein

Hinweis: Die Eingabevalidierung muss proaktiv sein , dh Sie müssen verhindern, dass der Benutzer die Aktion ausführt, wenn keine obligatorischen Parameter eingegeben wurden, indem Sie die Schaltfläche Ausführen ausgrauen und im Allgemeinen GUI-Elemente ausgraden oder aktivieren, um die ordnungsgemäße Verwendung zu vermitteln. In CLI-Apps führt der Benutzer nur den Befehl aus und erhält eine Fehlermeldung, dh die Validierung ist reaktiv.


1
Sehr guter Rat. Keine Antwort an und für sich, sondern eine großartige "Anleitung" zur Ergänzung der anderen "Was zu tun ist" -Antworten.
Bobson

6

Normalerweise kann dies durch Schreiben eines GUI-Frontends gelöst werden, das eine Befehlszeile erstellt . An diesem Punkt rufen Sie einfach die alte CLI-Funktion "main ()" mit den Argumenten in der entsprechenden Reihenfolge auf.

Was Sie dann tun müssen, hängt von der Ausgabe ab. Sie können dies gut tun, indem Sie alle printf()in eine generische Ausgabevariablenfunktion einschließen, die in der CLI-Version nur die Kontrolle übergibt, printfwährend in der GUI-Version die Ausgabe an ein Scrolldown-Protokollfenster oder ähnliches gesendet wird.

Auf diese Weise bleibt die CLI-Anwendung weitgehend unverändert, und das GUI-Front-End verliert zwar an Effizienz, bleibt jedoch lose gekoppelt und kann unabhängig verwaltet werden (in einigen Fällen kann ein Modell - oder sogar eine echte Alternative zur GUI - unabhängig sein Anwendung , die dann laicht die CLI binär mit den richtigen Argumenten, Art , was Sie mit AutoIt auf Windows, sozusagen tun können).

Dies hängt jedoch stark davon ab, was die Anwendung tatsächlich tut . Dieser Ansatz kann immer noch mehr oder weniger verfolgt werden, aber es kann unangenehm werden, wenn Sie beispielsweise die CLI-Routine zyklisch oder ähnlich ausführen möchten . oder wenn das Programm voraussichtlich mit einem Eingang von arbeiten wird stdin.


Interessante Idee, obwohl ich nicht wirklich den Vorteil sehe, ein Befehlszeilenargument aufzubauen, anstatt nur dieselbe Methode von beiden Stellen aus aufzurufen. Darüber hinaus scheint es seltsam, während des gesamten Lebens des GUI-Programms möglicherweise mehrmals main aufzurufen.
Jhewlett

1
Wenn Sie dies nicht tun, laufen Sie Gefahr, dass die GUI Dinge tun kann, die über eine Befehlszeile nicht möglich sind.
Pieter B

1
@jhewlett, das ist zugegebenermaßen eine Abkürzung. main()selbst sollte kaum mehr als ein Argument-Parsing-Frontend für den "echten" Programmkörper sein. Aber wenn dies der Fall gewesen wäre, wäre die Annahme Ihrer Option (die die beste ist) meiner Meinung nach so einfach gewesen, dass eine Frage überhaupt nicht gerechtfertigt wäre.
LSerni

3

Das erste, was Sie tun möchten, ist, das Back-End (hinter der aktuellen CLI) vom Frontend (der CLI) zu trennen.

Trennen Sie im Wesentlichen die Ansicht / den Controller (CLI) vom Modell, damit der gesamte Funktionscode in ein eigenes eigenständiges Modul aufgeteilt werden kann (das Sie beispielsweise in eine statische Bibliothek kompilieren können).

Dann können Sie die öffentliche C-Schnittstelle dieses Moduls verwenden, um in Ihrer QT-GUI zu codieren

Für die Korrelation der Tastendrücke gibt es in QT eine umfangreiche Signal-Slot-Implementierung, und der QT-Ersteller übernimmt einen Großteil der Bindung für Sie (so einfach wie Rechtsklick-> Gehe zu Slot ...-> geklickt () - > Typ foo())


1

Wenn Ihre aktuelle CLI-Anwendung ein angemessen strukturiertes Eingabe- und Ausgabeformat verwendet (insbesondere die Ausgabe. Sie sollte so strukturiert sein, dass sie von einem Computer analysiert werden kann), können Sie jederzeit eine separate GUI-Anwendung erstellen, die über Pipes und / oder mit der CLI-Anwendung kommuniziert oder temporäre Dateien.

Um die GUI in die aktuelle Anwendung zu integrieren, müssen Sie in der Lage sein, die E / A-Behandlung vollständig vom Rest der Anwendung zu trennen, damit Sie den Teil ohne E / A als Bibliothek erstellen und eine Benutzeroberfläche (entweder) erstellen können GUI oder CLI) dazu. Wenn die ursprüngliche Anwendung nie dafür entwickelt wurde, könnte dies eine schwierige Aufgabe sein, da es so einfach ist, printfAnrufe überall zu verteilen .

Die Tatsache, dass Qt C ++ ist und Ihre Anwendung sich in C befindet, sollte kein großes Hindernis für eine integrierte Anwendung sein, solange die Schnittstelle zum Back-End-Teil in der gemeinsamen Teilmenge von C und C ++ geschrieben ist. Dann müssen Sie nur noch die Lernkurve von C ++ überwinden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.