Buttons in wxPython nicht mehr ansprechbar

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Hallo,

Wie kann ich den Code von dem Tkinter Beispiel, dass ganz am Anfang des folgenden Beitrags:

http://www.python-forum.de/topic-3869.html

steht auf wxPython anpassen? Ich versuche schon 1 Tag lang eine Lösung zu finden...
Ich habe nämlich das Problem, dass ich mit dem Boa-Constructor eine GUI in wxPython erstellt habe und ich die darin enthaltenen Start und Stopp Buttons statt der Tkinter Buttons (wie im Beispiel) die Funktionen uebernehmen sollen . Sobald ich aber auf Start des wxPython Buttons drücke sind die anderen Buttons meiner GUI nicht mehr ansprechbar...
Wie löse ich dieses Problem???
Vielen Dank für die Hilfe im Voraus!!!

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

Hallo Toni83!

Ich habe jetzt leider keine Zeit mehr für viele Erklärungen. Nur eines ist zu sagen: Unter wxPython ist es sehr wichtig, Threads nicht direkt miteinander kommunizieren zu lassen. Es muss immer über ein "Thread-sicheres" Objekt (z.B. threading.Event) kommuniziert werden. Irgendwo zwischen den Threads muss immer so ein threadsicheres Objekt stehen.

Grob gesagt: Der Thread ist alles was in der "run"-Methode drinnen ist. Du darfst also nichts direkt von außen anfassen, was vom Thread verwendet wird. Und umgekehrt. Deshalb auch "wx.CallAfter()".

Code: Alles auswählen

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

import wx
import threading
from itertools import count
import time

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


class StepMotor(threading.Thread):
    
    def __init__(self, statusfunction = None):
        threading.Thread.__init__(self)
        self._statusfunction = statusfunction
        self._exit_event = threading.Event()
        self._run_event = threading.Event()
    
    
    def run(self):
        print "thread started"
        for step in count():
            self._run_event.wait()
            if self._exit_event.isSet():
                break
            if self._statusfunction and callable(self._statusfunction):
                wx.CallAfter(self._statusfunction, "Step %i" % step)
            print step
            time.sleep(0.5)
        print "thread stoped"    
    
    
    def motor_run(self):
        print "motor_run"
        self._run_event.set()
    
    
    def motor_halt(self):
        print "motor_halt"
        self._run_event.clear()
    

    def exit_thread(self):
        print "exit_thread"
        self._exit_event.set()
        self._run_event.set()
    
    
class MyFrame(wx.Frame):
    
    def __init__(
        self, parent = None, id = -1, title = "Schrittmotorsteuerung",
        style = wx.DEFAULT_FRAME_STYLE ^ (
            wx.RESIZE_BORDER | wx.RESIZE_BOX | wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX
        )
    ):
        wx.Frame.__init__(self, parent, id, title, style = style)
        
        panel = wx.Panel(self)
        self.panel = panel
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox)
        
        self.motor = StepMotor(self.update_status)
        self.motor.start() # Thread starten
        
        lab_status = wx.StaticText(
            panel, label = "<>", size = (250, -1), style = wx.TE_CENTER
        )
        vbox.Add(lab_status, 0, wx.ALL | wx.EXPAND, 5)
        self.lab_status = lab_status
        
        btn_run = wx.Button(panel, -1, "Run")
        vbox.Add(btn_run, 0, wx.ALL | wx.EXPAND, 5)
        btn_run.Bind(wx.EVT_BUTTON, lambda event: self.motor.motor_run())
        
        btn_halt = wx.Button(panel, -1, "Halt")
        vbox.Add(btn_halt, 0, wx.ALL | wx.EXPAND, 5)
        btn_halt.Bind(wx.EVT_BUTTON, lambda event: self.motor.motor_halt())
        
        btn_exit = wx.Button(panel, -1, "Exit")
        vbox.Add(btn_exit, 0, wx.ALL | wx.EXPAND, 5)
        btn_exit.Bind(wx.EVT_BUTTON, lambda event: self.Close())
        
        self.Bind(wx.EVT_CLOSE, self.on_frame_close)
        
        panel.Fit()
        self.Fit()
    
    
    def on_frame_close(self, event):
        event.Skip()
        self.motor.exit_thread()
        self.motor.join()
    
    
    def update_status(self, message):
        self.panel.Freeze()
        self.lab_status.SetLabel(message)
        self.panel.Layout()
        self.panel.Thaw()


def main():
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten