Seite 1 von 1

Binding zu einer unbekannten Zahl von Checkboxen

Verfasst: Freitag 5. März 2010, 14:21
von calo
Hallo,

Ich stehe gerade auf der Leitung und komme einfach nicht weiter. Folgender Code:

Code: Alles auswählen

import wx


class Frame(wx.Frame):

    def __init__(self, parent, id, title, suites):
        wx.Frame.__init__(self, parent, id, title, size=(400, 200))
        self.suites = suites

        self.nb = wx.Notebook(self,-1)
        self.feat_book = feat_nb(self.nb, -1, suites)
        self.nb.AddPage(self.feat_book, "features")


################################################################################
class feat_nb(wx.Panel):
    def __init__(self, parent, id, suite_labels):
        wx.Panel.__init__(self, parent, id)

        self.all_boxes = []
        self.feature_boxes = {}
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        for suite in suite_labels.keys():
            box = self.MakeStaticBoxSizer(suite, suite_labels[suite])
            sizer.Add(box, 0, wx.ALL, 10)
            self.all_boxes.append(box)

        self.SetSizer(sizer)
        sizer.Fit(self)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def MakeStaticBoxSizer(self, suite_label, feat_labels):
        box = wx.StaticBox(self, -1, suite_label)
        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)

        for label in feat_labels:
            feat = wx.CheckBox(self, -1, label)
            self.feature_boxes[label] = feat
            sizer.Add(feat, 0, wx.ALL)

        return sizer

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def set_CheckBoxes(self, features, suites):
        for feature in features:
            for suite in suites.keys():
                if feature in suites[suite]:
                    self.feature_boxes[feature].SetValue(True)



###############################################################################
class App(wx.App):

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __init__(self, redirect=False):
        wx.App.__init__(self, redirect)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def OnInit(self):
        self.suites = {"Gruppe 1": ["EINS", "ZWEI", "DREI"], "Gruppe 2": ["VIER", "FUENF", "SECHS", "SIEBEN"]}
        self.features_on_start = ["EINS", "DREI", "FUENF"]

        self.frame = Frame(None, -1, "test", self.suites)
        self.SetTopWindow(self.frame)
        self.frame.Show()       
        self.frame.feat_book.set_CheckBoxes(self.features_on_start, self.suites)

        self.Bind(wx.EVT_CHECKBOX, self.OnEinsCheckbox, self.frame.feat_book.feature_boxes["EINS"])

        return True


    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def OnEinsCheckbox(self, evt):
        print "EINS"        
        

###############################################################################
if __name__=="__main__":
    app = App()
    app.MainLoop()
Ich habe eine unbekannte Anzahl an Suites (Gruppe 1, Gruppe 2). Diese werde aus einer INI-Datei eingelesen. Außerdem habe ich zu jeder Suite eine unbekannte Anzahl an Features (EINS, ZWEI, ...). Für jedes Features/Suite-Kombination erzeuge ich eine Checkbox. Das klappt soweit.

Jetzt möchte ich auch zu jedem Feature eine Ereignis-Funktion schreiben. Dazu benötige ich aber eine dynamisch erstelltes Binding zwischen jeder Checkbox und der dazu gehörenden Funktion:
* EINS --> OnEinsCheckbox()
* ZWEI --> OnZweiCheckbox()
* ...
Rein statisch im Quellcode wäre das ja kein Problem. Aber ich weis halt vorher nicht wieviele Suiten und Features aus der INI-Datei eingelesen werden. Hat mir vielleicht einer von euch einen Tipp?

Calo

Re: Binding zu einer unbekannten Zahl von Checkboxen

Verfasst: Freitag 5. März 2010, 15:44
von tordmor
calo hat geschrieben: Jetzt möchte ich auch zu jedem Feature eine Ereignis-Funktion schreiben. Dazu benötige ich aber eine dynamisch erstelltes Binding zwischen jeder Checkbox und der dazu gehörenden Funktion
Ich kann mir nicht vorstellen, dass dynamisch erzeugte Checkboxen tatsächlich alle eine vollständig unterschiedliche Funktion haben. Also wozu für jede Checkbox eine eigene Funktion?

Verfasst: Freitag 5. März 2010, 15:51
von EyDu
Hallo.

functools.partial ist dein Freund. Mit lambda geht es auch noch, finde ich aber nicht so schön.

Sebastian

Re: Binding zu einer unbekannten Zahl von Checkboxen

Verfasst: Freitag 5. März 2010, 16:24
von calo
Zugegeben. Für jede Checkbox eine eigene Funktion zu schreiben, macht in meinem speziellen Fall nicht so viel Sinn. Vielleicht ist es Sinnvoller alle Checkboxen mit einem Binding zu verknüpfen:
Klick auf irgend eine Checkbox --> OnClickCheckbox()

Anschließend innerhalb von OnClickCheckbox eine Fallunterscheidung durchführen. In diesem Fall die Frage, wie erzeuge ich ein Binding, das auf alle Checkboxen reagiert:
self.Bind(EVT_CHECKBOX, self.OnClickCheckbox, self.anyCheckbox)

Mir fehlt hier die Verbindung zwischen den einzelnen Checkboxen, die in der Liste feat_book.all_boxes eingefügt wurden und anyCheckbox.
tordmor hat geschrieben:
calo hat geschrieben: Jetzt möchte ich auch zu jedem Feature eine Ereignis-Funktion schreiben. Dazu benötige ich aber eine dynamisch erstelltes Binding zwischen jeder Checkbox und der dazu gehörenden Funktion
Ich kann mir nicht vorstellen, dass dynamisch erzeugte Checkboxen tatsächlich alle eine vollständig unterschiedliche Funktion haben. Also wozu für jede Checkbox eine eigene Funktion?

Verfasst: Freitag 5. März 2010, 16:26
von EyDu
Tja, hättest du nur meinen Beitrag gelesen ...

Re: Binding zu einer unbekannten Zahl von Checkboxen

Verfasst: Freitag 5. März 2010, 16:32
von tordmor
calo hat geschrieben: Mir fehlt hier die Verbindung zwischen den einzelnen Checkboxen, die in der Liste feat_book.all_boxes eingefügt wurden und anyCheckbox.
Du musst schon für jede Checkbox ein binding machen, aber eben nicht mit unterschiedilchen Funktionen, sondern mit der selben- oder wie EyDu schrieb mit functools.partial.

Verfasst: Freitag 5. März 2010, 21:11
von calo
@EyDu
Sorry. Ich konnte mit functools.partial erst einmal so rein gar nichts anfangen. Jetzt habe ich mich ein bisschen eingelesen ... und siehe da (ich meine unten) es funktioniert :lol:
EyDu hat geschrieben:Tja, hättest du nur meinen Beitrag gelesen ...

Code: Alles auswählen

# -*- coding: utf-8 -*-
import wx
from functools import partial


class Frame(wx.Frame):

    def __init__(self, parent, id, title, suites, app):
        wx.Frame.__init__(self, parent, id, title, size=(400, 200))
        self.suites = suites
        self.app = app

        self.nb = wx.Notebook(self,-1)
        self.feat_book = feat_nb(self.nb, -1, suites, app)
        self.nb.AddPage(self.feat_book, "features")


################################################################################
class feat_nb(wx.Panel):
    def __init__(self, parent, id, suite_labels, app):
        wx.Panel.__init__(self, parent, id)

        self.app = app
        self.all_boxes = []
        self.feature_boxes = {}
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        for suite in suite_labels.keys():
            box = self.MakeStaticBoxSizer(suite, suite_labels[suite])
            sizer.Add(box, 0, wx.ALL, 10)
            self.all_boxes.append(box)

        self.SetSizer(sizer)
        sizer.Fit(self)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def MakeStaticBoxSizer(self, suite_label, feat_labels):
        box = wx.StaticBox(self, -1, suite_label)
        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)

        for label in feat_labels:
            feat = wx.CheckBox(self, -1, label)
            self.feature_boxes[label] = feat
            cmd = partial(self.app.OnClickCheckbox, arg=label)
            self.app.Bind(wx.EVT_CHECKBOX, cmd, feat)
            sizer.Add(feat, 0, wx.ALL)

        return sizer

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def set_CheckBoxes(self, features, suites):
        for feature in features:
            for suite in suites.keys():
                if feature in suites[suite]:
                    self.feature_boxes[feature].SetValue(True)



###############################################################################
class App(wx.App):

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __init__(self, redirect=False):
        wx.App.__init__(self, redirect)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def OnInit(self):
        self.suites = {"Gruppe 1": ["EINS", "ZWEI", "DREI"], 
                       "Gruppe 2": ["VIER", "FUENF", "SECHS", "SIEBEN"]}
        self.features_on_start = ["EINS", "DREI", "FUENF"]

        self.frame = Frame(None, -1, "test", self.suites, self)
        self.SetTopWindow(self.frame)
        self.frame.Show()       
        self.frame.feat_book.set_CheckBoxes(self.features_on_start, self.suites)

        return True


    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def OnClickCheckbox(self, evt, arg):
        print arg       
       

###############################################################################
if __name__=="__main__":
    app = App()
    app.MainLoop()