Code wird zu umständlich
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
phonebook.h
phonebook.cpp
main.cpp
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
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
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
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];
}
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();
}
Gruß
Treehouse
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;
};
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;
};
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
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
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
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
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
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.
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.
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.
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.
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 ...
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 ...