Problem mit der Return Taste und einem TextCtrl

Plattformunabhängige GUIs mit wxWidgets.
Antworten
basti33
User
Beiträge: 56
Registriert: Donnerstag 24. August 2006, 15:05

Hallo,

in einem kleinen Programm habe ich ein TextCtrl, in das der Benutzer etwas eingeben soll. Wenn er fertig ist, soll er seine Eingabe mit Return (WXK_RETURN) bestätigen. Jetzt habe ich das Problem, dass das TextCtrl in diesem Moment nicht den Eventhandler startet, sondern versucht, zum nächsten Widget zu springen, das es aber nicht gibt. Das Verhalten wundert mich ein bisschen, da dafür doch eigentlich die TAB-Taste zuständig wäre. Wie kann ich es schaffen, dass Return für den Zweck "umbelegt" wird?

Danke

P.S.: Das Programm ist für Win XP und das TextCtrl ist in einem Frame
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Hi.

Das Event `wx.EVT_TEXT_ENTER` an die gewünschte Instanz vom `wx.TextCtrl` binden.

Code: Alles auswählen

import wx


class MainFrame(wx.Frame):
    def __init__(self, parent=None, id=-1, title = "MyApp"):
         wx.Frame.__init__(self, parent, id, title)
         self.panel = wx.Panel(self) 
         self.txt1 = wx.TextCtrl(self.panel)
         self.txt2 = wx.TextCtrl(self.panel, pos=(120, 0))
         
         self.txt1.Bind(wx.EVT_TEXT_ENTER, self.OnReturnTxt1)
     
    def OnReturnTxt1(self, event):
        self.txt2.WriteText("Hello World!")
     
def main():
    app = wx.PySimpleApp()
    mf =  MainFrame()
    mf.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()
lg
basti33
User
Beiträge: 56
Registriert: Donnerstag 24. August 2006, 15:05

Vielen Dank.

Noch eine Frage: wieso betrifft das jetzt nur Windows und nicht Linux? Ist das eine Eigenheit von MFC, oder wie soll ich mir das vorstellen?

Danke
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Keine Ahnung. Hab nur Windows und wusste daher nicht das es unter Linux anders ist.

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

basti33 hat geschrieben:Ist das eine Eigenheit von MFC, oder wie soll ich mir das vorstellen?
Hi basti33!

Keine Ahnung! :K

Vielleicht hängt es auch damit zusammen, wie unter Windows mit Standard-Buttons umgegangen wird. Ich wollte dieses Verhalten ein wenig testen. Hier der Testcode von mir:

Code: Alles auswählen

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

import wx

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


class MyFrame(wx.Frame):
    
    def __init__(self, parent = None, id = -1, title = "Servus"):
        wx.Frame.__init__(self, parent, id, title)
        
        # Panel
        panel = wx.Panel(self)
        
        # Hauptsizer
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox_main)
        
        # Sizer für die Felder
        fgsizer = wx.FlexGridSizer(cols = 3, vgap = 3, hgap = 3)
        fgsizer.AddGrowableCol(1)
        vbox_main.Add(fgsizer, 1, wx.EXPAND | wx.ALL, 5)
        
        # Eingabefeld 1 - Label
        lab_eingabe1 = wx.StaticText(panel, -1, "Eingabefeld 1:")
        fgsizer.Add(lab_eingabe1, 0, wx.ALIGN_CENTER_VERTICAL)
        
        # Eingabefeld 1 - TextCtrl
        txt_eingabe1 = wx.TextCtrl(panel, name = "txt_eingabe1")
        fgsizer.Add(txt_eingabe1, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
        txt_eingabe1.Bind(wx.EVT_SET_FOCUS, self.on_textbox_setfocus)
        txt_eingabe1.AcceptsFocusFromKeyboard
        
        # Eingabefeld 1 - Button
        cmd_eingabe1 = wx.Button(panel, -1, "OK", name = "cmd_eingabe1")
        fgsizer.Add(cmd_eingabe1, 0, wx.ALIGN_CENTER_VERTICAL)
        self.cmd_eingabe1 = cmd_eingabe1
        cmd_eingabe1.Bind(wx.EVT_BUTTON, self.on_ok)
        
        # Eingabefeld 2 - Label
        lab_eingabe2 = wx.StaticText(panel, -1, "Eingabefeld 2:")
        fgsizer.Add(lab_eingabe2, 0, wx.ALIGN_CENTER_VERTICAL)
        
        # Eingabefeld 2 - TextCtrl
        txt_eingabe2 = wx.TextCtrl(panel, name = "txt_eingabe2")
        fgsizer.Add(txt_eingabe2, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
        txt_eingabe2.Bind(wx.EVT_SET_FOCUS, self.on_textbox_setfocus)
        
        # Eingabefeld 2 - Button
        cmd_eingabe2 = wx.Button(panel, -1, "OK", name = "cmd_eingabe2")
        fgsizer.Add(cmd_eingabe2, 0, wx.ALIGN_CENTER_VERTICAL)
        self.cmd_eingabe2 = cmd_eingabe2
        cmd_eingabe2.Bind(wx.EVT_BUTTON, self.on_ok)
        
        # Zentrieren
        self.Center()
    
    
    def on_textbox_setfocus(self, event):
        """
        Setzt den zugehörigen OK-Button auf "Default".
        """
        
        mappings = {
            "txt_eingabe1": self.cmd_eingabe1,
            "txt_eingabe2": self.cmd_eingabe2,
        }
        mappings[event.GetEventObject().GetName()].SetDefault()
    
    
    def on_ok(self, event):
        print event.GetEventObject().GetName()
    

def main():
    app = wx.PySimpleApp()
    f = MyFrame()
    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.
basti33
User
Beiträge: 56
Registriert: Donnerstag 24. August 2006, 15:05

Oh je, jetzt wollte ich das gerade ausprobieren und musste feststellen, dass wx.EVT_TEXT_ENTER nicht funktioniert.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

basti33 hat geschrieben:Oh je, jetzt wollte ich das gerade ausprobieren und musste feststellen, dass wx.EVT_TEXT_ENTER nicht funktioniert.
:shock: Wie funktioniert nicht? Der gepostet code von mir Funktioniert 100%ig und ist von mir vor dem Posten auch getestet worden.

Was genau funktioniert nicht? Kriegst du ein Traceback oder macht es nur nicht das, was es machen sollte?
basti33
User
Beiträge: 56
Registriert: Donnerstag 24. August 2006, 15:05

Ich habe den Code von dir kopiert und ausgeführt. Wenn ich Enter drücke, dann springt der Cursor nach wie vor zwischen den beiden Eingabefeldern hin und her, genauso wie wenn man TAB drückt. Welche Version von wxPython nimmst du denn? Ich habe nämlich die ganz neue (Versionsnummer ist mir gerade entfallen) und irgendwie den Verdacht, dass das ein ziemlicher Schrott ist.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Wenn `self.txt1` Fokussiert ist und du dann enter drückst, wird dann das an `self.txt1` gebundene Event `wx.EVT_TEXT_ENTER` ausgelöst, dass die Methode `self.OnReturnTxt1` ausführt.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

basti33 hat geschrieben:Ich habe den Code von dir kopiert und ausgeführt. Wenn ich Enter drücke, dann springt der Cursor nach wie vor zwischen den beiden Eingabefeldern hin und her, genauso wie wenn man TAB drückt. Welche Version von wxPython nimmst du denn? Ich habe nämlich die ganz neue (Versionsnummer ist mir gerade entfallen) und irgendwie den Verdacht, dass das ein ziemlicher Schrott ist.
Ohh :? Ich schau mal kurz.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Ich hab das Binary "wxPython2.6-win32-unicode-2.6.3.3-py25.exe" installiert.
basti33
User
Beiträge: 56
Registriert: Donnerstag 24. August 2006, 15:05

sape hat geschrieben:Ich hab das Binary "wxPython2.6-win32-unicode-2.6.3.3-py25.exe" installiert.
Mit dieser Version geht es bei mir auch. Damit hab ich allerdings kein CollapsiblePane und das habe ich jetzt so praktisch verbaut. Vielleicht hätte ich doch gtk lernen sollen, irgendwie ist wxPython ja nicht das Wahre...
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Oh, da ist aber großer misst das da so ein Bug in der neuen Version ist :?

>> irgendwie ist wxPython ja nicht das Wahre...
Naja, ich bin mit wxPython eigentlich zu frieden. Es ist mMn die beste Alternative wenn ein Programm sich an das Native aussehen vom OS anpassen soll. GTK soll da unter Windows noch ziemlich bescheiden sein und ist unter Windows sehr langsam (Ob das auf neuere Releases zutrift weiß ich nicht. Hab das mal in nem Trhead hier gelesen). Und wxPython soll sowohl auf Linux und auch auf Windows ungefähr gleich schnell sein und sich dem aussehen anpassen.

OK, die wirklich schlechte Dokumentation ist echt oft frustrierend und artet in viel rumprobieren aus (Die von GTK ist viel besser). (BTW: Trift das aber auch auf die Dokumentation der mitgelieferten Python Libs zu. Die sind oft auch viel zu kurz und man muss da auch viel rumprobieren mangels guter Infos (Zu wenig bis gar keine Beispiele):? Naja, wie heißt es so "schön": programmiere schrieben keine Dokus sondern überlassen das anderen :/)


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

basti33 hat geschrieben:Oh je, jetzt wollte ich das gerade ausprobieren und musste feststellen, dass wx.EVT_TEXT_ENTER nicht funktioniert.
Hi basti33!

Du musst die TextCtrls mit ``style = wx.TE_PROCESS_ENTER`` erzeugen.
EVT_TEXT_ENTER(id, func):
Respond to a wxEVT_COMMAND_TEXT_ENTER event, generated when enter is pressed in a text control (which must have wxTE_PROCESS_ENTER style for this event to be generated).
wxTE_PROCESS_ENTER:
The control will generate the event wxEVT_COMMAND_TEXT_ENTER (otherwise pressing Enter key is either processed internally by the control or used for navigation between dialog controls).
Siehe: http://wxwidgets.org/manuals/2.8.0/wx_wxtextctrl.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
basti33
User
Beiträge: 56
Registriert: Donnerstag 24. August 2006, 15:05

Vielen, vielen Dank. Damit ist mein Problem jetzt gelöst. Ich sollte vielleicht öfter in der wxWidgets Doku nachschauen anstatt in der wxPython Doku.
Nirven
User
Beiträge: 130
Registriert: Mittwoch 10. Mai 2006, 08:18
Wohnort: Bremerhaven

Hi, den Style für das TextCtrl umzusetzen hat bei mir nicht ganz den gewünschten Erfolg gehabt. Zwar ist der Fokus nicht weitergesprungen, aber der Default-Button wurde auch nicht "ausgelöst".

Die Doku gab mir dann die Lösung zu diesem Problem, Button.SetDefault() funktioniert unter Windows nur in Dialogboxen. Statt dessen soll man wxTopLevelWindow::SetDefaultItem benutzen. Nachdem ich das gemacht hatte, wurde der Button ausgelöst, wenn ich irgendwo Return gedrückt habe , nur nicht in dem TextCtrl, das ich auf 'wx.TE_PROCESS_ENTER' gesetzt hatte.

Ist in diesem Fall auch Ok, wer in dem fenster Return drückt will das eigentlich genau so, nehm ich halt den Style für die eine TextCtrl wieder raus und es funktioniert überall.

Aber wie könnte ich denn diese Funktionalität nur für ein TextCtrl aktiviere, und bei allen anderen bleibt die ursprüngliche erhalten, also zum näöchsten Window springen?

Hat irgendjemand eine Idee dazu, wie das funktioniert? Oder seh ich grade etwas falsch, und es ist eigentlich ganz einfach?
Antworten