Code wird zu umständlich

Verschiedenes zu Qt
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

Ich verstehe jetzt nicht, was Du mit Gui und Funktionen meinst, zeig mal bitte Deine Klassenhierarchie, dann kann man Dir besser helfen...
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Also dann will ich mal. Ich wollte z.b für mich ein kleines Telefonbuch schreiben nix wildes aber daran wollte ich halt Qt lernen und üben. Es ist aber wirklich noch die absolute Rohfassung also kommt noch einiges. Aber es geht ja erst mal um das Prinzip. Hier also die Files so wie sie bis jetzt sind.

setForm.h

Code: Alles auswählen

/********************************************************************************
** Form generated from reading ui file 'setForm.ui'
**
** Created: Wed Jun 27 01:51:21 2007
**      by: Qt User Interface Compiler version 4.3.0
**
** WARNING! All changes made in this file will be lost when recompiling ui file!
********************************************************************************/

#ifndef SETFORM_H
#define SETFORM_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QGroupBox>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QListWidget>
#include <QtGui/QPushButton>
#include <QtGui/QTextBrowser>
#include <QtGui/QWidget>

class Ui_setForm
{
public:
    QListWidget *listNames;
    QLineEdit *searchLine;
    QLabel *label;
    QGroupBox *groupBox;
    QPushButton *addButton;
    QPushButton *deleteButton;
    QPushButton *quitButton;
    QTextBrowser *information;

    void setupUi(QWidget *setForm)
    {
    if (setForm->objectName().isEmpty())
        setForm->setObjectName(QString::fromUtf8("setForm"));
    setForm->setEnabled(true);
    QSize size(748, 505);
    size = size.expandedTo(setForm->minimumSizeHint());
    setForm->resize(size);
    setForm->setWindowIcon(QIcon(QString::fromUtf8("kview.png")));
    listNames = new QListWidget(setForm);
    listNames->setObjectName(QString::fromUtf8("listNames"));
    listNames->setGeometry(QRect(20, 70, 221, 421));
    searchLine = new QLineEdit(setForm);
    searchLine->setObjectName(QString::fromUtf8("searchLine"));
    searchLine->setGeometry(QRect(20, 30, 221, 23));
    label = new QLabel(setForm);
    label->setObjectName(QString::fromUtf8("label"));
    label->setGeometry(QRect(20, 10, 91, 18));
    groupBox = new QGroupBox(setForm);
    groupBox->setObjectName(QString::fromUtf8("groupBox"));
    groupBox->setGeometry(QRect(630, 60, 101, 161));
    groupBox->setFlat(false);
    addButton = new QPushButton(groupBox);
    addButton->setObjectName(QString::fromUtf8("addButton"));
    addButton->setGeometry(QRect(10, 30, 83, 27));
    deleteButton = new QPushButton(groupBox);
    deleteButton->setObjectName(QString::fromUtf8("deleteButton"));
    deleteButton->setGeometry(QRect(10, 70, 83, 27));
    quitButton = new QPushButton(groupBox);
    quitButton->setObjectName(QString::fromUtf8("quitButton"));
    quitButton->setGeometry(QRect(10, 110, 83, 27));
    information = new QTextBrowser(setForm);
    information->setObjectName(QString::fromUtf8("information"));
    information->setGeometry(QRect(260, 70, 361, 421));
    label->setBuddy(searchLine);

    retranslateUi(setForm);
    QObject::connect(quitButton, SIGNAL(clicked()), setForm, SLOT(close()));

    QMetaObject::connectSlotsByName(setForm);
    } // setupUi

    void retranslateUi(QWidget *setForm)
    {
    setForm->setWindowTitle(QApplication::translate("setForm", "Phonebook", 0, QApplication::UnicodeUTF8));
    label->setText(QApplication::translate("setForm", "&Searching:", 0, QApplication::UnicodeUTF8));
    groupBox->setTitle(QApplication::translate("setForm", " Options ", 0, QApplication::UnicodeUTF8));
    addButton->setText(QApplication::translate("setForm", "&Add", 0, QApplication::UnicodeUTF8));
    deleteButton->setText(QApplication::translate("setForm", "&Delete", 0, QApplication::UnicodeUTF8));
    quitButton->setText(QApplication::translate("setForm", "&Quit", 0, QApplication::UnicodeUTF8));
    Q_UNUSED(setForm);
    } // retranslateUi

};

namespace Ui {
    class setForm: public Ui_setForm {};
} // namespace Ui

#endif // SETFORM_H
phonebook.h

Code: Alles auswählen

#ifndef _MAINWINDOW_
#define _MAINWINDOW_

#include "setForm.h"
#include <QStringList>
#include <QDebug>
#include <QString>
#include <QFile>
#include <QDataStream>
#include <QTextStream>
#include <QMultiMap>
#include <QVector>
#include <QStringList>
#include <QMap>

using namespace std;

class Phonebook: public QWidget, private Ui::setForm{


  Q_OBJECT

  public:
  
  Phonebook(QWidget *parent = 0);
  ~Phonebook();
  void fillList(); 
  void formatText(QString *out, QStringList &list);
  
  private:

  QFile file;
  QTextStream stream;
  QMultiMap<QString, QStringList> book;
  QString line;

  public slots:
  void display(QListWidgetItem *);
  

};
#endif
phonebook.cpp

Code: Alles auswählen

#include "phonebook.h"

using namespace std;

Phonebook::Phonebook(QWidget *parent):QWidget(parent){

  setupUi(this);
  fillList();
  connect(listNames, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(display(QListWidgetItem *)));

}

Phonebook::~Phonebook(){
  book.clear();
}

void Phonebook::fillList(){

  QStringList list;

  file.setFileName("file.dat");
  file.open(QIODevice::ReadWrite);
  stream.setDevice(&file);

  while(!stream.atEnd()){
  line = stream.readLine();
  list = line.split(";");
  listNames->addItem(list[0]);
  book.insert(list[0], list);
  }
  
}

void Phonebook::display(QListWidgetItem *item){

  QMap<QString, QStringList>::iterator itr = book.find(item->text());
  QStringList list = itr.value();
  QTextStream stream;
  QString out;
  formatText(&out , list);
  information->setHtml(out);
}

void Phonebook::formatText(QString *out, QStringList &list){

  QTextStream stream(out);

  stream << "<h3></h3><b><center><font size=5>" << list[0] <<  "</font></center></b><h5></h5>";
  stream << "<br><b><big>Strasse: </big></b>" << list[1];
  stream << "<br><b><big>Ort:     </big></b>" << list[2];
  stream << "<br><b><big>Email:   </big></b>" << list[3];
  stream << "<br><b><big>Telefon: </big></b>" << list[4];
  stream << "<br><b><big>Telefon 2: </big></b>" << list[5];
  stream << "<br><b><big>Handy: </big></b>" << list[6];
  stream << "<br><b><big>Fax: </big></b>" << list[7];
  stream << "<br><b><big>Homepage: </big></b>" << list[8];
}
main.cpp

Code: Alles auswählen

#include "phonebook.h"

using namespace std;

int main(int argc, char **argv){

  QApplication app(argc, argv);

  Phonebook window;

  window.show();


  return app.exec();
}
So das ist das Prinzip so wie ich es jetzt verstanden habe. Also eine Klasse für die Gui und eine für die Hauptfunktionen, Slots etc.

Gruß

Treehouse
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

Na gut, in diesem Kontext gibt es eigentlich nur eine Klasse - Phonebook.

Ui::setForm wurde generiert und spielt architektonisch keine Rolle. Also was soll in diesem Code (weg)optimiert werden?



Beser wäre es wenigstens die Datenbehandlung rauszunehmen:

class PhoneBook
{
public:

PhoneBook();
PhoneBook(const PhoneBook&);
virtual ~PhoneBook();

friend QDataStream& operator << (QDataStream& stream, const PhoneBook& data);
friend QDataStream& operator >> (QDataStream& stream, const PhoneBook& data);

QMultiMap<QString, QStringList> book;
};



class PhoneBookGui : public QWidget, private Ui::setForm
{
void setPhoneBook(const PhoneBookData& book);
const PhoneBookData& phoneBook(const PhoneBookData& book) const;


// usw.

private:
PhoneBook m_phoneBook;
};
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Hi lepsai

Darum gings ja auch nicht was da opimiert werden soll. Ich wollte lediglich wissen ob man das so macht mit der Trennung von Gui und kernfunktionen. Weil ich dieses Prinzip nicht ganz verstanden habe wie das unter Qt laufen soll.

Das war meine ursprüngliche frage und darauf hin habe ich den Code gepostet um zu fragen ob ich das richtig verstanden habe das man das so macht.

Ich habe mir übrigens das observer pattern angesehen. Angeblich soll das sogar schon in QT intregiert sein. Aber ich muss ehrlich zugeben das ich das nicht verstanden habe wie das dann abläuft.

Gruß

Treehouse
NoobSaibot
Beiträge: 99
Registriert: 27. Januar 2005 15:55

Beitrag von NoobSaibot »

das ganze Qt Framework ist nach den bekannten design patterns aufgebaut, connect() bedient sich des observer patterns. es gibt sehr viele frameworks die die design patterns umsetzen.

das heißt jedoch nicht, daß das ganze auch framework übergreifend funktionieren *muß*.
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

na gut, Signal/Slot-Konzept kann man nur auf einer ganz abstrakten Ebene als Observer/Observable Pattern betrachten. Aber es spricht nichts gegen eine C++-Variante von diesem Pattern, was nicht die Nachteile von Signal/Slot-Konzept hat... Wie man das umsetzt ist z.B. in Wikipedia ausreichend beschrieben.
NoobSaibot
Beiträge: 99
Registriert: 27. Januar 2005 15:55

Beitrag von NoobSaibot »

wieso es nur auf einer ganz abstrakten ebene betrachtet werden kann leuchtet mir nicht ein. erklär bitte.

es gibt natürlich auch eine andere implementierung, und zwar die der boost bibliothek. im vergleich zu Qts signal/slot umsetzung gibt es da vorteile aber auch wieder nachteile.

boost-signals-slots-with-qt
a deeper look at signals and slots
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

na ja, Observer/Observable Pattern dient letztendlich der KONTROLLIERTEN Benachrichtigung über Änderungen von Daten an die angebundenen Beobachter. Im Signal/Slot-Konzept (welches, übrigens auch nicht dazu gedacht war) gibt es keine Definition von Controller, also jener Komponente, die Verbindung zwischen Observable und Observer herstellt und trennt. Schlimmer noch, es ist ohne weiteres möglich an jeder Stelle des Programms in diese Verbindung einzugreifen (verbinden, trennen). Ein Observer könnte sich z.B. auch selbst mit dem Model verbinden. Es gibt letztendlich keine Abstraktionen in Qt, die Model und Observer beschreiben, so gibt es also viele Misbrauchmöglichkeiten. Desweitern gibt es bei Signals/Slots im Gegensatz zu einer C++-Implementierung, keine eindeutige Schnittstelle, um z.B. auf Model-Änderungen zu reagieren, etwa in der Form:


void MyObserverImpl::onUpdate(const AbstractObservable& model)
{
// update my GUI
}

All das macht eine direkte Anwendung von Signal/Slot-Konzept für Observer-Pattern aus meiner Sicht eher ungünstig und fehleranfällig, aber selbstverständlich nicht unmöglich.
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Also mit anderen Worten sollte man selber das Observer Pattern schreiben und dann auf die Gui und daten anwenden ??

Habe ich dich da richtig verstanden.............
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

Treehouse hat geschrieben:Also mit anderen Worten sollte man selber das Observer Pattern schreiben und dann auf die Gui und daten anwenden ??

Habe ich dich da richtig verstanden.............
Absolut richtig.
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Also heißt das auch das ich nicht die Signal Slot methode von Qt verwenden soll sondern lieber das was ich selber geschrieben habe ?

Ist das nicht so ein bisschen das Rad neu erfinden ............. also ich sehe gerade nicht so denn sinn darin alles selber zu schreiben wenn es das schon gibt und sogar zum Toolkit gehört.

Sag doch mal ein klares beispiel an wo das einem so richtig nutzen bringt.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

DU musst halt ganz klar trennen, von wo deine funktionalitaet kommt !

Also irgendwer aendert am Datensatz X, oder besser an Object X deiner DatenHaltungs-Schicht, irgend ein Attribut , und im Datensatz Y muss sich dann zwangslaeufig Auch ein Attribut aendern, so ist das tiefstes Problem der Datenhaltungsschicht. die verknuepfung zwischen den beiden aenderungen sollte natuerlich nicht ueber QT signale (GUI framework) oder sowas laufen.
Aber um diese aenderung zu visualisieren koennte die datenhaltung eine Art Event (meistens Callback oder Abstrakte Listener Klasse) "senden" ... wo dann die GUI (also QT) sich eingeklinkt hat, und daraus ein QT SIgnal erzeugt, worauf die wildesten GUI Anederungen erfolgen koennten.

Wir machen das hier auch so .... Die tieferen Biblotheken sind reines C / C++ Also benutzen wir da je nachdem dll's mit flachen c schnittstellen (callbacks funktionspointer), hat den vorteil der kompilerunabhaengigkeit, oder C++ mit pure abstract Interface Klassen ... da muessen die compiler fuer die komponenten (Dlls / exe) zueinander kompatibel sein.

Als strings werden prinzipiell nur c-Strings verwendet, also char * , oder wchar_t * . STL klassen ueber DLL grenzen hinweg ist sowieso keine gute Idee.

Fuer die ganzen konvertierungen haben wir nen ganzen satz an Adapter klassen (meist templates) wo wir in 1-2 Zeilen die konvertierungen abhaken koennen.
Viele hilfsfunktionen fuer strings z.b. sind als templates ausgelegt, und gehen dann mit std::strings und QT gleichermassen, um nicht unnoetig konvertieren zu muessen.
Einige wenige biblios (statische, also .lib) gibt es als std:: und als QT variante.

Wenn Du wirklich modular Programmieren willst, und generische Programmteile schreiben willst, wirst um diesen aufwand ned wirklich herumkommen. Wobei templates einem da die arbeit ungemein erleichtern.

Ciao ...
Antworten