Event auf Radiobutton hat Absturz zur Folge

Plattformunabhängige GUIs mit wxWidgets.
BW
User
Beiträge: 25
Registriert: Dienstag 20. März 2007, 10:25

Event auf Radiobutton hat Absturz zur Folge

Beitragvon BW » Dienstag 6. November 2007, 15:27

Hallo zusammen,

ich stehe vor einem Rätsel...
Auf meinem PC mit Windows XP läuft das Skript ohne Probleme, aber das gleiche Skript auf einem PC mit Windows 2000 verursacht einen Absturz.
Auf beiden PCs ist die gleiche Version von Python und wxPython.

Wenn ich auf dem Windows 2000 PC bei einigen Radiobuttongruppen ein Event auslöse, hängt sich das Skript auf und beide Radiobuttons sind aktiv. Danach geht nichts mehr....

Ich bekomme leider keinerlei Fehlermeldung. Selbst nur ein "print" in der Event-Methode wird nicht ausgeführt.
Ich habe schon nachgeschaut, ob die ID vielleicht aus versehen doppelt vergeben ist oder ob die Event-Methode zweimal auftaucht. Beides ist nicht der Fall, soweit ich das gesehen habe.

Hat einer von euch vielleicht noch ne Idee, warum das passiert bzw. vielleicht einen Hinweis wie ich das Problem beseitigen kann?

Den Code hier reinzustellen ist leider nicht möglich, weil das Problem in einem größeren Zusammenhang drin steckt.

viele Grüße
Barbara
The Spirit
User
Beiträge: 274
Registriert: Freitag 8. Juni 2007, 08:50
Wohnort: 84xxx Bereich
Kontaktdaten:

Beitragvon The Spirit » Dienstag 6. November 2007, 16:51

wenn du das skript über die commandozeile aufrufst müsste doch immer ne meldung kommen, wenn sich das script aufhängt.
um dir helfen zu können, wäre dies wichtig
BW
User
Beiträge: 25
Registriert: Dienstag 20. März 2007, 10:25

Beitragvon BW » Mittwoch 7. November 2007, 07:59

guten morgen,
leider überhaupt keine Meldung :(
Es erscheint nur ein Fenster mit der Information, dass das Programm nicht reagiert. Dann habe ich die Möglichkeit auf "sofort beenden" oder "abbrechen" zu drücken. Bei "abbrechen" bleibt die Anwendung nach wie vor hängen und bei "sofort beenden" schließt sich die Anwendung vollständig ohne einen Hinweis darauf, was denn da gerade schief gegangen ist.

Was ich noch heraus gefunden habe ist, dass wenn ich mit der Tab-Taste die Radiobuttongruppe steuer, dann funktioniert alles so wie es soll. Sprich "nur" das Mouse-Event geht daneben.

Gibts denn da ne Möglichkeit herauszufinden, was während des Mouse-Events passiert?

Was die ganze Sache ja noch merkwürdiger macht ist, dass in anderen Dialogen der Anwendung die Radiobuttongruppen ganz normal funktionieren. Ich verstehe das einfach nicht....

Also wenn jemand ne Idee hat, bin ich sehr dankbar dafür.

Barbara
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 7. November 2007, 08:11

Hallo Barbara!

Was passiert, wenn du dein Programm so startest?
python -i <modulname.py>

Deaktiviere nach und nach Codeteile (z.B. Eventhandler) und finde zumindest mal raus, in welchem Codeteil dein Fehler auftritt.

Nach und nach kannst du dann wieder Codezeilen hinzufügen. Jedes mal danach einen Test.

Erstelle dir Haltepunkte und debugge deine Anwendung Schritt für Schritt. Z.B. mit WingIDE. Das ist meine Lieblingsmethode. Damit finde ich einen Fehler meist in wenigen Minuten.

Ich zitiere mal Robin Dunn: Please make a small sample app that shows the problem. http://wiki.wxpython.org/MakingSampleApps

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BW
User
Beiträge: 25
Registriert: Dienstag 20. März 2007, 10:25

Beitragvon BW » Mittwoch 7. November 2007, 08:39

moin moin,

ich hatte mir ein mini Beispiel erstellt und getestet, ob das denn läuft. Und es geht auf beiden Rechnern.
Hier mal der Code:

Code: Alles auswählen

import wx

class DialogMain(wx.Dialog):
    def __init__(self, parent, id, title,
        pos = wx.DefaultPosition, size = wx.DefaultSize,
        style = wx.DEFAULT_DIALOG_STYLE ):
        wx.Dialog.__init__(self, parent, id, title, pos, size, style)
       
        item0 = wx.BoxSizer( wx.VERTICAL )       
        # obere Teil
        item1 = wx.StaticText( self, -1, "Hier ist eigntlich noch ein weiteres Panel",
            wx.DefaultPosition, wx.DefaultSize, 0 )
        item0.Add( item1, 0, wx.ALIGN_CENTER|wx.ALL, 5 )       
        # panel
        self.panel1 = Panel_1(self, -1)       
        # hinzufuegen zu sizer
        item0.Add(self.panel1, 0, wx.ALIGN_LEFT)       
        self.SetSizer(item0)
        item0.SetSizeHints( self )       
        # EVENTS
        wx.EVT_RADIOBUTTON(self, self.panel1.Radio1.GetId(), self.OnRadio)
        wx.EVT_RADIOBUTTON(self, self.panel1.Radio2.GetId(), self.OnRadio)
        wx.EVT_RADIOBUTTON(self, self.panel1.Radio3.GetId(), self.OnRadio)         
        self.TransferDataToWindow()
   
    def TransferDataToWindow(self):
        if self.panel1.Radio1.GetValue() == True:
            self.panel1.GetSizer().Show(self.panel1.SIZER_ro, True, True)
            self.panel1.GetSizer().Show(self.panel1.SIZER_rm, False, True)
            self.panel1.GetSizer().Show(self.panel1.SIZER_ru, False, True)
        elif self.panel1.Radio2.GetValue() == True:
            self.panel1.GetSizer().Show(self.panel1.SIZER_ro, False, True)
            self.panel1.GetSizer().Show(self.panel1.SIZER_rm, True, True)
            self.panel1.GetSizer().Show(self.panel1.SIZER_ru, False, True)
        elif self.panel1.Radio3.GetValue() == True:
            self.panel1.GetSizer().Show(self.panel1.SIZER_ro, False, True)
            self.panel1.GetSizer().Show(self.panel1.SIZER_rm, False, True)
            self.panel1.GetSizer().Show(self.panel1.SIZER_ru, True, True)
        self.panel1.Layout()
       
    def OnRadio(self, event):
        self.TransferDataToWindow()

class Panel_1(wx.Panel):
    def __init__(self, parent, id,
        pos = wx.DefaultPosition, size = wx.DefaultSize,
        style = wx.TAB_TRAVERSAL ):
        wx.Panel.__init__(self, parent, id, pos, size, style)
             
        item0 = wx.BoxSizer( wx.HORIZONTAL )#wx.VERTICAL )       
        # links
        item1 = wx.BoxSizer( wx.VERTICAL )#wx.HORIZONTAL )
        self.SIZER_1 = item1
               
        item2 = wx.StaticText( self, -1, "text", wx.DefaultPosition, wx.DefaultSize, 0 )
        item1.Add( item2, 0, wx.ALIGN_CENTER|wx.ALL, 5 )

        item3 = wx.StaticText( self, -1, "text", wx.DefaultPosition, wx.DefaultSize, 0 )
        item1.Add( item3, 0, wx.ALIGN_CENTER|wx.ALL, 5 )

        item0.Add( item1, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
       
        # mitte
        item4 = wx.BoxSizer( wx.VERTICAL )#wx.FlexGridSizer( 0, 2, 0, 0 )
        self.SIZER_2 = item4
       
        self.Radio1 = wx.RadioButton( self, -1, "Radio", wx.DefaultPosition, wx.DefaultSize, wx.RB_GROUP )
        item4.Add( self.Radio1, 0, wx.ALIGN_CENTER|wx.ALL, 5 )

        self.Radio2 = wx.RadioButton( self, -1, "Radio", wx.DefaultPosition, wx.DefaultSize, 0 )
        item4.Add( self.Radio2, 0, wx.ALIGN_CENTER|wx.ALL, 5 )

        self.Radio3 = wx.RadioButton( self, -1, "Radio", wx.DefaultPosition, wx.DefaultSize, 0 )
        item4.Add( self.Radio3, 0, wx.ALIGN_CENTER|wx.ALL, 5 )

        item0.Add( item4, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
       
        #rechts
        item9 = wx.BoxSizer( wx.VERTICAL )
        # rechts oben
        item10 = wx.BoxSizer( wx.HORIZONTAL )
        self.SIZER_ro = item10
        item13 = wx.TextCtrl(self,-1,"oben")
        item10.Add( item13, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
       
        # rechts mitte
        item11 = wx.BoxSizer( wx.HORIZONTAL )
        self.SIZER_rm = item11
        item14 = wx.StaticText( self, -1, "mitte")
        item11.Add( item14, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
       
        # rechts unten
        item12 = wx.BoxSizer( wx.HORIZONTAL )
        self.SIZER_ru = item12
        item15 = wx.Button(self,-1,"unten")#wx.TextCtrl(self,-1,"unten")
        item12.Add( item15, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
       
        item9.Add( item10, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
        item9.Add( item11, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
        item9.Add( item12, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
       
        item0.Add( item9, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
       
        self.SetSizer(item0)
        item0.SetSizeHints( self )

if __name__ == "__main__":
    app = wx.PySimpleApp()
    frm = wx.Frame(None,-1,"test")
    frm.CentreOnScreen(wx.BOTH)
    frm.Show()
    pnl = DialogMain(frm,-1,"bla")
    pnl.ShowModal()
    app.MainLoop()


Ich habe ja schon Teile deaktiviert und die Event-Methode durch ein einziges "print" ersetzt, aber selbst bis dort kommt die Anwendung leider nicht.

Ich muss gerade warten, bis mein Kollege mich an seinen Win2000 Rechner lässt, damit ich mal den anderen Start ausprobiere. Gerold, werde deinen Hinweisen nachgehen.

Barbara
BW
User
Beiträge: 25
Registriert: Dienstag 20. März 2007, 10:25

Beitragvon BW » Mittwoch 7. November 2007, 08:57

ein Start mit python -i modulname.py gibt mir immer noch keine Fehlermeldung zurück und ändert auch nichts am Verhalten.
Dann begebe ich mich mal ans debuggen...
Barbara
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 7. November 2007, 09:00

Hallo Barbara!

Probier mal aus:

Code: Alles auswählen

    def OnRadio(self, event):
        self.TransferDataToWindow()
        event.Skip()

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BW
User
Beiträge: 25
Registriert: Dienstag 20. März 2007, 10:25

Beitragvon BW » Mittwoch 7. November 2007, 09:09

Hallo Gerold,
leider keine Veränderung...
Barbara
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 7. November 2007, 09:23

Hallo Barbara!

Eigentlich wollte ich dir in diesem Post aufzeigen, was ich an deinem Code anders machen würde und wo ich glaube, dass du Fehler machst. Aber ich habe es aufgegeben.

Das soll keine Beleidigung sein. Bitte fasse das nicht falsch auf. Es ist gut gemeinte Kritik.

Man müsste dein Programm komplett neu schreiben. Du operierst an manchen Stellen so umständlich und verworren, dass es mich wundert, dass das Beispiel überhaupt funktioniert.

Probiere mal dieses Beispiel http://www.python-forum.de/post-81569.html#81569 aus und versuche es zu verstehen. Vielleicht kannst du dann dein Programm so umschreiben, dass du mehrere **abgeschlossene** Einzelteile hast, die eigenständig agieren und (wenn man möchte) sogar ausgetauscht werden könnten, ohne dass der Rest des Programms etwas davon mit bekommt.

Damit lösen sich deine Probleme wahrscheinlich ganz von selbst. Ach ja, fast hätte ich es vergessen: ``<object>.Bind()`` gibt es schon seit einigen Jahren und sollte auch verwendet werden.

Es ist auch nie zu spät, sich der Lektüre von "wxPython in Action" zu widmen.

Nicht vergessen: Es ist gut gemeinte Kritik. ;-)

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 7. November 2007, 09:38

Hallo Barbara!

Dein größtes Problem ist wahrscheinlich ``TransferDataToWindow``. Darin machst du Sizer(???) sichtbar und unsichtbar. Das wird nichts.

Nimm stattdessen drei kleine Panels. Gib die Widgets in die Panels. Und mache diese Panels unsichtbar.

Je nachdem welche Option angeklickt wurde, kannst du dann das gewünschte Panel sichtbar machen. Spiele dich aber auf keinen Fall mit den Sizern.

Du darfst diese Panels nicht übereinander legen. Deshalb musst du zuerst das aktive Panel aus dem Sizer entfernen und danach das anzuzeigende Panel in den Sizer legen.
Beispiel: http://www.python-forum.de/topic-10536.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BW
User
Beiträge: 25
Registriert: Dienstag 20. März 2007, 10:25

Beitragvon BW » Mittwoch 7. November 2007, 16:37

Hallo Gerold,
das ist mir schon etwas länger bewusst, dass ich an meinem, ich nenne es mal, Stil arbeiten muss, aber ich lerne wxPython noch und kenne sicher nicht längst alle Möglichkeiten. Auch die objektorientierte Programmierung fällt mir noch nicht so leicht.

Ich habe bisher immer mit dem wxDesigner mir die Widgets zusammenstellen lassen. Ist das keine gute Idee? Meinen obigen Code habe ich halt annähernd der Ausgabe vom wxDesigner aufgeschrieben.

Aber mal abgesehen von dem Stil, wieso ist es denn dann möglich, dass auf dem XP Rechner die Sache ohne zu murren läuft aber auf der 2000der Kiste nicht? Meinst du wirklich, das liegt tatsächlich an den Sizern oder eben an den Events, die nicht in ihrer eigenen Klasse, sondern im Dialog behandelt werden?

Ich habe heute Nachmittag mal brav ein Panel so aufgebaut, wie in deinen Beispielen, aber auch das hat nicht geholfen...

Da bleibt mir wohl nichts anderes übrig als morgen weiter auf Suche zu gehen, woran das denn liegt...

Barbara
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 7. November 2007, 16:50

BW hat geschrieben:Aber mal abgesehen von dem Stil, wieso ist es denn dann möglich, dass auf dem XP Rechner die Sache ohne zu murren läuft aber auf der 2000der Kiste nicht? Meinst du wirklich, das liegt tatsächlich an den Sizern

Hallo Barbara!

Ja! Das ist wie bei Threads. Wenn man die nicht korrekt verwendet, dann funktioniert sie beim Einen, aber beim Anderen funktionieren sie nicht. (oft schon selber miterlebt)

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BW
User
Beiträge: 25
Registriert: Dienstag 20. März 2007, 10:25

Beitragvon BW » Donnerstag 8. November 2007, 13:46

Hallo Gerold,

na dann fange ich mal an ds Ganze zu überarbeiten und ich hoffe, dass du dann Recht behälst und es danach funktioniert.
Ansonsten melde ich mich noch mal. :wink:

Barbara
borgolte
User
Beiträge: 1
Registriert: Samstag 10. November 2007, 12:21

Beitragvon borgolte » Samstag 10. November 2007, 12:28

gerold hat geschrieben:Dein größtes Problem ist wahrscheinlich ``TransferDataToWindow``. Darin machst du Sizer(???) sichtbar und unsichtbar. Das wird nichts.


Hallo Gerold.
Warum kann man keine Sizer innerhalb anderer Sizer sichtbar und unsichtbar machen? Kannst Du da vielleicht einen entsprechenden Link auf die Dokumentation liefern? So wie ich es bisher verstehe, lassen sich alle Sizeritems sichtbar und unsichtbar machen. Und offensichtlich hat das ja auch bisher funktioniert.

Viele Grüße
chris
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Samstag 10. November 2007, 16:13

Hallo Barbara!

Vielleicht kannst du damit etwas anfangen:

Code: Alles auswählen

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

import wx
import wx.lib.newevent


class BaseActionPanel(wx.Panel):
    """
    Von diesem Panel erben die anderen Action-Panels. Das muss nicht sein, kann
    aber in größeren Programmen die Arbeit erleichtern, da hier die Eigenschaften
    aller abgeleiteten Panels gemeinsam verändert werden können.
    """
   
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, style = wx.TAB_TRAVERSAL | wx.BORDER)
       
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.vbox)
       
        self.lab_hinweis = wx.StaticText(self)
        self.vbox.Add(self.lab_hinweis, 0, wx.ALL, 5)


class ActionPanel1(BaseActionPanel):
    """
    Zeigt ein paar Widgets an
    """
   
    def __init__(self, parent):
        BaseActionPanel.__init__(self, parent)
        #self.SetBackgroundColour("green")
       
        self.lab_hinweis.SetLabel(u"Action Panel 1")
       
        btn_hallo = wx.Button(self, label = u"Hallo")
        self.vbox.Add(btn_hallo, 0, wx.ALL, 5)
        btn_hallo.Bind(wx.EVT_BUTTON, self.say_hello)
   
   
    def say_hello(self, event = None):
        app = wx.GetApp()
        if app.world:
            wx.MessageBox("Hallo Welt")
        else:
            wx.MessageBox("Hallo Mond")


class ActionPanel2(BaseActionPanel):
    """
    Zeigt ein paar Widgets an
    """
   
    def __init__(self, parent):
        BaseActionPanel.__init__(self, parent)
        #self.SetBackgroundColour("yellow")
       
        self.lab_hinweis.SetLabel(u"Action Panel 2")
       
        chk_welt = wx.CheckBox(self, label = u"Welt")
        self.vbox.Add(chk_welt, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5)
        chk_welt.Bind(wx.EVT_CHECKBOX, self.set_world)
   
   
    def set_world(self, event):
        app = wx.GetApp()
        event_object = event.GetEventObject()
        app.world = event_object.GetValue()
   

class ControlPanel(wx.Panel):
    """
    Panel mit zwei Radio-Buttons.
    """
   
    # Event-Klasse und Eventbinder-Funktion erstellen
    (ActionSelectedEvent, EVT_ACTION_SELECTED) = wx.lib.newevent.NewEvent()
   
   
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
       
        vbox = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(vbox)
       
        rad_action1 = wx.RadioButton(self, label = u"Action 1", name = "action1")
        vbox.Add(rad_action1, 0, wx.ALL, 5)
        rad_action1.Bind(wx.EVT_RADIOBUTTON, self.on_action_selected)
           
        rad_action2 = wx.RadioButton(self, label = u"Action 2", name = "action2")
        vbox.Add(rad_action2, 0, wx.ALL, 5)
        rad_action2.Bind(wx.EVT_RADIOBUTTON, self.on_action_selected)
   
   
    def on_action_selected(self, event):
        """
        Eventhandler für die RadioButtons
       
        Gibt den Namen des ausgewählten RadioButtons als Attribut des
        ausgelösten Events weiter.
        """
       
        event_object = event.GetEventObject()
        action_name = event_object.GetName()
       
        evt = self.ActionSelectedEvent()
        evt.selected_action = action_name
       
        self.ProcessEvent(evt)
   
   
class MyDialog(wx.Dialog):
    """
    Irgendein Dialog
    """
   
    def __init__(self, parent = None):
        wx.Dialog.__init__(self, parent, title = u"Servus")
       
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(vbox_main)
       
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        vbox_main.Add(hbox, 1, wx.EXPAND | wx.ALL, 5)
        self.hbox = hbox
       
        control_panel = ControlPanel(self)
        self.control_panel = control_panel
        hbox.Add(control_panel, 0)
        control_panel.Bind(control_panel.EVT_ACTION_SELECTED, self.on_action_selected)
       
        self.action_panel_1 = ActionPanel1(self)
        self.action_panel_1.Hide()
       
        self.action_panel_2 = ActionPanel2(self)
        self.action_panel_2.Hide()
       
        self.current_action_panel = None
   
   
    def on_action_selected(self, event):
        """
        Reagiert auf die Action-Änderungen
        """
       
        self.Freeze()
       
        if self.current_action_panel:
            self.current_action_panel.Hide()
            self.hbox.Detach(self.current_action_panel)
       
        selected_action = event.selected_action
        self.current_action_panel = {
            "action1": self.action_panel_1,
            "action2": self.action_panel_2,
        }[selected_action]
        self.hbox.Add(self.current_action_panel, 1, wx.EXPAND | wx.ALL, 5)
        self.current_action_panel.Show()
        self.Layout()
       
        self.Thaw()


class MyApp(wx.PySimpleApp):
   
    world = False
   
    def OnInit(self):
       
        diag = MyDialog()
        diag.ShowModal()
        return True


def main():
    app = MyApp()


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.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder