Discussion:
[Python-de] POython QT und Listen
Stefan Miefert
2005-08-05 15:17:50 UTC
Permalink
Hallo,

ich habe eine QT Listbox. Darin speicher ich z.B. Mitarbeiternamen. Da
ich diese aber einmalig über eine ID in der DB identifiziere muss ich
eine parallele List emit diesen IDs verwalten

Solang die Listeneu geladen wird geht das auch aber wenn ich jetzt ein
Element entferne oder hinzufüge wird die interne Nummerierung der
Listbox durcheinader geworfen

z.B.

ListBox
Nr. Wert:
1 Michael
2 Markus
3 Thomas
4 Horst
5 Sabine
6 Karin
7 John
8 Bernd

Eine Liste wäre ungefähr so aufgebaut


mitarbeiter[1]= 105
mitarbeiter[2]= 366
mitarbeiter[3]= 15
mitarbeiter[4]= 66
u.s.w.

Wenn ich jetzt mit removeItem aus der Listbox einen Eintrag entferne
wird die Nummern kaum nachvollziehbar neu nummeriert udn die Verbindung
der beiden Datensätze ist wech:(

In HTML z.B. kann man für jeden Eintrag einen Namen udn einen Wert
speichern. Das machtd as ganze sehr komfortabel:(

Wie kann ich das trpotzdem verwalten?

Anfänglich habe ich die ganze Liste neu geladen aber das geht aus
Geschwindigkeitsgründen nicht mehr bei ca 1000 Einträgen
Uwe Tapper
2005-08-05 15:41:07 UTC
Permalink
Moin,
Post by Stefan Miefert
Hallo,
ich habe eine QT Listbox. Darin speicher ich z.B. Mitarbeiternamen. Da
ich diese aber einmalig über eine ID in der DB identifiziere muss ich
eine parallele List emit diesen IDs verwalten
...
In HTML z.B. kann man für jeden Eintrag einen Namen udn einen Wert
speichern. Das machtd as ganze sehr komfortabel:(
Wie kann ich das trpotzdem verwalten?
grobe Skizze: Du leitest von QListBoxItem eine eigene Klasse ab, die
dann ein zusaetzliches Attribut bekommt - einen Schluessel fuer den
Datenbank z.B.

Durch das "Speichern" der Schluessel in der ListBox sparst Du Dir die
parallel gefuehrte Liste - und die damit verbundenen Probleme.

Viele Gruesse

Uwe
Andreas Pakulat
2005-08-05 15:46:44 UTC
Permalink
Solang die Listeneu geladen wird geht das auch aber wenn ich jetzt ein Element
entferne oder hinzufüge wird die interne Nummerierung der Listbox durcheinader
geworfen
Eine Liste wäre ungefähr so aufgebaut
mitarbeiter[1]= 105
mitarbeiter[2]= 366
mitarbeiter[3]= 15
mitarbeiter[4]= 66
u.s.w.
Wenn ich jetzt mit removeItem aus der Listbox einen Eintrag entferne wird die
Nummern kaum nachvollziehbar neu nummeriert udn die Verbindung der beiden
Datensätze ist wech:(
Dann benutze doch statt einer Liste ein Dict fuer die DB-Id's und als
Schluessel die Mitarbeiternamen, statt den Nummern. Dann kann dir die
Reihenfolge egal sein, du kommst mit mitarbeiter['klaus'] immer auf die
richtige Id.

Andreas
--
Perfect day for scrubbing the floor and other exciting things.
Diez B. Roggisch
2005-08-05 15:57:44 UTC
Permalink
Post by Stefan Miefert
Wenn ich jetzt mit removeItem aus der Listbox einen Eintrag entferne
wird die Nummern kaum nachvollziehbar neu nummeriert udn die Verbindung
der beiden Datensätze ist wech:(
In HTML z.B. kann man für jeden Eintrag einen Namen udn einen Wert
speichern. Das machtd as ganze sehr komfortabel:(
Wie kann ich das trpotzdem verwalten?
item = QListViewItem(...)
item.mitarbeiternummer = 100

So einfach.

Diez
Stefan Miefert
2005-08-08 18:43:08 UTC
Permalink
Post by Diez B. Roggisch
item = QListViewItem(...)
item.mitarbeiternummer = 100
So einfach.
Hallo,

bei mir ist das nicht so einfach:)

Ich habe es so versucht
item = QListBoxItem(self.listBoxMitarbeiter)
item.MITARBEITERID = row["MAID"]
item.setText="Alles ok"

Da passiert aber nix. Keine EInträge werden angezeigt

Wenn ich jetzt das aufrufe

item.paint()

bekomme ich einen Fehler:

TypeError: Insufficient number of arguments to QListBoxItem.paint()

Welcher Wert muss da übergeben werden ?
Andreas Pakulat
2005-08-08 19:43:13 UTC
Permalink
Post by Stefan Miefert
Post by Diez B. Roggisch
item = QListViewItem(...)
item.mitarbeiternummer = 100
So einfach.
Hallo,
bei mir ist das nicht so einfach:)
Ich glaub du machst was falsch ;-)
Post by Stefan Miefert
Ich habe es so versucht
item = QListBoxItem(self.listBoxMitarbeiter)
item.MITARBEITERID = row["MAID"]
Soweit ok, aber...
Post by Stefan Miefert
item.setText="Alles ok"
setText ist eine Funktion (jedenfalls im Original C++ Qt), also eher
item.setText("Alles ok").
Post by Stefan Miefert
Da passiert aber nix. Keine EInträge werden angezeigt
Wenn ich jetzt das aufrufe
item.paint()
TypeError: Insufficient number of arguments to QListBoxItem.paint()
Welcher Wert muss da übergeben werden ?
Schau in die Qt Doku, paint will man normalerweise nicht selbst
aufrufen, eher schon repaint. Aber auch das sollte unnoetig sein, das
macht die QListBox wenn du die Items erstellst...

Andreas
--
Do not overtax your powers.
Stefan Miefert
2005-08-08 21:30:54 UTC
Permalink
Post by Andreas Pakulat
Post by Stefan Miefert
item.setText="Alles ok"
setText ist eine Funktion (jedenfalls im Original C++ Qt), also eher
item.setText("Alles ok").
Post by Stefan Miefert
Da passiert aber nix. Keine EInträge werden angezeigt
Wenn ich jetzt das aufrufe
item.paint()
TypeError: Insufficient number of arguments to QListBoxItem.paint()
Welcher Wert muss da übergeben werden ?
Schau in die Qt Doku, paint will man normalerweise nicht selbst
aufrufen, eher schon repaint. Aber auch das sollte unnoetig sein, das
macht die QListBox wenn du die Items erstellst...
Andreas
Hallo,

habe es mal geändert aber nix passiert

for row in result:
#
self.listBoxMitarbeiter.insertItem(self.__tr(str(row["nachname"]+","+row["vorname"])))

#
self.mitarbeiterliste[row["MAID"]]=self.listBoxMitarbeiter.count()-1
#
self.mitarbeiterliste2[self.listBoxMitarbeiter.count()-1]=row["MAID"]

item = QListBoxItem(self.listBoxMitarbeiter)
item.MITARBEITERID = row["MAID"]
item.setText("Alles ok")
Ulrich Berning
2005-08-08 22:16:10 UTC
Permalink
Post by Stefan Miefert
Post by Andreas Pakulat
Post by Stefan Miefert
item.setText="Alles ok"
setText ist eine Funktion (jedenfalls im Original C++ Qt), also eher
item.setText("Alles ok").
Post by Stefan Miefert
Da passiert aber nix. Keine EInträge werden angezeigt
Wenn ich jetzt das aufrufe
item.paint()
TypeError: Insufficient number of arguments to QListBoxItem.paint()
Welcher Wert muss da übergeben werden ?
Schau in die Qt Doku, paint will man normalerweise nicht selbst
aufrufen, eher schon repaint. Aber auch das sollte unnoetig sein, das
macht die QListBox wenn du die Items erstellst...
Andreas
Hallo,
habe es mal geändert aber nix passiert
#
self.listBoxMitarbeiter.insertItem(self.__tr(str(row["nachname"]+","+row["vorname"])))
#
self.mitarbeiterliste[row["MAID"]]=self.listBoxMitarbeiter.count()-1
#
self.mitarbeiterliste2[self.listBoxMitarbeiter.count()-1]=row["MAID"]
item = QListBoxItem(self.listBoxMitarbeiter)
item.MITARBEITERID = row["MAID"]
item.setText("Alles ok")
Ein kurzer Blick in die Qt Doku würde zeigen, dass QListBoxItem eine
abstrakte Klasse ist und damit auch nicht direkt verwendet werden kann.
Also entweder von QListBoxItem ableiten und paint(), width() und
height() implementieren (ist ziemlich viel Aufwand), oder QListBoxText
verwenden. QListBoxText ist von QListBoxItem abgeleitet und kann in der
gewünschten Art und Weise verwendet werden:

item = None
for row in result:
item = QListBoxText(self.listBoxMitarbeiter,
row["nachname"]+","+row["vorname"], item)
item.MITARBEITERID = row["MAID"]

Alternativ könnte man QListView und QListViewItem verwenden.

Ulli
Ulrich Berning
2005-08-09 15:20:34 UTC
Permalink
Post by Stefan Miefert
Post by Ulrich Berning
item = None
item = QListBoxText(self.listBoxMitarbeiter,
row["nachname"]+","+row["vorname"], item)
item.MITARBEITERID = row["MAID"]
Alternativ könnte man QListView und QListViewItem verwenden.
Hallo,
das scheint jetzt so zu funktioneiren. Wie greif ich aber später auf
diesen Wert zu ?
Den Text erhalte ich mit
print self.listBoxMitarbeiter.text(self.listBoxMitarbeiter.currentItem())
aber wie erhalte ich jetzt den neuen Wert MITARBEIETRID ?!
print self.listBoxMitarbeiter.currentItem().MITARBEITERID
Mit allen Methoden, die ein QListBoxItem zurück liefern:

QListBoxItem * selectedItem () const
QListBoxItem * item ( int index ) const
QListBoxItem * findItem ( const QString & text, ComparisonFlags compare
= BeginsWith ) const
QListBoxItem * itemAt ( const QPoint & p ) const
QListBoxItem * firstItem () const

Oder indem Du die Signale verwendest, die ein QListBoxItem an die
Slot-Routine liefern:

void highlighted ( QListBoxItem * )
void selected ( QListBoxItem * )
void selectionChanged ( QListBoxItem * item )
void currentChanged ( QListBoxItem * item )
void clicked ( QListBoxItem * item )
void clicked ( QListBoxItem * item, const QPoint & pnt )
void pressed ( QListBoxItem * item )
void pressed ( QListBoxItem * item, const QPoint & pnt )
void doubleClicked ( QListBoxItem * item )
void returnPressed ( QListBoxItem * )
void rightButtonClicked ( QListBoxItem *, const QPoint & )
void rightButtonPressed ( QListBoxItem *, const QPoint & )
void mouseButtonPressed ( int button, QListBoxItem * item, const QPoint
& pos )
void mouseButtonClicked ( int button, QListBoxItem * item, const QPoint
& pos )
void contextMenuRequested ( QListBoxItem * item, const QPoint & pos )
void onItem ( QListBoxItem * i )

Alle Methoden oder Signale, die nur den Text des QListBoxItem liefern,
sind nicht zu gebrauchen.
Alle Methoden oder Signale, die nur den Index des QListBoxItem liefern,
können zusammen mit der Methode item() verwendet werden.

Also z.B.: print
self.listBoxMitarbeiter.item(self.listBoxMitarbeiter.currentItem()).MITARBEITERID

Meines Erachtens ist is besser, das ganze Objekt (row) im QListBoxItem
zu referenzieren und nicht nur ein einzelnes Attribut, dann ist der
spätere Zugriff auf alle Attribute einfacher und lesbarer:
...
item.refobj = row
...
obj = self.listBoxMitarbeiter.selectedItem().refobj
print obj["vorname"], obj["nachname"], obj["MAID"]
...

Noch lesbarer wird das ganze, wenn die Daten als Instanzen einer Klasse
vorliegen:
...
print obj.vorname, obj.nachname, obj.MAID
...

Ich habe ein kleines funktionierendes Beispiel angehängt.


Ulli

-------------- nächster Teil --------------
#!/usr/bin/env python

import sys
from qt import *

# Diese Daten moegen das Ergebnis einer Datenbank-Abfrage sein:
result = [{"vorname": "Ulli",
"nachname": "Berning",
"MAID": 105},
{"vorname": "Stefan",
"nachname": "Miefert",
"MAID": 104},
{"vorname": "Otto",
"nachname": "Meyer",
"MAID": 103}]

# Diese Klasse nimmt die Daten eines Mitabeiters auf
class Mitarbeiter:
def __init__(self, d):
for key, value in d.items():
self.__dict__[key] = value

# Erzeugen der Liste aller Mitarbeiter-Instanzen
mitarbeiter_liste = []
for row in result:
mitarbeiter_liste.append(Mitarbeiter(row))

class MainWidget(QWidget):
def __init__(self, parent=None, name=None):
QWidget.__init__(self, parent, name)
v = QVBoxLayout(self, 4, 4)

self.lbm = QListBox(self)
v.addWidget(self.lbm)
self.connect(self.lbm,
SIGNAL("selectionChanged(QListBoxItem *)"),
self.slotItemSelected)

h = QHBoxLayout()
v.addLayout(h)

l = QLabel("Mitarbeiter:", self)
h.addWidget(l)

self.l = QLabel(self)
h.addWidget(self.l)

# Fuellen der ListBox
item = None
for ma in mitarbeiter_liste:
item = QListBoxText(self.lbm,
"%s,%s" % (ma.nachname, ma.vorname),
item)
item.refobj = ma

def slotItemSelected(self, item):
self.l.setText("[%d] %s %s" % (item.refobj.MAID,
item.refobj.vorname,
item.refobj.nachname))

if __name__=="__main__":
a = QApplication(sys.argv)
QObject.connect(a, SIGNAL("lastWindowClosed()"), a, SLOT("quit()"))
w = MainWidget()
a.setMainWidget(w)
w.show()
a.exec_loop()
Stefan Miefert
2005-08-09 15:51:03 UTC
Permalink
Post by Ulrich Berning
item = None
item = QListBoxText(self.listBoxMitarbeiter,
row["nachname"]+","+row["vorname"], item)
item.MITARBEITERID = row["MAID"]
Alternativ könnte man QListView und QListViewItem verwenden.
Hallo,

das scheint jetzt so zu funktioneiren. Wie greif ich aber später auf
diesen Wert zu ?

Den Text erhalte ich mit
print self.listBoxMitarbeiter.text(self.listBoxMitarbeiter.currentItem())

aber wie erhalte ich jetzt den neuen Wert MITARBEIETRID ?!

print self.listBoxMitarbeiter.currentItem().MITARBEITERID

--
Stefan Miefert
2005-08-09 16:07:35 UTC
Permalink
Post by Ulrich Berning
item = None
item = QListBoxText(self.listBoxMitarbeiter,
row["nachname"]+","+row["vorname"], item)
item.MITARBEITERID = row["MAID"]
Alternativ könnte man QListView und QListViewItem verwenden.
Hallo,

das scheint jetzt so zu funktioneiren. Wie greif ich aber später auf
diesen Wert zu ?

Den Text erhalte ich mit
print self.listBoxMitarbeiter.text(self.listBoxMitarbeiter.currentItem())
aber wie erhalte ich jetzt den neuen Wert MITARBEIETRID ?!

print self.listBoxMitarbeiter.currentItem().MITARBEITERID

--

Loading...