ich validiere in einem Dialog Werte in TextCtrls und gebe via MessageDialog eine Fehlermeldung aus, wenn die Validierung fehlschlägt. Dabei bekomme ich das Verhalten der TextCtrls nicht in den Griff. Der Cursor verschwindet nach einer Fehlermeldung und der Focus ist auch nicht da, wo ich glaube, ihn gesetzt zu haben. Habe das Programm auf ein Minimum gestutzt, um nur die Fehlerumgebung testen zu können. Hier der Code (kurze Erklärung dazu weiter unten):
Code: Alles auswählen
# -*- coding: iso-8859-15 -*-
import wx
class CDlgBlahBase ( wx.Dialog ):
def __init__( self, parent ):
# Definiert das UI des Dialogs
wx.Dialog.__init__ ( self, parent, style = wx.CAPTION|wx.DEFAULT_DIALOG_STYLE )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer_blah = wx.BoxSizer( wx.VERTICAL )
gbSizer_blah = wx.GridBagSizer( 0, 0 )
gbSizer_blah.SetFlexibleDirection( wx.BOTH )
gbSizer_blah.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
bSizer_test = wx.BoxSizer( wx.HORIZONTAL )
bSizer_testname1 = wx.BoxSizer( wx.VERTICAL )
self.m_staticText_testname1 = wx.StaticText( self, wx.ID_ANY, u"Test 1" )
bSizer_testname1.Add( self.m_staticText_testname1, 0, wx.ALIGN_LEFT|wx.BOTTOM, 3 )
self.m_textCtrl_testname1 = wx.TextCtrl( self, wx.ID_ANY, u"Test 1", name=u"testname1" )
bSizer_testname1.Add( self.m_textCtrl_testname1, 0, wx.BOTTOM|wx.LEFT, 3 )
bSizer_test.Add( bSizer_testname1, 1, 0, 5 )
bSizer_testname2 = wx.BoxSizer( wx.VERTICAL )
self.m_staticText_testname2 = wx.StaticText( self, wx.ID_ANY, u"Test 2" )
bSizer_testname2.Add( self.m_staticText_testname2, 0, wx.ALIGN_LEFT|wx.BOTTOM, 3 )
self.m_textCtrl_testname2 = wx.TextCtrl( self, wx.ID_ANY, name=u"testname2" )
bSizer_testname2.Add( self.m_textCtrl_testname2, 0, wx.BOTTOM|wx.LEFT, 3 )
bSizer_test.Add( bSizer_testname2, 1, wx.EXPAND, 5 )
gbSizer_blah.Add( bSizer_test, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 2 ), wx.ALL|wx.EXPAND, 5 )
bSizerButtons = wx.BoxSizer( wx.HORIZONTAL )
self.m_button_ok = wx.Button( self, wx.ID_OK, u"OK", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizerButtons.Add( self.m_button_ok, 0, wx.ALL, 5 )
self.m_button_cancel = wx.Button( self, wx.ID_CANCEL, u"Abbrechen" )
bSizerButtons.Add( self.m_button_cancel, 0, wx.ALL, 5 )
gbSizer_blah.Add( bSizerButtons, wx.GBPosition( 1, 0 ), wx.GBSpan( 1, 1 ), wx.ALIGN_RIGHT|wx.BOTTOM|wx.TOP, 5 )
bSizer_blah.Add( gbSizer_blah, 1, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( bSizer_blah )
bSizer_blah.Fit( self )
class CMyDlg(CDlgBlahBase):
def __init__( self, parent ) :
CDlgBlahBase.__init__( self, parent )
self._defaultBgCol = self.m_textCtrl_testname1.GetBackgroundColour()
self.m_textCtrl_testname1.Bind( wx.EVT_KILL_FOCUS, self.on_kill_focus_testname )
self.m_textCtrl_testname2.Bind( wx.EVT_KILL_FOCUS, self.on_kill_focus_testname )
# Zur Verhinderung einer Fehlermeldung, wenn aufgrund einer Eingabe z. B. das Feld testname1 den Fokus
# an testname2 abgibt, dann ein Fehler-Popup den Fokus von testname2 killt.
self._fail_dict = {'test1':False, 'test2':False}
def set_focus( self, field ):
field.SetFocus()
def on_kill_focus_testname( self, event ) :
field = event.GetEventObject()
# Vorbereitungen
if field == self.m_textCtrl_testname1 :
test_no = 1
check_fail = u'test2'
elif field == self.m_textCtrl_testname2 :
test_no = 2
check_fail = u'test1'
else :
assert False
if self._fail_dict[check_fail] :
# Zur Verhinderung von doppelten Fehlermeldungen (siehe Kommentar von self._fail_dict)
event.Skip()
return
if field.GetValue( ) == u'' :
# Fehler: das Feld darf nicht leer sein
self._fail_dict[u'test{}'.format(test_no)] = True
field.SetBackgroundColour( u'pink' ) # Fehler wird sichtbar
# Leider ohne Quelle: habe irgendwo gelesen, dass SetFocus() nicht innerhalb eine kill_focus()-Methode
# aufgerufen werden soll:
wx.CallAfter( self.set_focus, field )
# Fehlermeldung.
wx.MessageDialog( self, u'Testname {} fehlt'.format(test_no), u'Fehler', wx.OK|wx.ICON_ERROR ).ShowModal()
else :
# Aufräumen, wenn der Fehler beseitigt ist.
self._fail_dict[u'test{}'.format(test_no)] = False
field.SetBackgroundColour( self._defaultBgCol )
self.Refresh()
event.Skip()
###################################################################################################################
class CTest( wx.Frame ) :
def __init__( self, parent ) :
wx.Frame.__init__( self, parent )
CMyDlg(self).ShowModal()
if __name__ == "__main__":
app = wx.App( redirect = False )
CTest( wx.Frame(None) )
(1) Mißlang die Validierung, weil das Feld beim Fokusverlust leer war, dann ist in diesem Feld nach Ausgabe der Fehlermeldung der Cursor verschwunden :K .
(2) Ist das Feld testname2 bei Fokusverlust leer, dann gilt (1) und zusätzlich ist der Fokus nicht wie vermutet in testname2, sondern testname1 :K .
Punkt (2) scheint mir besonders seltsam, da der Code genau der gleiche ist aber für die beiden Dialogfelder je unterschiedliches Verhalten hervorruft. Streiche ich den Aufruf von MessageDialog(), dann ist alles funzt es (nur kann ich leider auf die Fehlermeldung nciht verzichten).
Ich arbeite mit Python 2.7.2, wxPython 3.0.2.0 und Win 8.1
Kann jemand helfen?
Schönene Dank schon mal und Beste Grüße aus München
Humbalan