text cut off in single-line wxTextCtrl

I've encountered what appears to be a bug in wxTextCtrl introduced in wxWindows 2.3.3. I'm testing with wxPython, Python 2.2, under MS Windows 98SE and 95, and the problem occurs with wxPython 2.3.3.1, 2.3.4.1, and 2.4.0.2, but not 2.3.2.1.

[I'm posting this to the wx-users list as well, because I suspect it is a wxWindows bug. I don't have wxWindows built for MSW, so I can't readily check this with a C++ sample.]

I am creating a single-line text control as the first control in a
dialog or panel and specifying a non-empty value in the constructor. The text control is going to be added to a wxBoxSizer, so I use wxDefaultSize in the constructor.

When the dialog is initially displayed, the initial text is selected,
but the first part of the text appears cut off. The effect is the same
as if the contents of the control were too long to fit in the single-line control, and the control had therefore auto-scrolled to keep the cursor visible. In fact, the entire text is in the box, and if I scroll left past the visible start of the text, it auto-scrolls just like it would in that situation. The catch is that the text is NOT too long for the control.

I've attached a minimal sample in wxPython which demonstrates this effect (apologies again for not having a comparable C++ wxWindows sample). Note that depending on your font sizes, you may have to fiddle with the value of the initial test to make sure that it is long enough for the effect to occur but not so long that it actually doesn't fit in the text control at its final size.

If I make the initial value in the wxTextCtrl constructor an empty string, and then set it afterwards (e.g. with wxPython wxCallAfter or with a validator), the problem does not occur. Similarly, if I hard-code the size of the control instead of using wxDefaultSize and a box sizer, there is no problem. This leads me to suspect that the problem is caused by the text being set when the text control has default (i.e. 0?) width .

Also, the fact that the problem does not occur in wxPython 2.3.2.1 but does in wxPython 2.3.3.1 suggests that the bug may have been introduced at the same time as the default behavior of text controls was changed to select-all-on-focus.

David

cutoff.py (1.12 KB)

Just tested on Win ME, python 2.2.2, wxPy 2.4.0.2, and it displayed normally..?!

···

----- Original Message -----
From: David C. Fox
To: wx-users ; wxPython Users List
Sent: Saturday, February 22, 2003 4:56 AM
Subject: [wxPython-users] text cut off in single-line wxTextCtrl

I've encountered what appears to be a bug in wxTextCtrl introduced in
wxWindows 2.3.3. I'm testing with wxPython, Python 2.2, under MS
Windows 98SE and 95, and the problem occurs with wxPython 2.3.3.1,
2.3.4.1, and 2.4.0.2, but not 2.3.2.1.

[I'm posting this to the wx-users list as well, because I suspect it is
a wxWindows bug. I don't have wxWindows built for MSW, so I can't
readily check this with a C++ sample.]

I am creating a single-line text control as the first control in a
dialog or panel and specifying a non-empty value in the constructor.
The text control is going to be added to a wxBoxSizer, so I use
wxDefaultSize in the constructor.

When the dialog is initially displayed, the initial text is selected,
but the first part of the text appears cut off. The effect is the same
as if the contents of the control were too long to fit in the
single-line control, and the control had therefore auto-scrolled to keep
the cursor visible. In fact, the entire text is in the box, and if I
scroll left past the visible start of the text, it auto-scrolls just
like it would in that situation. The catch is that the text is NOT too
long for the control.

I've attached a minimal sample in wxPython which demonstrates this
effect (apologies again for not having a comparable C++ wxWindows
sample). Note that depending on your font sizes, you may have to fiddle
with the value of the initial test to make sure that it is long enough
for the effect to occur but not so long that it actually doesn't fit in
the text control at its final size.

If I make the initial value in the wxTextCtrl constructor an empty
string, and then set it afterwards (e.g. with wxPython wxCallAfter or
with a validator), the problem does not occur. Similarly, if I
hard-code the size of the control instead of using wxDefaultSize and a
box sizer, there is no problem. This leads me to suspect that the
problem is caused by the text being set when the text control has
default (i.e. 0?) width .

Also, the fact that the problem does not occur in wxPython 2.3.2.1 but
does in wxPython 2.3.3.1 suggests that the bug may have been introduced
at the same time as the default behavior of text controls was changed to
select-all-on-focus.

David

--------------------------------------------------------------------------------

from wxPython.wx import *

class MyFrame(wxFrame):
  def __init__(self, parent, ID, title):
    wxFrame.__init__(self, parent, ID, title, wxDefaultPosition,
        wxSize(200, 200))
    self.panel = MyPanel(self)

class MyPanel(wxPanel):
  def __init__(self, parent):
    wxPanel.__init__(self, parent, -1)
    self.initial = "the initial value"
    initial = self.initial
# initial = ""
    self.text = wxTextCtrl(self, -1, initial,
# wxDefaultPosition, wxSize(150, 30))
      wxDefaultPosition, wxDefaultSize)
    b = wxButton(self, -1, "Reset", wxDefaultPosition, wxDefaultSize)
    EVT_BUTTON(self, b.GetId(), self.on_reset)
    s = wxBoxSizer(wxVERTICAL)
    s.Add(self.text, 0, wxGROW)
    s.Add(b, 0)
    self.SetAutoLayout(1)
    self.SetSizer(s)
# wxCallAfter(self.do_reset)
  def do_reset(self):
    self.text.SetValue(self.initial)
  def on_reset(self, evt):
    self.do_reset()

class application(wxApp):
  def OnInit(self):
    frame = MyFrame(NULL, -1, "Hello, world")
    frame.Show(true)
    self.SetTopWindow(frame)
    return true

def run():
  app=application(0)
  app.MainLoop()

if __name__ =='__main__':
  run()

--------------------------------------------------------------------------------

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

I've done a few more experiments which clarify what is happening and why.

If I use wxDefaultSize for the text control, but don't use a sizer, the initial width of the control appears to be arbitrary (i.e. unrelated to the length of the initial value) but nonzero. In fact, the length of the text which is displayed after the sizer does its work is the same as this default width.

This suggests the following hypothesis:

1. The constructor, given wxDefaultSize, creates a text control of the default width.
2. It sets the value of the control to the initial value given to the constructor. If that value exceeds the default width, it will (correctly) appear cut off at the end.
3. When the focus is set to the text control (apparently before the sizer resizes everything), it selects the entire contents, leaving the insertion point at the end of the text (under the change to the text control on-focus behavior made in 2.3.3). Because the insertion point is now set at the end of the control, any value exceeding the current width of the control is cut off at the beginning.
4. When the sizer resizes the text control, the view of the contents is not updated to reflect the fact that the contents now does fit fully in the control.

Assuming this hypothesis is correct, the question now becomes, what can we do about it:

(a) perhaps something can be done to trigger the text control to re-display once it is resized (note that calling Refresh on the text control after the resizing does not help)

(b) perhaps the size chosen by wxTextCtrl with wxDefaultSize should be based on the initial contents (like wxButton or wxListBox)

(c) as I've mentioned, it is possible to work around the problem by specifying an empty string in the constructor and then using some mechanism (the TransferToWindow method of a validator, or wxCallAfter in wxPython) to set the "initial" value of the string. However, validators are a bit of a pain to use and seem like overkill if you only need one to set the initial value, which ought to be settable from the constructor. Therefore, it seems worthwhile to try to fix this, if it can be done without breaking existing code.

David C. Fox wrote:

···

I've encountered what appears to be a bug in wxTextCtrl introduced in wxWindows 2.3.3. I'm testing with wxPython, Python 2.2, under MS Windows 98SE and 95, and the problem occurs with wxPython 2.3.3.1, 2.3.4.1, and 2.4.0.2, but not 2.3.2.1.

I am creating a single-line text control as the first control in a
dialog or panel and specifying a non-empty value in the constructor. The text control is going to be added to a wxBoxSizer, so I use wxDefaultSize in the constructor.

When the dialog is initially displayed, the initial text is selected,
but the first part of the text appears cut off. The effect is the same
as if the contents of the control were too long to fit in the single-line control, and the control had therefore auto-scrolled to keep the cursor visible. In fact, the entire text is in the box, and if I scroll left past the visible start of the text, it auto-scrolls just like it would in that situation. The catch is that the text is NOT too long for the control.

Chris Munchenberg wrote:

Just tested on Win ME, python 2.2.2, wxPy 2.4.0.2, and it displayed normally..?!
From: David C. Fox To: wx-users ; wxPython Users List Sent: Saturday, February 22, 2003 4:56 AM
Subject: [wxPython-users] text cut off in single-line wxTextCtrl

Did you try fiddling with the value of self.initial? Remove the call to SetSizer, run the program, and just type into the box to see how long a string will fit in it with its default size. Then put the SetSizer call back, change the value of self.initial to something a few characters longer than that, and re-run it.

David

···

----- Original Message -----

You're right in your analysis of this bug in general and here in
particular, of course. But the problem is that the last time I tried to fix
it I spent more than an hour on this and finally decided to use the
workaround descibed above (i.e. just moved the code to set the initial
value in MyDialog::TransferDataToWindow() from the MyDialog ctor). Maybe
there is some simple fix for this which I overlooked, of course...

Sorry,
VZ

···

On Sat, 22 Feb 2003 13:38:12 -0500 "David C. Fox" <davidcfox@post.harvard.edu> wrote:

(c) as I've mentioned, it is possible to work around the problem by
specifying an empty string in the constructor and then using some
mechanism (the TransferToWindow method of a validator, or wxCallAfter in
wxPython) to set the "initial" value of the string. However, validators
are a bit of a pain to use and seem like overkill if you only need one
to set the initial value, which ought to be settable from the
constructor. Therefore, it seems worthwhile to try to fix this, if it
can be done without breaking existing code.

Chris Munchenberg wrote:

I am creating a single-line text control as the first control in a
dialog or panel and specifying a non-empty value in the constructor. The text control is going to be added to a wxBoxSizer, so I use wxDefaultSize in the constructor.

When the dialog is initially displayed, the initial text is selected,
but the first part of the text appears cut off. The effect is the same
as if the contents of the control were too long to fit in the single-line control, and the control had therefore auto-scrolled to keep the cursor visible. In fact, the entire text is in the box, and if I scroll left past the visible start of the text, it auto-scrolls just like it would in that situation. The catch is that the text is NOT too long for the control.

Although I can't duplicate it now I have seen this before. IIRC, in the wxPython demo I did a SetInsertionPoint(0) right after creating the control and that was a suitable workaround.

···

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