Auto scroll TextCtrl only when at bottom

Hey All,
I have been trying to figure this out and I can’t seem to get it to work. What I am trying to accomplish is to only auto scroll my output window when the user is looking at the last line of output. I am using a multi line txtctrl in which I am feeding output from a background process so there is almost always text going into the control. What I want is for the user to be able to look at lines of text without the output window jumping to the bottom( disable auto scroll), but when they are looking at the bottom line it should auto scroll for them. Right now I am not using append on the textctrl so I am not worring about wxPythons autoscroll, I am doig my scrollingmanually. The problem is I can’t figure out when I am looking at the last line in the text control. If the last line in the output is visable I want autoscroll, if the last line is not visable then I will not autoscroll.

Thanks!
-Nathan

Hi,
the specification is not quite clear to me, but it seems, that you
could use HitTest() for your task. See the sample displying the
currently visible lines in the title bar (on left-click).

hth,
vbr

test-wx-TextCtrl-visible-lines.py (1.24 KB)

···

2009/4/29 Nathan Fillhardt <fillbertz@gmail.com>:

Hey All,
I have been trying to figure this out and I can't seem to get it to work.
What I am trying to accomplish is to only auto scroll my output window when
the user is looking at the last line of output. I am using a multi line
txtctrl in which I am feeding output from a background process so there is
almost always text going into the control. What I want is for the user to be
able to look at lines of text without the output window jumping to the
bottom( disable auto scroll), but when they are looking at the bottom line
it should auto scroll for them. Right now I am not using append on the
textctrl so I am not worring about wxPythons autoscroll, I am doig my
scrollingmanually. The problem is I can't figure out when I am looking at
the last line in the text control. If the last line in the output is visable
I want autoscroll, if the last line is not visable then I will not
autoscroll.

Thanks!
-Nathan

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

############################################################

#! Python
# -*- coding: utf-8 -*-

import wx

def check_last_line_visible(evt=None):
    """
    display an info about the currently visible lines (title bar)
    """
    last_line_nr = testTxtCtrl.PositionToXY(testTxtCtrl.LastPosition)[1]
    first_visible_line = testTxtCtrl.HitTest((0, 5))[2] # 5 pixels
from the margin - arbitrary
    last_visible_line = testTxtCtrl.HitTest((0,
testTxtCtrl.GetSizeTuple()[1]-5))[2] # 5 px - ditto
    last_line_visibility = "VISIBLE" if first_visible_line <=
last_line_nr <= last_visible_line else "INVISIBLE" # first part not
needed for the last line
    info_txt = u"top vis.: %s; bottom vis.: %s; last line: %s; last
line is %s" % (first_visible_line, last_visible_line, last_line_nr,
last_line_visibility)
    frm.SetTitle(info_txt)

    evt.Skip()

appl = wx.App(redirect=False)
frm = wx.Frame(None, -1, "Last line - ??", size = (500, 500))

testTxtCtrl = wx.TextCtrl(frm, -1, style=wx.TE_MULTILINE | wx.TE_RICH2

wx.WANTS_CHARS) #

testTxtCtrl.SetValue("\n".join(str(x).zfill(9) for x in range(0,101)))

testTxtCtrl.Bind(wx.EVT_LEFT_UP, check_last_line_visible)

sizerFrm = wx.BoxSizer(wx.HORIZONTAL)
sizerFrm.Add(testTxtCtrl, 1, wx.EXPAND)
frm.SetSizer(sizerFrm)

frm.Show()
appl.MainLoop()

############################################################

Nathan Fillhardt wrote:

Hey All,
I have been trying to figure this out and I can't seem to get it to work. What I am trying to accomplish is to only auto scroll my output window when the user is looking at the last line of output. I am using a multi line txtctrl in which I am feeding output from a background process so there is almost always text going into the control. What I want is for the user to be able to look at lines of text without the output window jumping to the bottom( disable auto scroll), but when they are looking at the bottom line it should auto scroll for them. Right now I am not using append on the textctrl so I am not worring about wxPythons autoscroll, I am doig my scrollingmanually. The problem is I can't figure out when I am looking at the last line in the text control. If the last line in the output is visable I want autoscroll, if the last line is not visable then I will not autoscroll.

If you're not locked in to using a wx.TextCtrl for some reason then it would be fairly easy to create a custom widget that displays text and behaves that way. Otherwise, there are enough variations in the native text widgets that doing that consistently will be tricky at best.

···

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

Robin Dunn wrote:

Nathan Fillhardt wrote:

Hey All,
I have been trying to figure this out and I can't seem to get it to
work. What I am trying to accomplish is to only auto scroll my output
window when the user is looking at the last line of output. I am using a
multi line txtctrl in which I am feeding output from a background
process so there is almost always text going into the control. What I
want is for the user to be able to look at lines of text without the
output window jumping to the bottom( disable auto scroll), but when they
are looking at the bottom line it should auto scroll for them. Right now
I am not using append on the textctrl so I am not worring about
wxPythons autoscroll, I am doig my scrollingmanually. The problem is I
can't figure out when I am looking at the last line in the text control.
If the last line in the output is visable I want autoscroll, if the last
line is not visable then I will not autoscroll.

If you're not locked in to using a wx.TextCtrl for some reason then it
would be fairly easy to create a custom widget that displays text and
behaves that way. Otherwise, there are enough variations in the native
text widgets that doing that consistently will be tricky at best.

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

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Robin,

Can you point me in the right direction here? I too would like to know how
to create a 'logging' window. (i.e. a text window which is continually
appending text to the end and normally scrolls up except when the user has
moved the scroll bar thumb off from bottom to examine past history and
resumes scrolling when the user has moved the scroll bar thumb back to the
bottom.) I am sure a class for this already exists but I don't know where.
I am willing to create custom widget as you suggest ... but I need a few
hints on how to proceed.

Trevor

···

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/Auto-scroll-TextCtrl-only-when-at-bottom-tp2371998p3360550.html
Sent from the wxPython-users mailing list archive at Nabble.com.

trevor wrote:

Can you point me in the right direction here? I too would like to know how
to create a 'logging' window. (i.e. a text window which is continually
appending text to the end and normally scrolls up except when the user has
moved the scroll bar thumb off from bottom to examine past history and
resumes scrolling when the user has moved the scroll bar thumb back to the
bottom.) I am sure a class for this already exists but I don't know where.
I am willing to create custom widget as you suggest ... but I need a few
hints on how to proceed.

I use a stock standard list box for exactly this purpose. You can use
SetFirstItem to scroll the proper item into view. You can even use the
standard cut-and-paste keystrokes to grab a copy for saving. (For
example, Ctrl-A, Ctrl-C to copy all.)

Your requirements for the scroll bar are a bit contradictory. You might
need to provide a checkbox to enable "auto scroll", so they can disable
auto scroll while they scroll backwards.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Thank you for your response. I am sorry for being unclear. I am not asking
for anything unusual. All linux terminal windows behave this way. A
terminal window allows the user to scroll backwards at any time and to leave
it there WHILE AT THE SAME TIME new text is being appended at the end
(although the user won't see it until/unless he scrolls the window back down
to the bottom.

The wx.TextCtrl behaves exactly the same except that if/when new data is
appended, the window is automatically scrolled down to the bottom.
Basically, forcing the user to see the new data immediately.

What I would like in my custom/extended TextCtrl is for it to be scroll bar
thumb aware when appending new text. If the thumb is at the bottom, then
behave normally (i.e. append and scroll). If the thumb is not at the bottom
(i.e. the user is looking historical data), then just append the new data to
the end but leave the scrolled position alone thus allowing the user to
continue viewing previous lines for whatever length of time s/he needs.

Is that clearer?

···

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/Auto-scroll-TextCtrl-only-when-at-bottom-tp2371998p3360618.html
Sent from the wxPython-users mailing list archive at Nabble.com.

I asked about this before, and I think the answer was that it simply isn’t possible using the TextCtrl - you’d have to draw a custom widget. It may be possible to work around the problem by subclassing and overriding AppendText, but the result isn’t going to be very pretty.

-Nat

···

On Thu, Jan 27, 2011 at 3:30 PM, trevor trevor.christensen@hill.af.mil wrote:

The wx.TextCtrl behaves exactly the same except that if/when new data is

appended, the window is automatically scrolled down to the bottom.

Basically, forcing the user to see the new data immediately.

What I would like in my custom/extended TextCtrl is for it to be scroll bar

thumb aware when appending new text. If the thumb is at the bottom, then

behave normally (i.e. append and scroll). If the thumb is not at the bottom

(i.e. the user is looking historical data), then just append the new data to

the end but leave the scrolled position alone thus allowing the user to

continue viewing previous lines for whatever length of time s/he needs.

Nat Echols wrote:

The wx.TextCtrl behaves exactly the same except that if/when new data is
appended, the window is automatically scrolled down to the bottom.
Basically, forcing the user to see the new data immediately.

What I would like in my custom/extended TextCtrl is for it to be scroll
bar
thumb aware when appending new text. If the thumb is at the bottom, then
behave normally (i.e. append and scroll). If the thumb is not at the
bottom
(i.e. the user is looking historical data), then just append the new data
to
the end but leave the scrolled position alone thus allowing the user to
continue viewing previous lines for whatever length of time s/he needs.

I asked about this before, and I think the answer was that it simply isn't
possible using the TextCtrl - you'd have to draw a custom widget. It may
be
possible to work around the problem by subclassing and overriding
AppendText, but the result isn't going to be very pretty.

I suspected as much. I have already done the subclassing/overriding but
without access to the scroll bar itself the solution is not elegant. I was
hoping that it was somehow possible to access the scroll bar widget/events
(i.e. wx.ScrollBar.GetThumbPosition(), etc.) I am just too inexperienced to
know all my options.

···

On Thu, Jan 27, 2011 at 3:30 PM, trevor > <trevor.christensen@hill.af.mil>wrote:

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/Auto-scroll-TextCtrl-only-when-at-bottom-tp2371998p3360639.html
Sent from the wxPython-users mailing list archive at Nabble.com.

yup -- and it sure seems like you should be able to do that pretty easily, but looking at the docs, there doesn't appear to be any way to programmaticly control the scrolling of a wx.TextCtrl -- odd, I'd sure think it would be common to want to scroll to a particular part of the text with a method call.

But if it's really not there, then you may have to roll your own. That may not be as hard as you think, particularly if it can be read-only and used a fixed width font.

Or us a list control instead, as suggested by another poster.

-Chris

···

On 1/27/11 3:30 PM, trevor wrote:

What I would like in my custom/extended TextCtrl is for it to be scroll bar
thumb aware when appending new text. If the thumb is at the bottom, then
behave normally (i.e. append and scroll). If the thumb is not at the bottom
(i.e. the user is looking historical data), then just append the new data to
the end but leave the scrolled position alone thus allowing the user to
continue viewing previous lines for whatever length of time s/he needs.

Is that clearer?

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Here is one way to do it.

* Start with a wx.ScrolledWindow that maintains a list of strings and is able to draw those strings in an EVT_PAINT handler, properly taking scrolling into account.

* When adding a new line of text, append it to the list and check the current scroll position. If the (former) end of the list is not in the visible area of the window then you are done. If both the beginning and the end of the list are visible then you just need to Refresh() and no extra scrolling is needed. Otherwise you should just need to scroll the window, that will move the existing pixels as needed and then "invalidate" the area exposed by the scroll and that will result in a paint event so you can draw the new text line and anything else that is in the window's update region.

···

On 1/27/11 2:13 PM, trevor wrote:

Can you point me in the right direction here? I too would like to know how
to create a 'logging' window. (i.e. a text window which is continually
appending text to the end and normally scrolls up except when the user has
moved the scroll bar thumb off from bottom to examine past history and
resumes scrolling when the user has moved the scroll bar thumb back to the
bottom.) I am sure a class for this already exists but I don't know where.
I am willing to create custom widget as you suggest ... but I need a few
hints on how to proceed.

--
Robin Dunn
Software Craftsman

Did anyone ever make a widget that does this for you?