Seite 1 von 1

Problem mit der Return Taste und einem TextCtrl

Verfasst: Samstag 23. Dezember 2006, 19:28
von basti33
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

Verfasst: Samstag 23. Dezember 2006, 20:36
von sape
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

Verfasst: Samstag 23. Dezember 2006, 20:45
von basti33
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

Verfasst: Samstag 23. Dezember 2006, 21:10
von sape
Keine Ahnung. Hab nur Windows und wusste daher nicht das es unter Linux anders ist.

lg

Verfasst: Samstag 23. Dezember 2006, 21:35
von gerold
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
:-)

Verfasst: Samstag 23. Dezember 2006, 22:07
von basti33
Oh je, jetzt wollte ich das gerade ausprobieren und musste feststellen, dass wx.EVT_TEXT_ENTER nicht funktioniert.

Verfasst: Samstag 23. Dezember 2006, 22:18
von sape
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?

Verfasst: Samstag 23. Dezember 2006, 22:21
von basti33
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.

Verfasst: Samstag 23. Dezember 2006, 22:21
von sape
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.

Verfasst: Samstag 23. Dezember 2006, 22:22
von sape
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.

Verfasst: Samstag 23. Dezember 2006, 22:23
von sape
Ich hab das Binary "wxPython2.6-win32-unicode-2.6.3.3-py25.exe" installiert.

Verfasst: Samstag 23. Dezember 2006, 22:58
von basti33
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...

Verfasst: Samstag 23. Dezember 2006, 23:14
von sape
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

Verfasst: Samstag 23. Dezember 2006, 23:46
von gerold
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
:-)

Verfasst: Sonntag 24. Dezember 2006, 00:10
von basti33
Vielen, vielen Dank. Damit ist mein Problem jetzt gelöst. Ich sollte vielleicht öfter in der wxWidgets Doku nachschauen anstatt in der wxPython Doku.

Verfasst: Dienstag 27. Februar 2007, 14:29
von Nirven
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?