ListCtrl Verbindung Rückgabe mit Ursprungsdaten

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi,

habe ein Problem mit folgendem Code:

Code: Alles auswählen

#!/bin/env python
# -*- coding: iso-8859-15 -*-

import wx
import sys

class AuswahlDialog(wx.Dialog):
    def __init__(self, parent, spalten, daten):
        self.daten = daten
        wx.Dialog.__init__(self,parent,-1)
        self.Text = wx.StaticText(self,-1,"Auswahl",wx.Point(10,10))
        self.list=wx.ListCtrl(self,-1,wx.Point(10,50),wx.Size(200,100),wx.LC_REPORT
                                 | wx.BORDER_NONE
                                 | wx.LC_EDIT_LABELS
                                 | wx.LC_SORT_ASCENDING )
        for i in range(len(spalten)): 
            self.list.InsertColumn(i,spalten[i])

        for i in range(len(daten)):
            index = self.list.InsertStringItem(sys.maxint,"")
            self.list.SetStringItem(index, 0, str(daten[i][0]))
            self.list.SetStringItem(index, 1, daten[i][1])
                        
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, self.list)
        self.ShowModal()
        
    def OnItemActivated(self,event):
        self.currentItem = event.m_itemIndex
        self.artikel = self.daten[self.currentItem] 
        self.Fit()
    
    def GetReturn(self):
        return self.artikel
        
def main():
    app = wx.PySimpleApp()
    
    daten = ((1,'Haus'),(2,'Garten'),(3,'Baum'))
    spalten = ('Nummer','Teil')
    diag = AuswahlDialog(None,spalten,daten)
    print diag.GetReturn()
    app.MainLoop()
    
if __name__ == "__main__":
    main()
Wollte eigentlich nach der Auswahl eines ListItems die Ursprungsdaten weiterverarbeiten. Die Ursprungsdaten kommen aus einer SQL-Abfrage.

Bei Ausführung des obigen Codes werden die Items aber immer in umgekehrter Reihenfolge eingefügt, und die Verbindung liefert z.B. statt dem 1. Wert den letzten Wert.

Das Problem liegt in Codezeile 21, wenn man das 2. Argument nicht leer lässt sondern einen String einfügt, wir die Reihenfolge richtig angezeigt.

Fragt sich nur ob das so richtig ist, und ob es nicht eine bessere Möglichkeit gibt?

Der Code ist wahrscheinlich total primitiv, aber ist halt erst der Anfang und ein Versuch aus Beispielen ans Ziel zu kommen. Für Verbesserungen bin ich immer offen.

Gruß Christian
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Byte hat geschrieben:Für Verbesserungen bin ich immer offen.
Hi Christian!

Ich nehme dich beim Wort ;-)

Code: Alles auswählen

#!/bin/env python
# -*- coding: iso-8859-15 -*-

import wx
import sys

wx.SetDefaultPyEncoding("iso-8859-15")


class AuswahlDialog(wx.Dialog):
    
    def __init__(
        self, parent = None, id = -1, title = "Auswahldialog", spalten = None, zeilen = None
    ):
        
        wx.Dialog.__init__(self, parent, id, title)
        
        # vbox_border (Rahmen um Alles)
        vbox_border = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(vbox_border)
        
        # vbox (Sizer für die Widgets)
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox_border.Add(vbox, 0, wx.ALL, 5)
        
        # Label (StaticText)
        lab_auswahl = wx.StaticText(self, -1, " Auswahl")
        vbox.Add(lab_auswahl, 0, wx.TOP | wx.LEFT, 5)
        
        # ListCtrl
        list_ctrl = wx.ListCtrl(
            self, -1, size = wx.Size(200,100), 
            style = wx.LC_REPORT | wx.LC_EDIT_LABELS
        )
        vbox.Add(list_ctrl, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
        self.list_ctrl = list_ctrl
        
        # Spalten hinzufügen
        for spalte in spalten:
            list_ctrl.InsertColumn(sys.maxint, spalte)
        
        # Zeilen hinzufügen
        anz_spalten = list_ctrl.ColumnCount
        for zeile in zeilen:
            zeilenindex = list_ctrl.InsertStringItem(sys.maxint, str(zeile[0]))
            for spaltenindex in range(1, anz_spalten):
                list_ctrl.SetStringItem(zeilenindex, spaltenindex, str(zeile[1]))
        
        ## Automatische Spaltenbreite
        #for spaltenindex in range(list_ctrl.ColumnCount):
        #    list_ctrl.SetColumnWidth(spaltenindex, -1)
        
        # Linie
        vbox_border.Add(wx.StaticLine(self), proportion = 0, flag = wx.EXPAND)
        
        # hbox_buttons
        hbox_buttons = wx.BoxSizer(wx.HORIZONTAL)
        vbox_border.Add(
            hbox_buttons, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5
        )
        
        # Abbruch-Button
        cmd_cancel = wx.Button(self, wx.ID_CANCEL, "Abbruch")
        hbox_buttons.Add(cmd_cancel, proportion = 0, flag = wx.ALL, border = 5)
        
        # Spacer
        hbox_buttons.Add((0, 0), proportion = 1)
        
        # OK-Button
        cmd_ok = wx.Button(self, wx.ID_OK, "OK")
        hbox_buttons.Add(cmd_ok, proportion = 0, flag = wx.ALL, border = 5)
        
        # Größe auf das Minimum schrumpfen und auf Bildschirm zentrieren
        self.Fit()
        self.Center()
    
    
    def get_selected(self):
        
        list_ctrl = self.list_ctrl
        
        if list_ctrl.GetSelectedItemCount() > 0:
            focused_item = list_ctrl.GetItem(list_ctrl.FocusedItem)
            return focused_item.GetText()
        else:
            return None


def main():
    app = wx.PySimpleApp()
   
    spalten = ('Nummer', 'Teil')
    zeilen = ((1, 'Haus'), (2, 'Garten'), (3, 'Baum'))
    
    diag = AuswahlDialog(spalten = spalten, zeilen = zeilen)
    if diag.ShowModal() == wx.ID_OK:
        print diag.get_selected()
    else:
        print "Abbruch"


if __name__ == "__main__":
    main()
mfg
Gerold
:-)

Edit: Am Code noch eine Kleinigkeit ausgebessert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold!
Edit: Am Code noch eine Kleinigkeit ausgebessert.
Danke, funktioniert prima. Werde mich noch genauer damit befassen, aber das ist wieder ein Schritt in die richtige Richtung.

Ist echt ein gutes Forum, ohne blöde Sprüche.

Gruß
Christian
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold,

jetzt hatte ich doch noch ein Problem mit dem Code,

Code: Alles auswählen

anz_spalten = list_ctrl.ColumnCount
auf einem anderen Rechner, sagt er list_ctrl hat kein Attribut ColumnCount.

Habe deshalb wxPython 2.7 installiert und jetzt geht es. Wollte in der Referenz nachschauen ob das da drin steht, aber Fehlanzeige. Woher bekommt man also diese Eigenschaft.

Gruß Christian
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Byte hat geschrieben:Woher bekommt man also diese Eigenschaft.
Hi Christian!

Dass dieses Property erst mit wxPython 2.7 eingeführt wurde, das wusste ich nicht. Als Alternative schlage ich ``GetColumnCount()`` vor.

Wer sich nicht alles merken kann, der braucht eine gute IDE. :D WingIDE (http://wingware.com/) hat mir ``ColumnCount`` als "Property" von ``ListCtrl`` angezeigt. Deshalb habe ich es verwendet.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold,

ganz sicher bin ich mir auch nicht, ob das erst mit 2.7 funktioniert.

help(list_ctrl) gibt unter anderem folgendes aus.
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| ColumnCount
| See `GetColumnCount`
|
Habe zwar nur einen kleinen Schimmer, was das bedeutet. Bei der UNO API gibt es glaube ich sowas, wo man die Methoden get und set mit der Eigenschaft ansprechen kann, das wir da auch so sein.

Habe jetzt nur außer dem Help-Befehl nichts gefunden wo das dokumentiert ist.

Gruß Christian
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Byte hat geschrieben:ganz sicher bin ich mir auch nicht, ob das erst mit 2.7 funktioniert.
Hallo Christian!

Ich habe eben nachgesehen. Im wxPython 2.6.3.3 ist das Property ``ColumnCount`` noch nicht drinnen. Genauer gesagt, sind dort noch überhaupt keine Properties für das "ListCtrl" definiert.

Property siehe: http://docs.python.org/lib/built-in-funcs.html (suche nach "Property")

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold,

habe versucht das ganze in meine Anwendung zu packen, dabei bleibt mir noch das Problem, der Verbindung zu den Orginaldaten.

Kill mich bitte nicht, weil ich das Design etwas zerstört habe. :wink:

Code: Alles auswählen

#!/bin/env python
# -*- coding: iso-8859-15 -*-

import wx
import sys

wx.SetDefaultPyEncoding("iso-8859-15")


class AuswahlDialog(wx.Dialog):
   
    def __init__(
        self, parent = None, id = -1, title = "Auswahldialog", spalten = None, zeilen = None
    ):
       
        wx.Dialog.__init__(self, parent, id, title)
       
        # vbox_border (Rahmen um Alles)
        vbox_border = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(vbox_border)
       
        # vbox (Sizer für die Widgets)
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox_border.Add(vbox, 0, wx.ALL, 5)
       
        # Label (StaticText)
        lab_auswahl = wx.StaticText(self, -1, " Auswahl")
        vbox.Add(lab_auswahl, 0, wx.TOP | wx.LEFT, 5)
       
        # ListCtrl
        list_ctrl = wx.ListCtrl(
            self, -1, size = wx.Size(200,100),
            style = wx.LC_REPORT | wx.LC_EDIT_LABELS
        )
        vbox.Add(list_ctrl, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
        self.list_ctrl = list_ctrl
       
        # Spalten hinzufügen
        for spalte in spalten:
            list_ctrl.InsertColumn(sys.maxint, spalte)
            # Zeilen hinzufügen
        anz_spalten = list_ctrl.ColumnCount
        for zeile in zeilen:
            zeilenindex = list_ctrl.InsertStringItem(sys.maxint, str(zeile[0]))
            for spaltenindex in range(1, anz_spalten):
                list_ctrl.SetStringItem(zeilenindex, spaltenindex, str(zeile[spaltenindex]))
       
        ## Automatische Spaltenbreite
        #for spaltenindex in range(list_ctrl.ColumnCount):
        #    list_ctrl.SetColumnWidth(spaltenindex, -1)
       
        # Linie
        vbox_border.Add(wx.StaticLine(self), proportion = 0, flag = wx.EXPAND)
       
        # hbox_buttons
        hbox_buttons = wx.BoxSizer(wx.HORIZONTAL)
        vbox_border.Add(
            hbox_buttons, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5
        )
       
        # Abbruch-Button
        cmd_cancel = wx.Button(self, wx.ID_CANCEL, "Abbruch")
        hbox_buttons.Add(cmd_cancel, proportion = 0, flag = wx.ALL, border = 5)
       
        # Spacer
        hbox_buttons.Add((0, 0), proportion = 1)
       
        # OK-Button
        cmd_ok = wx.Button(self, wx.ID_OK, "OK")
        hbox_buttons.Add(cmd_ok, proportion = 0, flag = wx.ALL, border = 5)
       
        # Größe auf das Minimum schrumpfen und auf Bildschirm zentrieren
        self.Fit()
        self.Center()
   
   
    def get_selected(self):
       
        list_ctrl = self.list_ctrl
       
        if list_ctrl.GetSelectedItemCount() > 0:
            focused_item = list_ctrl.GetItem(list_ctrl.FocusedItem)
            return focused_item.GetText()
        else:
            return None


def main():
    app = wx.PySimpleApp()
   
    spalten = ('Nummer', 'Teil','Eigenschaft')
    zeilen = ((1, 'Haus','groß','100'), (2, 'Garten','grün','500'), (3, 'Baum','hoch','300'))
   
    diag = AuswahlDialog(spalten = spalten, zeilen = zeilen)
    if diag.ShowModal() == wx.ID_OK:
        print diag.get_selected()
    else:
        print "Abbruch"


if __name__ == "__main__":
    main()
Eine kleine Verbesserung habe ich auch gemacht, Zeile 47 anstatt 1 Spaltenindex eingefügt.

Jetzt aber wieder zu meinem Problem, die Zeilen sind Datensätze aus einer Abfrage, Rückgabewert soll der ausgewählte Datensatz als Liste sein.

Ich könnte natürlich mit dem jetzigen Wert, der zufällig der PrimaryKey des Datensatz ist eine neue Abfrage ausführen, die mir nur diesen Datensatz zurückliefert. Ist aber glaube ich für die Performance nicht recht gut.

Evtl. gibt es auch eine Listenfunktion, die mir anhand der Zahl den richtigen Listenpunkt zurückgibt.

Meine Idee war aber, da ich die einzelnen Datensätze aus der Liste, eindeutig indexieren kann, und auch der Reihe nach in das listCtrl einfüge, vom listCtrl nach Auswahl einen Wert zurückzuerhalten, den ich direkt mit den Datensätzen in Verbindung bringen kann.

Rückgabewert, ist ja im jetzigen Fall immer der Text der erste Spalte. Aber was mache ich wenn ich den 1 und 4 Wert weiterverarbeiten will, wobei der 4 Wert nur im Datensatz vorhanden ist und im Dialog nicht angezeigt wird?

Ich hoffe meine Unwissenheit wird dir nicht schön langsam zu blöd.


Christian
:?
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold,

und hier mein Lösungsvorschlag, zum Beitrag vorher, bin mir nur nicht sicher ob das 100Prozent immer passt.

Code: Alles auswählen

#!/bin/env python
# -*- coding: iso-8859-15 -*-

import wx
import sys

wx.SetDefaultPyEncoding("iso-8859-15")


class AuswahlDialog(wx.Dialog):
   
    def __init__(
        self, parent = None, id = -1, title = "Auswahldialog", spalten = None, zeilen = None
    ):
        # Damit es in der Funktion weiter verwendet werden kann?
        self.zeilen = zeilen
        
        wx.Dialog.__init__(self, parent, id, title)
       
        # vbox_border (Rahmen um Alles)
        vbox_border = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(vbox_border)
       
        # vbox (Sizer für die Widgets)
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox_border.Add(vbox, 0, wx.ALL, 5)
       
        # Label (StaticText)
        lab_auswahl = wx.StaticText(self, -1, " Auswahl")
        vbox.Add(lab_auswahl, 0, wx.TOP | wx.LEFT, 5)
       
        # ListCtrl
        list_ctrl = wx.ListCtrl(
            self, -1, size = wx.Size(200,100),
            style = wx.LC_REPORT | wx.LC_EDIT_LABELS
        )
        vbox.Add(list_ctrl, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
        self.list_ctrl = list_ctrl
       
        # Spalten hinzufügen
        for spalte in spalten:
            list_ctrl.InsertColumn(sys.maxint, spalte)
            # Zeilen hinzufügen
        anz_spalten = list_ctrl.ColumnCount
        for zeile in zeilen:
            zeilenindex = list_ctrl.InsertStringItem(sys.maxint, str(zeile[0]))
            for spaltenindex in range(1, anz_spalten):
                list_ctrl.SetStringItem(zeilenindex, spaltenindex, str(zeile[spaltenindex]))
       
        ## Automatische Spaltenbreite
        #for spaltenindex in range(list_ctrl.ColumnCount):
        #    list_ctrl.SetColumnWidth(spaltenindex, -1)
       
        # Linie
        vbox_border.Add(wx.StaticLine(self), proportion = 0, flag = wx.EXPAND)
       
        # hbox_buttons
        hbox_buttons = wx.BoxSizer(wx.HORIZONTAL)
        vbox_border.Add(
            hbox_buttons, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5
        )
       
        # Abbruch-Button
        cmd_cancel = wx.Button(self, wx.ID_CANCEL, "Abbruch")
        hbox_buttons.Add(cmd_cancel, proportion = 0, flag = wx.ALL, border = 5)
       
        # Spacer
        hbox_buttons.Add((0, 0), proportion = 1)
       
        # OK-Button
        cmd_ok = wx.Button(self, wx.ID_OK, "OK")
        hbox_buttons.Add(cmd_ok, proportion = 0, flag = wx.ALL, border = 5)
       
        # Größe auf das Minimum schrumpfen und auf Bildschirm zentrieren
        self.Fit()
        self.Center()
   
   
    def get_selected(self):
       
        list_ctrl = self.list_ctrl
       
        if list_ctrl.GetSelectedItemCount() > 0:
            focused_item = list_ctrl.FocusedItem
            print self.zeilen[focused_item]
        else:
            return None


def main():
    app = wx.PySimpleApp()
   
    spalten = ('Nummer', 'Teil','Eigenschaft')
    zeilen = ((1, 'Haus','groß','100'), (2, 'Garten','grün','500'), (3, 'Baum','hoch','300'))
   
    diag = AuswahlDialog(spalten = spalten, zeilen = zeilen)
    if diag.ShowModal() == wx.ID_OK:
        print diag.get_selected()
    else:
        print "Abbruch"


if __name__ == "__main__":
    main()

Auf alle Fälle danke für deine Hilfe.

Gruß Christian
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi Christian!

Bis auf wenige Ausnahmen, denke ich, dass es sinnvoll ist, die Initialisierung des Dialogs nicht nach unten zu verschieben. Damit meine ich, dass vor der Zeile 19 (``print self.zeilen[focused_item]``) keine anderen Anweisungen stehen sollten.

Zeile 85: Aus ``focused_item = list_ctrl.FocusedItem`` könnte man ``focused_item = list_ctrl.GetFocusedItem()`` machen, damit wäre dieses Property auch aus dem Weg. Vielleicht bringt es etwas in Richtung Rückwärtskompatibilität.
Zeile 86: Aus ``print self.zeilen[focused_item]`` würde ich ``return self.zeilen[focused_item]`` machen. :-)

Mehr ist mir nicht aufgefallen. Das ist doch ein gutes Zeichen, oder? :-)

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold,
Mehr ist mir nicht aufgefallen. Das ist doch ein gutes Zeichen, oder?
Hab mir auch fast nicht helfen lassen! :D

Danke Christian

p. s.: habe sicher bald wieder was
Antworten