2016-04-07 8 views
2

Ich habe an einem GUI-Code in wxpython gearbeitet, der mehr oder weniger die gleichen Informationen 4 Mal wiederholt. Es gibt viele Schaltflächen auf dem Bildschirm, an die ich Ereignisse binden musste, und ich stelle fest, dass ich eine Menge von on_button_click-Definitionen habe, die fast identisch aussehen. Also habe ich mich gefragt, ob es einen Weg gibt, einen Parameter einfach zu durchlaufen, wenn man die Schaltfläche an ein Ereignis bindet und 3 der Definitionen ausschneidet. Hier ein Beispiel:Verkürzung des GUI-Codes durch Übergabe von Parametern an Definitionen

self.VDBenchSlot1 = wx.Button(self, -1, "Slot 1 VDBench") 
sizer.Add(self.VDBenchSlot1,(1, 5), (1, 5), wx.EXPAND) 
self.VDBenchSlot1.Bind(wx.EVT_BUTTON, self.VDBenchSlot1_clicked) 

self.VDBenchSlot2 = wx.Button(self, -1, "Slot 2 VDBench") 
sizer.Add(self.VDBenchSlot2,(1, 5), (1, 5), wx.EXPAND) 
self.VDBenchSlot2.Bind(wx.EVT_BUTTON, self.VDBenchSlot2_clicked) 

self.VDBenchSlot3 = wx.Button(self, -1, "Slot 3 VDBench") 
sizer.Add(self.VDBenchSlot3,(1, 5), (1, 5), wx.EXPAND) 
self.VDBenchSlot3.Bind(wx.EVT_BUTTON, self.VDBenchSlot3_clicked) 

self.VDBenchSlot4 = wx.Button(self, -1, "Slot 4 VDBench") 
sizer.Add(self.VDBenchSlot4,(1, 5), (1, 5), wx.EXPAND) 
self.VDBenchSlot4.Bind(wx.EVT_BUTTON, self.VDBenchSlot4_clicked) 

def VDBenchSlot1_clicked(self, event):  
    global diskchange 
    if diskchange[1] == 'No Disk': 
     self.TextSlot1.AppendText("No Disk is currently in the slot so you cannot run this! \n") 
    else: 
     # Open the file startDisk#VD.sh that has the setup to start running VDBench 
     os.system("echo pcieRocks | sudo -S gnome-terminal --profile=VDbench --working-directory=/home/pciedev3ubuntu/Documents -e './vdbench -f disk%dVDscript.txt -vr' &" %diskchange[1]) 

def VDBenchSlot2_clicked(self, event): 
    global diskchange 

    if diskchange[2] == 'No Disk': 
     self.TextSlot2.AppendText("No Disk is currently in the slot so you cannot run this! \n") 
    else: 
     # Open the file startDisk#VD.sh that has the setup to start running VDBench 
     os.system("echo pcieRocks | sudo -S gnome-terminal --profile=VDbench --working-directory=/home/pciedev3ubuntu/Documents -e './vdbench -f disk%dVDscript.txt -vr' &" %diskchange[2]) 

def VDBenchSlot3_clicked(self, event): 
    global diskchange 

    if diskchange[3] == 'No Disk': 
     self.TextSlot3.AppendText("No Disk is currently in the slot so you cannot run this! \n") 
    else: 
     # Open the file startDisk#VD.sh that has the setup to start running VDBench 
     os.system("echo pcieRocks | sudo -S gnome-terminal --profile=VDbench --working-directory=/home/pciedev3ubuntu/Documents -e './vdbench -f disk%dVDscript.txt -vr' &" %diskchange[3]) 

def VDBenchSlot4_clicked(self, event): 
    global diskchange 

    if diskchange[4] == 'No Disk': 
     self.TextSlot4.AppendText("No Disk is currently in the slot so you cannot run this! \n") 
    else: 
     # Open the file startDisk#VD.sh that has the setup to start running VDBench 
     os.system("echo pcieRocks | sudo -S gnome-terminal --profile=VDbench --working-directory=/home/pciedev3ubuntu/Documents -e './vdbench -f disk%dVDscript.txt -vr' &" %diskchange[4]) 

Ich habe versucht, VDBenchslotx_clicked zu VDBenchslotx_clicked Wechsel() und Übergabe von Parametern an, aber einer von zwei Dingen geschehen; Es sagt mir, dass die eingegebenen Parameter nicht mit den Parametern des def übereinstimmen, oder es lässt mein Programm laufen, aber es führt automatisch das Def beim Programmstart aus und nicht wenn die Taste gedrückt wird, und die Taste funktioniert dann nicht richtig.

+5

Ich weiß nicht, wxpython, aber es scheint, dass Sie das nicht tun können, was ärgerlich ist: sogar die bescheidene Tkinter ermöglicht es Ihnen, eine zusätzliche Arg übergeben, wenn Sie einen Rückruf an ein Widget binden. Die oberste Antwort auf [diese Frage] (http://stackoverflow.com/questions/173687/is-it-possible-to-pass-arguments-into-event-bindings) zeigt jedoch, wie Sie erreichen können, was Sie wollen. –

+0

BTW, können Sie die Wiederholung reduzieren, indem Sie eine Hilfsfunktion erstellen, die Ihre Schaltflächen erstellt. Eine übliche Technik besteht darin, solche Hilfsfunktionen innerhalb der Methode zu definieren, die die Widgets erzeugt (typischerweise die Methode "__init__"), so dass sie auf die lokalen Variablen der Methode zugreifen kann, ohne diese Variablen im Funktionsaufruf übergeben zu müssen. –

+0

Ich bin mir nicht sicher, was Sie meinen, wenn Sie Helferfunktion sagen, da ich ziemlich neu dazu bin ... haben Sie eine gute Verbindung, die Sie als Beispiel liefern können? –

Antwort

2

Verwenden Sie einen Lambda-Ausdruck, um Argumente an gebundene Funktionen zu übergeben. Zum Beispiel:

self.VDBenchSlot1.Bind(wx.EVT_BUTTON, lambda event: self.VDBenchSlot_clicked(event, 1)) 

def VDBenchSlot_clicked(self, event, position): 
    if position == 1: 
     text_slot = self.TextSlot1 
    elif position == 2: 
     text_slot = self.TextSlot2 
    elif position == 3: 
     text_slot = self.TextSlot3 
    elif position == 4: 
     text_slot = self.TextSlot4  
    global diskchange 
    if diskchange[position] == 'No Disk': 
     text_slot.AppendText("No Disk is currently in the slot so you cannot run this! \n") 
    else: 
     # Open the file startDisk#VD.sh that has the setup to start running VDBench 
     os.system("echo pcieRocks | sudo -S gnome-terminal --profile=VDbench --working-directory=/home/pciedev3ubuntu/Documents -e './vdbench -f disk%dVDscript.txt -vr' &" %diskchange[position]) 
+0

Ich erhalte die folgende Fehlermeldung nach der Implementierung Ihrer Änderungen: TypeError: VDBenchSlot_clicked() nimmt genau 2 Argumente (3 gegeben) –

+0

Nevermind, ich fand es heraus. Es sollte nur VDBenchSlot1_clicked (1) sein, nicht (event, 1). Vielen Dank dafür! –

0

DBC (und the linked question) zeigen, wie man das erreichen, was Sie wollen. Aber hier ist eine kurze Demonstration des Hilfsfunktionskonzepts, das ich oben in meinem Kommentar erwähnt habe.

def make_button(text, callback): 
    button = wx.Button(self, -1, text) 
    sizer.Add(button, (1, 5), (1, 5), wx.EXPAND) 
    button.Bind(wx.EVT_BUTTON, callback) 
    return button 

self.VDBenchSlot1 = make_button("Slot 1 VDBench", self.VDBenchSlot1_clicked) 
self.VDBenchSlot2 = make_button("Slot 2 VDBench", self.VDBenchSlot2_clicked) 

Beachten Sie, dass make_button nicht über self in seiner Unterschrift. Das ist, weil es nicht eine Methode ist, ist es eine Funktion innerhalb einer Methode definiert. Ein vollständiges Beispiel in GTK2 + finden Sie unter this answer.

Beachten Sie auch, dass mein Code auf Ihrem ursprünglichen Code basiert, aber es sollte einfach für Sie sein, es an die neueCallback-Methode von dbc anzupassen.

+0

Ah okay, ich sehe die allgemeine Idee. Ich bin mir ziemlich sicher, dass ich sizer.Add aus dem DEF nehmen möchte, oder? denn sonst werde ich einfach alle diese Buttons am selben Ort erstellen. –

+0

@TreverWagenhals: Ich habe meinen Code korrigiert. Entschuldigung wegen der früheren Verwirrung. : oops: –

+1

hat einige Änderungen an Ihrem Post vorgenommen, um meine Bedenken bezüglich sizer.Add widerzuspiegeln. Zeigte, wie es in beiden Fällen aussieht, damit du sehen kannst, was ich ein wenig besser finde. Danke dafür, zwischen diesen beiden Anpassungen habe ich bereits etwa 300 Zeilen Code verschrottet. –

Verwandte Themen