EVT_SET_FOCUS und wx.ComboBox: unerwartetes Verhalten

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Benutzeravatar
Humbalan
User
Beiträge: 59
Registriert: Mittwoch 2. September 2009, 15:11

Hallo,

ich habe ein Probem mit EVT_SET_FOCUS. Arbeite unter Windows XP SP3, Python 2.6.2, wx-2.8-msw-unicod.

Das Problem:
Bei einer ComboBox binde ich an EVT_SET_FOCUS und EVT_KILL_FOCUS die entsprechenden Methoden onFocusSet und onFocusLost. Wenn ich die ComboBox mit der TAB-Taste 'betrete', wird nicht wie erwartet die Methode onFocusSet aufgerufen, sondern die Sequenz onFocusSet - onFocusLost - onFocusSet. Bei Mausklick in die ComboBox gibt es - wie erwartet - nur ein onFocusSet. Scheint ein auf die ComboBox beschränktes Phänomen zu sein, ein TextCtrl zeigt das nicht. Da wird sowohl bei Mausklick als auch bei TAB nur die onFocusSet-Methode aufgerufen.

Folgender Programmausschnitt reproduziert das Verhalten:

Code: Alles auswählen

import wx
class cMainFrame(wx.Frame):

    def __init__(self, parent, id, label):
        wx.Frame.__init__(self, parent, id, label)
        panel = wx.Panel(self, id)
       #----------------------------------------------------
        self.comboBox = wx.ComboBox(panel, -1, value='wx.ComboBox', choices=[ 'wx.ComboBox','zwei','drei'])
        self.comboBox.SetSelection(0)
        wx.EVT_SET_FOCUS (self.comboBox, self.onFocusSet_combo)
        wx.EVT_KILL_FOCUS(self.comboBox, self.onFocusLost_combo)
       #----------------------------------------------------
        self.textCtrl = wx.TextCtrl(panel, -1, 'wx.TextCtrl')
        wx.EVT_SET_FOCUS (self.textCtrl, self.onFocusSet_text)
        wx.EVT_KILL_FOCUS(self.textCtrl, self.onFocusLost_text)
       #----------------------------------------------------
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.textCtrl, 0, wx.ALL, 1)
        sizer.Add(self.comboBox, 0, wx.ALL, 1)
        panel.SetSizer(sizer)
        panel.Layout()

    def onFocusSet_combo(self, event):
        print 'onFocusSet_MyCombo()'
        event.Skip()

    def onFocusLost_combo(self, event):
        print 'onFocusLost_myCombo()'
        event.Skip()

    def onFocusSet_text(self, event):
        print '********************* onFocusSet_TextCtrl'
        event.Skip()

    def onFocusLost_text(self, event):
        print '********************* onFocusLost_TextCtrl'
        event.Skip()

myApp = wx.PySimpleApp(0)
myFrame = cMainFrame(None, -1, 'Test')

myApp.SetTopWindow(myFrame)
myFrame.Show()
myApp.MainLoop()
Mache ich etwas falsch?

Grüße und Danke
Humbalan
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

Hallo, also unter Ubuntu funktioniert das sowohl mit Mausklick als auch über die Tab Taste richtig. Am besten Robin Dunn berichten (in der wxPython Liste oder Google Groups IIRC), oder in den Bug tracker.
fhoech
User
Beiträge: 143
Registriert: Montag 9. April 2007, 18:26

Ich denke, dieses Verhalten wird dadurch hervorgerufen, dass die ComboBox als Kindelement ein TextCtrl enthält. Wird die ComboBox per TAB fokussiert, so erhält scheinbar (zumindest unter Windows) erst das Containerelement den Fokus, dann das enthaltene TextCtrl. Bei einem Klick erhält direkt das TextCtrl den Fokus. Bin auch der Meinung, dass das ein Bug ist.
Falls Du das TextCtrl in der ComboBox evtl. gar nicht brauchst, kannst Du ihr style=wx.CB_READONLY mitgeben oder stattdessen ein wx.Choice verwenden.
Benutzeravatar
Humbalan
User
Beiträge: 59
Registriert: Mittwoch 2. September 2009, 15:11

Vielen Dank für Eure Antworten.

@fhoech:
Unten ist die Klassenhierarchie einer Combobox (aus http://www.wxpython.org/docs/api/wx.ComboBox-class.html). Ich habe überhaupt nicht verstanden, wo Du da ein Kindelelement TextCtrl siehst.

Code: Alles auswählen

object --+                
         |                
    Object --+            
             |            
    EvtHandler --+        
                 |        
            Window --+    
                     |    
               Control --+
                         |
            object --+   |
                     |   |
         ItemContainer --+
                         |
                        ComboBox
Der einzige Unterschied zw. TextCtrl und ComboBox: ComboBox erbt von ItemContainer und Control, TextCtrl nur von Control. Da aber nur im Control-Zweig ein EvtHandler ist, ist so der zweite Aufruf von onFocusSet m. E. nicht zu erklären. V. a. wo kommt das onFocusLost her?
fhoech
User
Beiträge: 143
Registriert: Montag 9. April 2007, 18:26

Robin Dunn hat das glaube ich mal erklärt, dass eine ComboBox wx-intern nichts anderes ist als ein editierbares Textfeld in eben dieser Box, finde allerdings den entsprechenden Beitrag nicht mehr. Macht ja auch Sinn. Warum sollte man einen Teil der TextCtrl-Funktionalität für ComboBox neuerfinden?
Benutzeravatar
Humbalan
User
Beiträge: 59
Registriert: Mittwoch 2. September 2009, 15:11

Des leuchtet ein, auch weil die Klassenhierarchien fast identisch sind, wie Du unten siehst (gleiche Quelle wie oben):

Code: Alles auswählen

Type ComboBox             Type TextCtrl

object --+                object --+                
         |                         |                
    Object --+                Object --+            
             |                         |            
    EvtHandler --+            EvtHandler --+        
                 |                         |        
            Window --+                Window --+    
                     |                         |    
               Control --+               Control --+
                         |                         |
            object --+   |                         |
                     |   |                         |
         ItemContainer --+                         |
                         |                         |
                        ComboBox                  TextCtrl
Es ist also tatsächlich nichts neu erfunden worden, ComboBox erbt nur noch zusätzlich von ItemContainer. Nur: der von beiden geerbte Control-Zweig enthält als einziger einen EvtHandler. Warum also sollten sich diese beiden Widgtes - was das Event-Verhalten anbetrifft - überhaupt voneinander unterscheiden?

Übrigens: ich bewundere Leute, die ihre Software so klar strukturieren können, dass sie keine unnötige Arbeit (und nicht nur das!) haben. Ich hätte gern ein Scheibchen davon :)
fhoech
User
Beiträge: 143
Registriert: Montag 9. April 2007, 18:26

Warum also sollten sich diese beiden Widgtes - was das Event-Verhalten anbetrifft - überhaupt voneinander unterscheiden?
Gute Frage :) In den wx-Sourcen gibt es für verschiedene OS auch verschiedene cpp-Dateien für die Controls, evtl. ist es also wirklich ein Windows-spezifischer Bug.
Übrigens: ich bewundere Leute, die ihre Software so klar strukturieren können, dass sie keine unnötige Arbeit (und nicht nur das!) haben. Ich hätte gern ein Scheibchen davon
Nicht nur Du. Mir fallen alle Dinge, die ich hätte besser strukturieren können, immer erst im nachhinein auf (wenn überhaupt ;)).
Benutzeravatar
Humbalan
User
Beiträge: 59
Registriert: Mittwoch 2. September 2009, 15:11

Francesco hat geschrieben:Hallo, also unter Ubuntu funktioniert das sowohl mit Mausklick als auch über die Tab Taste richtig. Am besten Robin Dunn berichten (in der wxPython Liste oder Google Groups IIRC), oder in den Bug tracker.
Habe mir Francescos Rat zu Herzen genommen und mich beim Bug Tracker umgesehen: das Problem wurde vor über einem Jahr schon beschrieben, hat aber keiner etwas Substantielles dazu gesagt (ticket #10046). Allerdings hatte der Melder damals auch ein Monsterprogramm als Beispiel mitgeliefert, an das vielleicht keiner ranwollte. Hab mein Ding gepostet, mal sehn was passiert.
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

Hallo Humbalan, das ist gut. Ich würde trotzdem per mailing list die wxPython Leute (Robin Dunn) das nochmals mitteilen. Ich habe die Erfahrung gemacht, wenn man nur in die Bug Liste was einträgt, das kann schon mal einige Monate lang nicht behandelt werden... Vielleicht erfährst du dort ja auch einen evtl. Workaround bis dass es in einer neueren Version gefixt ist.
Antworten