Anzeige:
Ergebnis 1 bis 7 von 7

Thema: Qt: Gui von Hauptprogramm trennen

  1. #1
    Registrierter Benutzer Avatar von Sector1379
    Registriert seit
    04.10.2005
    Ort
    KR
    Beiträge
    89

    Qt: Gui von Hauptprogramm trennen

    Hallo zusammen,

    ich fange gerade erst an mit GUI Programmierung, aber ich habe eine Frage bei der ich einfach nicht weiter komme. Unzwar wie Programmiert man eine GUI (also bei mir aktuell QT) und trennt diese von Hauptprogramm ?????

    Ich habe schon alles abgesucht nach Informationen aber ich blick einfach nicht druch wie ich das machen soll. Z.b muss ich doch an die connects andocken mit funktionen.

    Da kann ich doch gar nicht ohne Hauptprogramm arbeiten, den genau das stellt mir ja die function bereit................ also wie ihr seht scheine ich das was grundlegendes nicht verstanden zu haben und ich fände es spitze wenn mir vielleicht einer von euch an einen kleinen beispiel zeigen könnte was man genau darunter versteht..........
    Gruß Sector

  2. #2
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Damit ist nicht gemeint, dass Hauptprogramm und GUI nicht gegenseitig Funktionen aufrufen, sondern dass sie beide, oder zumindest der Hauptteil, nicht weiß, wessen Funktionen er aufruft.

    D.h. man kann die GUI austauschen, ohne am Hauptteil etwas ändern zu müssen.

    Bei Qt kann man das relativ leicht mit Signals&Slots machen, d.h. wenn der Kern eine Interaktion mit dem Benutzer wünscht, sendet er ein entsprechende Signal aus. Dabei ist dem Kern dann egal, an welche Art von GUI du das Signal verbunden hast.

    Allgemeinere Möglichkeiten sind abstrakte Klassen bzw. Interfaces als Schnittstellen, d.h. man hat eine Klasse mit virtuellen Methoden und der Kern macht an einem Objekt, da von dieser Klasse ableitet, seine Aufrufe, ohne wissen zu müssen, welche Klasse das Objekt konkret ist.

    Beispiel:
    Code:
    class MessageHandler
    {
    public:
        virtual void showMessage(const QString& message) = 0;
    };
    
    class Kern
    {
    public:
        void registerMessageHandler(MessageHandler* handler) { m_messageHandler = handler; }
    
        void foo() { m_messageHandler->showMessage("foo() called"); }
    private:
        MessageHandler* m_messageHandler;
    };
    
    class QtMessageHandler : public QTextEdit, public MessageHandler
    {
    public:
        virtual void showMessage(const QString& message)
        {
            append(message);
        }
    };
    
    class ConsoleMessageHandler : public MessageHandler
    {
        virtual void showMessage(const QString& message)
        {
            std::cout << message.local8Bit().data << std::endl;
        }
    };
    // irgendwo im Programm
    Kern kern;
    
    QtMessageHandler handler1;
    
    kern.registerMessageHandler(&handler1);
    kern.foo();
    
    ConsoleMessageHandler handler2;
    
    kern.registerMessageHandler(&handler2);
    kern.foo();
    Die Klasse Kern ist dabei von der GUI abgekoppelt, weil sie mit dem Interface MessageHandler arbeitet, das beliebigt implementiert sein kann

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  3. #3
    Registrierter Benutzer Avatar von Sector1379
    Registriert seit
    04.10.2005
    Ort
    KR
    Beiträge
    89
    Vielen vielen dank für die tolle erklärung
    Ich habe mich mal dran gemacht und ein mini programm geschrieben an dem ich dich mal fragen wollte ob ich alles richtig verstanden habe. Das Programm ist super simpel
    es soll einfach ein text eingegeben werden und dieser wird eingelesen und dann in der unteren Zeile ausgegeben. Hier mal der Code:

    Gui.h
    Code:
    #ifndef _GUI_
    #define _GUI_
    #include <QApplication>
    #include <QFont>
    #include <QPushButton>
    #include <QGridLayout>
    #include <QWidget>
    #include <QLineEdit>
    #include <QLabel>
    #include <QString>
    #include "func.h"
    
    class QtGui: public QWidget, public Func{
    
      Q_OBJECT
    
      public:
      
      QtGui(QWidget *parent = 0);
    
      private slots:
      void getInput();
    
     private:
      QPushButton *quit;
      QPushButton *read;
      QGridLayout *layout;
      QLineEdit *in;
      QLineEdit *out;
      QLabel *name_in;
      QLabel *name_out;
    };
    
    #endif
    Gui.cpp
    Code:
    #include "Gui.h"
    
    QtGui::QtGui(QWidget *parent)
      :QWidget(parent), Func()
    {
    
      quit = new QPushButton(tr("Quit"));
      connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
    
      read = new QPushButton(tr("Read"));
      connect(read, SIGNAL(clicked()), this, SLOT(getInput()));
    
      in = new QLineEdit;
      out = new QLineEdit;
    
      name_in = new QLabel("IN:");
      name_out = new QLabel("OUT:");
    
      layout = new QGridLayout;
      layout->addWidget(name_in, 0, 0);
      layout->addWidget(in, 0, 1);
      layout->addWidget(name_out, 1, 0);
      layout->addWidget(out, 1, 1);
      layout->addWidget(read, 2, 0); 
      layout->addWidget(quit, 2, 1);
      setLayout(layout);
    
    }
    
    void QtGui::getInput(){
    
      QString te;
      const char *huh;
    
      te = in->text();  
      QByteArray ba = te.toLatin1();
      huh = ba.data();
      setTex(huh);
      out->setText(getText());
    }
    Func.h
    Code:
    #ifndef _FUNC_
    #define _FUNC_
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Func{
    
     public:
      Func();
      char *getText();
      void setTex(const char *te);
    
     private:
    
      char *text;
    
    
    };
    
    #endif
    Func.cpp
    Code:
    #include "func.h"
    
    using namespace std;
    
    Func::Func(){
    }
    
    char* Func::getText(){
    
      return text;
    
    }
    
    void Func::setTex(const char *te){
    
      int len = strlen(te) + 1;
      text = new char[len];
      strcpy(text, te);
    }
    main.cpp
    Code:
    #include "Gui.h"
    #include <iostream>
    #include <string>
    #include "func.h"
    
    using namespace std;
    
    int main(int argc, char **argv){
    
      QApplication app(argc, argv);
      QtGui trennen;
    
      trennen.show();
    
    
      return app.exec();
    }

    So wie man unschwer erkennen kann ist es wirklich nix wildes was ich da gemacht habe, mir gehts halt nur ums prinzip und das ich das wirklich verstehe.

    Also die Func Klasse stellt bei mir die Kern klasse da diese soll nicht verändert werden. Die Gui ist klar greift auf die funktionen von Func zurück und in der main wird nur ein Object nämlich die gui erstellt und damit hat man dann alle funktionalitäten.

    Ist das so von mir richtig aufgefasst worden oder hätte ich anstatt der vererbung lieber eine delegation machen sollen ????
    Gruß Sector

  4. #4
    Registrierter Benutzer
    Registriert seit
    18.03.2005
    Beiträge
    211
    Unzwar wie Programmiert man eine GUI (also bei mir aktuell QT) und trennt diese von Hauptprogramm ?????
    Das solltest DU mal genauer erlaeutern, was genau Du meinst !

    Richtig "Trennen" kann man Hauptprogramm und GUI ned wirklich, weil die GUI zeigt (zumindest sollte normalereise es so sein) Inhalte aus dem Hauptprogramm an :-)

    Trennen wird eher im Sinne von Abstraktion verwendet.

    Trennen kann man auf executable Sicht sehen .... du hasst unterschiedliche executables.
    Beispiel eine LAMP anwendung
    - Datenbank(mysql daemon)
    - Apache mit php / perl / java engine (Logic - Schicht) (apache daemon)
    - Browser mit oder ohne Java / php script erweiterung (mozilla, oder IExplorer.exe )
    in dem falle koennten sogar alle 3 komponenten auf unterschiedlichen rechnern laufen. Verbunden sind sie soweiso immer, in dem fall ueber IPC Protokolle (TCP/IP - HTML).

    Man kann es aber auch Sicht von Uebersetzungseinheiten .... Sprich du hasst fuer die Datenhaltung / Logic / GUI unterschiedliche Module, die du austauschen kannst. Die Module werden dann klassischerweisse(also meistens) als shared Objects / dlls (InProzess) ausgefuhrt, executable hasst du nur noch eines, und das laed sich die module zu, verbunden sind die Schichten dann nur noch ueber (hoffentlich abstrakte) Schnittstellen.
    Wobei Externe Prozesse (ExtProzess) Loesungen (wie 1. Beispiel) natuerlich auch module sind.


    Von Trennung redet man auch, wenn man auch nur saubere Schnittstellen (abstract) einfuehrt (meist aber dann soweiso mit einer Modularisierung im hintergrund).

    Frueher in der Informatik redete man oft vom 3 Schicht Modell, nicht zuverwechseln mit dem gleichnamigen Modell zur Altersvorsorge unserer Bundesregierung :-) und dem OSI Modell .
    Viel spass beim googeln :-)

    Ciao ...
    Geändert von RHBaum (13-06-2007 um 14:47 Uhr)

  5. #5
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von Sector1379 Beitrag anzeigen
    Ist das so von mir richtig aufgefasst worden oder hätte ich anstatt der vererbung lieber eine delegation machen sollen ????
    Ja, wäre besser.

    Es könnte zum Beispiel einen Zeitpunkt geben, wo du "Func" auch gerne als QObject haben möchtest und dann geht auf einmal die Ableitung nicht mehr, weil man nicht zweimal von QObject ableiten darf.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  6. #6
    Registrierter Benutzer Avatar von Sector1379
    Registriert seit
    04.10.2005
    Ort
    KR
    Beiträge
    89
    Hi anda,

    sag mal ist es eigentlich generell besser eine Delegation zu machen. Ich meine mal mit bekommen zu haben das es besser ist für die Speicherverwaltung.

    Kannst du das bestätigen oder kommt das immer drauf an ??
    Gruß Sector

  7. #7
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Das ist Software Entwicklung, da gibt es keine generell richtigen Sachen

    Eine Delegation hat z.B. den Nachteil, eine Indirektion zu sein, könnte also teilweise bischen weniger performant werden (allerdings normalerweise vernachlässigbar)

    Ein gute Richtwert ist, keine Ableitung zu machen, wenn man es nur wegen dem Benutzen von Funktionalität gemacht hätte.

    In deinem Beispiel verbietet sich die Ableitung, weil das praktisch das Gegenteil von der als Ziel gesetzten Trennung ist.

    Eine Delegation erlaubt dir auch, den Zeitpunkt der Erzeugung anders zu variieren, d.h. du hast dann zum Beispiel die Möglichkeit, ein leeres Hauptfenster zu erzeugen und sofort anzuzeigen und erst danach Schrittweise den Kern bzw. mehrere Kernkomponenten.

    Aber er ist natürlich mehr Aufwand, daher kann man, meiner Meinung nach, keine allgemeine Richtigkeit draus machen.

    Hängt ja auch davon ab, ob man nur schnell einen Prototyp braucht, oder an etwas arbeitet, was dann lange erweiterbar und wartbar sein soll.

    Beim Thema Softwarearchitektur sollte man immer sowohl Vorteile als auch Nachteile von Lösungmöglichkeiten betrachten.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •