# Einstiegshilfe für Qt-Neuling

## l3u

Hallo an alle Qt-Profis ;-)

Ich bin gerade dabei, mein erstes Qt-Programm zu schreiben (mit PyQt und Python). Da tun sich ja ungeahnte Möglichkeiten auf, die einen leider auch ein bißchen erschlagen … Deswegen bräuchte ich eine kleine Starthilfe, damit ich nicht von Grund auf was falsch mache.

Derzeit macht das Programm noch nicht viel, es gibt eine QListView und ein QLineEdit. Per QPushButton wird der eingegebene Wert, sofern noch nicht vorhanden, an ein QStandardItemModel angehängt, was mit der QListView verknüpft ist.

Jetzt will ich zu jedem solchen Eintrag noch weitere Daten speichern (einmal Integer und einmal Bool). Sicher kann man das ja alles über so ein QStandardItemModel oder QAbstact…sowieso machen.

Jetzt die Frage: wäre es ein arger Frevel, die Daten einfach in einem Python-Array zu speichern, und die ganze Qt-Daten-Sache immer nur als Kopie mit abzugleichen, damit die GUI das selbe anzeigt, was auch in dem Array ist? Wenn ja: wie geht man sowas an? Ich würde gern zu jedem Eintrag eine eindeutige ID speichern und eben einen weiteren Integer- und Bool-Wert. Kann man das auf eine einfache Art und Weise machen, und die graphischen Elemente jeweils nur die Daten rausziehen lassen, die für sie relevant sind? Also z. B. bei der QListView eben nur den Namen des Eintrags?

Ich wäre euch für jede Hilfe echt dankbar :-)

----------

## franzf

 *l3u wrote:*   

> Jetzt will ich zu jedem solchen Eintrag noch weitere Daten speichern (einmal Integer und einmal Bool). Sicher kann man das ja alles über so ein QStandardItemModel oder QAbstact…sowieso machen.

 

QStandardItem::setData(), und als role ein Qt.UserRole + x (x>0) nehmen.

So kannst du dir natürlich auch die ID speichern.

Das mit dem Array geht natürlich auch, aber du musst dann selber schauen dass du die Daten im Model und in deinem Array auch immer brav korrekt abgleichst, sonst kommt es zu Inkonsistenzen und der User wundert sich  :Razz: 

Eine Alternative ist auch noch eine map (glaub das heißt in Python "Dictionary").

Da kannst du dann Paare (StandardItem, MeineDatenKlasse) speichern.

Aber ich würde erstmal versuchen das Problem nur mit dem QStandardItem + setData() zu lösen.

----------

## l3u

Sorry für Anfängerfragen, aber wie würde das denn (als Code) aussehen? Ich hab bisher folgendes:

Das besagte QStandardItemModel:

```
pairs = QtGui.QStandardItemModel()
```

An die QListView dranhängen (die nur den Namen anzeigen soll, nicht die anderen Daten):

```
self.ui.pairsList.setModel(self.pairs)
```

Und so füge ich weitere Einträge hinzu:

```
self.pairs.appendRow(QtGui.QStandardItem(newPairName))
```

Tja, und dann verließen die ihn … der Datensatz, den ich speichern will, würde dann (vermutlich?) so aussehen sollen:

```
|

+--Pair1

|    +--id: 1

|    +--table: 1

|    +--fixed: True

|

+--Pair2

|    +--id: 2

|    +--table: 1

|    +--fixed: False

|

+--Pair3

|    +--id: 3

|    +--table: 2

|    +--fixed: True

|
```

oder zumindest so ähnlich … vielleicht auch ID eine Ebene weiter oben und name als child?

----------

## franzf

 *l3u wrote:*   

> Und so füge ich weitere Einträge hinzu:
> 
> ```
> self.pairs.appendRow(QtGui.QStandardItem(newPairName))
> ```
> ...

 

```
item = QtGui.QStandardItem(newPairName)

item.setData(id, QtCore.Qt.UserRole + 1)

item.setData(table, QtCore.Qt.UserRole + 2)

item.setData(fixed, QtCore.Qt.UserRole + 3)

self.pairs.appendRow(item)
```

Wobei natürlich id, table und fixed die Werte sind, die dann an jener Stelle gespeichert werden sollen.

Wenn du dann später auf ein SIGNAL reagierst kommst du an die Daten mit index.data( QtCore.Qt.UserRole + 1 ) usw. ran.

Hoffe das hilft dir.

Ciao

Franz

----------

## l3u

Ich krieg's nicht gebacken …

http://l3u.de/pub/muckturnier.tar.gz – das ist das, was ich bisher hinbekommen hab. Was das Programm soweit können soll, erklärt die GUI denk ich ganz gut … was es bisher kann, ist, die QListView um Einträge zu erweitern.

Wär echt klasse, wenn mir jemand (mittels ein paar Zeilen Code ;-) erklären könnte, wie ich folgendes hinbekomme: Paare eingeben geht ja schon. Wenn man in der QListView ein Paar auswählt, soll man eben noch die Tischnummer eingeben und eben ggf. ein Häkchen für "fest" setzen können. Und referenzieren sollte man die Daten denke ich am besten nicht über den Namen, sondern über irgend eine ID, damit man den Namen auch ändern kann.

Qt ist derzeit noch ein Buch mit sieben Siegeln für mich … aber ich hoffe mal, daß ich mir den Rest erschließen kann, wenn ich sehe, wie man das mit den Daten für die Paare hinbekommt.

Also falls einer von euch Lust hat, mir bißchen unter die Arme zu greifen … ;-)

Weil ich denk, wenn ich die Daten einfach in Python-Dictionarys speichern würde, und diese Qt-Datenklassen nur für die GUI benutzen würde … dann würde ich's zwar hinkriegen, aber das wär ja nicht ganz im Sinne des Erfinders, oder?

----------

## franzf

Das mit dem Anclicken ist gleich getan:

```
self.ui.pairsList.clicked.connect(self.editPair)
```

editPair ist dann eine Methode:

```
def editPair(self, index):

    pairName = index.data(QtCore.Qt.DisplayRole)

    fixed = index.data(QtCore.Qt.UserRole + <fixedOffset> # hier dann den Index wählen für den du dein fixed setzen willst.

    # usw.
```

Die ausgelesenen Werte gibst du dann in dein Formular. Den Index musst du nicht nochmal ermitteln, das ist self.ui.pairsList.currentIndex().

Prinzipiell nehme ich an du willst die eingegebenen Daten auch mal abspeichern.

Wie wäre es mit der Kombination QTableView + QSqlTableModel (incl. QSQLITE Datenbank).

Zum Editieren einfach einen QDataWidgetMapper nehmen und du musst dich um fast gar nix mehr kümmern  :Wink: 

Und das ist gefährlich:

```
class Muckturnier(QtGui.QMainWindow):

   # The pairs list

   pairs = QtGui.QStandardItemModel() # Achtung Klassenvariable == statisch != self.pairs
```

----------

## l3u

Okay, mit

```
self.ui.pairsList.clicked.connect(self.displayPairData)
```

und

```
   def displayPairData(self, index):

      self.ui.pairName.setText(index.data(QtCore.Qt.DisplayRole).toString())

      self.ui.pairTable.setText(index.data(QtCore.Qt.UserRole + 1).toString())

      self.ui.pairTableFixed.setCheckState(int(index.data(QtCore.Qt.UserRole + 2).toString()))
```

kommen die Daten jetzt tatsächlich in die entsprechenden Felder bzw. die Checkbox. Aber wie kann ich sie wieder in das Datenfeld schreiben (bei einem Klick auf den Speichern-Knopf)?!

Ist Qt echt so dermaßen kompliziert? Ich hab ja doch schon einiges programmiert, aber da blick ich einfach nicht durch … Kann man sich nicht einfach die item-Nummer des ausgewählten Eintrags holen?

----------

## franzf

 *l3u wrote:*   

> Okay, mit
> 
> ```
> self.ui.pairsList.clicked.connect(self.displayPairData)
> ```
> ...

 

```
self.ui.saveButton.clicked.connect(self.saveCurrent)

def saveCurrent( self ):

  index = self.pairsList.currentIndex()

  self.parisList.setData(index, self.ui.pairName.text(), QtCore.Qt.DisplayRole)

  # usw.
```

Sollte gehen.

Du kannst dir von index auch row und column nehmen und ein komplett neues QStandardItem einfügen.

Als Alternative gäbe es noch QListWidget + QListWIdgetItems,da musst du nicht mit dem wahrscheinlich ungewohnten QModelIndex hantieren, da senden die SIGNALS gleich QListWidgetItems durch die Gegend, vllt. kommst du damit besser zurecht.

----------

## l3u

Hat funktioniert, danke :-) Ist aber schon wirklich alles bissl ungewohnt …

Könnte ich eigentlich das Datenfeld auch von einem QTableView (oder QTableWidget?!) anzeigen lassen? Also eine Spalte Name, eine Tischnummer, eine Fixed? Oder bräuchte man dazu dann ein ganz anderes Datenmodell? Wenn ich das Datenfeld mit einem QTableView verknüpfe, dann wird nur der Name angezeigt.

Bei nochmaligem Überlegen könnte man sich ja die Eingabemaske sparen, das QTableView kann man ja direkt editieren! Ich war beim Überlegen, wie ich die Oberfläche gestalten soll, gedanklich noch bei "Wie würde ich es mit PHP bei einer Client-Server-Anwendung machen?" ;-)

Gibt es eigentlich irgend eine Einführung in Qt, die solche grundsätzlichen Sachen erklärt? Also z. B. wie krieg ich Daten in eine solche Tabelle, wie krieg ich sie wieder raus und wie kann ich sie ändern? Ich finde immer nur diese Klassenreferenzen, und daraus werd ich teilweise nicht so ganz schlau ...

(Nochmal tausend Dank für die Hilfe :-)

----------

## firefly

Wenn du in der Klassen referenz auf den link more klickst dann kommt eine Beschreibung zum Teil mit Beispielen.

Für QTableView: http://qt.nokia.com/doc/4.6/qtableview.html#details

und QTableWidget: http://qt.nokia.com/doc/4.6/qtablewidget.html#details

und generell für Model/View: http://qt.nokia.com/doc/4.6/model-view-programming.html

----------

## franzf

 *l3u wrote:*   

> Gibt es eigentlich irgend eine Einführung in Qt, die solche grundsätzlichen Sachen erklärt? Also z. B. wie krieg ich Daten in eine solche Tabelle, wie krieg ich sie wieder raus und wie kann ich sie ändern? Ich finde immer nur diese Klassenreferenzen, und daraus werd ich teilweise nicht so ganz schlau ...

 

Also, eine Einführung in der Art "welches widget/welche view/melches model/..." verwende ich für Aufgabenstellung XYZ kenn ich jetzt nicht.

Prinzipiell überlegst du wie spezialisiert deine Ansicht werden soll. Wenn du einfach in einer Tabelle ein paar Daten anzeigen willst dann fährst du mit Q[Table, List, ...]Widget denke ich besser. Sobald aber etwas mehr hinter der Beschaffung/Speicherung der Daten steht fährst du mit nem Model besser.

Schau mal hier:

http://qt.nokia.com/doc/4.6/qabstractitemmodel.html

Und click dich durch soweit du willst bei "inherited by", dann weißt du für was es alles schon fertige Models gibt. 

In deinem Fall denke ich ist es richtig praktisch gleich auf das "QSqlTableModel" aufzuspringen.

http://qt.nokia.com/doc/4.6/qsqltablemodel.html

Tabellenname angeben und fertig! Du brauchst dich um eigentlich gar nix mehr kümmern, nur um das Erstellen der Datenbank. Da wird ein kleines SQLITE-File reichen.

Ich werd mal schauen, dass ich ein kleines Beispiel in Python zusammenschreib, dass du ne Orientierung hast.

----------

## franzf

Da muss ich ja gar nix selber schreiben  :Razz: 

Gibts schon im PyQt4-tar unter "examples/sql"  :Smile: 

Das sollte auch eine wahre Schatztruhe für Anregungen sein, also stöbern, starten, staunen...

----------

