Multi-line wxTextCtrl in tabbed dialogs

Hi,

Pythonologist wrote:
> Hi,

Under W2K, when a wxTextCtrl within a dialog (with buttons and so on)
receives the focus via tabbing, it selects all the text. This is fine
and normal practice with single-line input fields. However, with multi-
line entry fields, I don't really like it because it is easy to his
space or suchlike and zap the entire contents. I'd prefer that the
cursor simply appears at the last insertion point as occurs when you
click (but this changes the insertion point!). I've tried installing
handlers for OnFocus and OnActivateFocus, and then calling
SetSelection() but without much luck.

Robin replied:

Use wxCallafter in the EVT_SET_FOCUS handler so your SetSelection call
will happen after the default focus handler selects the whole text.

txt = event.GetEventObject()

>end = txt.GetLastPosition()
>wxCallAfter(txt.SetSelection, pos, pos)

I am very glad to see somebody having the same problem I had (and I
still have). I already posted a lot of times about this issue, but never got a
satisfying answer. The problem is not a w2k, nor a wxDialog or a NoteBook
issue. It has nothing to do with "multiline" or style. It is a TextCtrl issue.
It seems, it is IMPOSSIBLE to unselect a text in such a control, as the
simple application below shows.
I tried a lot of things, EVT_SET_FOCUS , SetInsertionPoint, SetSelection,
wxTE_NOHIDESEL, mimicking a OnLeftDown event, Refreshing, different
styles, setiing focus to the panek, frame...no way to unselect the text. Even
replacing some part of the text by '' or 'zzz' does not work.

The only way to unselect the text in my example application,
is clicking on it.

Unselecting a text is doable in vb, java but not in wxPython.

You may argue, that unselecting is not important, but if you open
a text file and display it in the text control in the __init__ procedure,
the whole text is selected.

Despite all answers I got up to now, I'm still thinking that if this is not
a bug, it is a design mistake.

Beside this, do you know, you can set text in a text control
with a SetLabel statement instead of SetValue !?

**I submit (again) a small app, can somebody remove the selection?. I
mean unselect the text, not remove/delete it**

Jean-Michel Fauth, Switzerland

#-*- coding: iso-8859-1 -*-

···

#-------------------------------------------------------------------
# textctrlc.py
# win98se, Py 2.3, wxPy 2.4.2.4
# 4 November 2003
# Jean-Michel Fauth, Switzerland
#-------------------------------------------------------------------

from wxPython.wx import *

#-------------------------------------------------------------------

class MyPanel(wxPanel):

    def __init__(self, parent, id):
        wxPanel.__init__(self, parent, id, wxDefaultPosition, wxDefaultSize)

        #a single wxTextCtrl, default style
        self.tc = wxTextCtrl(self, 1001, '', wxPoint(8, 8), wxSize(450, 40))
        #self.tc.SetLabel('abcdef')
        self.tc.SetValue('abcdef')
        #abcdef is highlighted/selected
        print self.tc.GetInsertionPoint()
        #print 0, and the caret is at the end!
        self.tc.SetSelection(3, 5)
        #nothing happens, caret still at the end
        #~ self.tc.Replace(1, 3, 'zzz')
        #still whole selection!
        
        EVT_SET_FOCUS(self, self.OnSetFocus)
        
    def OnSetFocus(self, event):
        print 'OnSetFocus'

#-------------------------------------------------------------------

class MyFrame(wxFrame):

    def __init__(self, parent, id):
        title = 'textctrl et selection'
        style = wxSYSTEM_MENU | wxCAPTION | wxMINIMIZE_BOX
        wxFrame.__init__(self, parent, id, title, wxPoint(0, 0), \
                            wxSize(500, 500), style)
        self.panel = MyPanel(self, -1)

#-------------------------------------------------------------------

class MyApp(wxApp):

    def OnInit(self):
        frame = MyFrame(None, -1)
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

#-------------------------------------------------------------------

def main():
    app = MyApp(0)
    app.MainLoop()

#-------------------------------------------------------------------

if __name__ == "__main__" :
    main()

#eof-------------------------------------------------------------------

Jean-Michel Fauth wrote:

Hi,

Pythonologist wrote:

Hi,

Under W2K, when a wxTextCtrl within a dialog (with buttons and so on)
receives the focus via tabbing, it selects all the text. This is fine
and normal practice with single-line input fields. However, with multi-
line entry fields, I don't really like it because it is easy to his
space or suchlike and zap the entire contents. I'd prefer that the
cursor simply appears at the last insertion point as occurs when you
click (but this changes the insertion point!). I've tried installing
handlers for OnFocus and OnActivateFocus, and then calling
SetSelection() but without much luck.

Robin replied:

Use wxCallafter in the EVT_SET_FOCUS handler so your SetSelection call will happen after the default focus handler selects the whole text.

txt = event.GetEventObject()

>end = txt.GetLastPosition()
>wxCallAfter(txt.SetSelection, pos, pos)

I am very glad to see somebody having the same problem I had (and I
still have). I already posted a lot of times about this issue, but never got a satisfying answer. The problem is not a w2k, nor a wxDialog or a NoteBook
issue. It has nothing to do with "multiline" or style. It is a TextCtrl issue.
It seems, it is IMPOSSIBLE to unselect a text in such a control, as the
simple application below shows.
I tried a lot of things, EVT_SET_FOCUS , SetInsertionPoint, SetSelection,
wxTE_NOHIDESEL, mimicking a OnLeftDown event, Refreshing, different
styles, setiing focus to the panek, frame...no way to unselect the text. Even replacing some part of the text by '' or 'zzz' does not work.

The only way to unselect the text in my example application, is clicking on it.

Unselecting a text is doable in vb, java but not in wxPython.

You may argue, that unselecting is not important, but if you open
a text file and display it in the text control in the __init__ procedure,
the whole text is selected.

Despite all answers I got up to now, I'm still thinking that if this is not
a bug, it is a design mistake.

Beside this, do you know, you can set text in a text control
with a SetLabel statement instead of SetValue !?

**I submit (again) a small app, can somebody remove the selection?. I
mean unselect the text, not remove/delete it**

Sure. Just as I said above, you need to ensure that SetSelection is called *after* the default processing has happened, so in your example just add this to your __init__

         wxCallAfter(self.tc.SetSelection, 0, 0)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

In Tuesday, November 4, 2003, 1:39:24 PM, Jean-Michel wrote:

I am very glad to see somebody having the same problem I had (and
I still have). I already posted a lot of times about this issue,
but never got a satisfying answer. The problem is not a w2k, nor
a wxDialog or a NoteBook issue. It has nothing to do with
"multiline" or style. It is a TextCtrl issue. It seems, it is
IMPOSSIBLE to unselect a text in such a control, as the simple
application below shows.

I had the very same problem once and I only could get it working using
a kind of strange workaround: I first created a read only TextCtrl and
made it accept entries only after it receives the focus.

**I submit (again) a small app, can somebody remove the
selection?. I mean unselect the text, not remove/delete it**

My weird workaround does the trick, but I don't like it though:

class MyPanel(wxPanel):
    def __init__(self, parent, id):
        wxPanel.__init__(self, parent, id, wxDefaultPosition, wxDefaultSize)

        self.tc = wxTextCtrl(self, 1001, '', wxPoint(8, 8), wxSize(450, 40),style=wxTE_READONLY)
        self.tc.SetValue('abcdef')
        print self.tc.SetInsertionPoint(0)
        self.tc.SetSelection(3, 5)
        self.tc.SetFocus()

        EVT_SET_FOCUS(self, self.OnSetFocus)

    def OnSetFocus(self, event):
        print 'OnSetFocus'
        self.tc.SetEditable(1)

HTH

-- Tacão