Reputation: 776
Hello I am trying to have one scrollbar bind to a text widget and a listbox - is this possible? I want them to synchronously scroll together; basically, the listbox will hold the line numbers of the text widget; like an editor. The code I am trying goes like this:
grid [ttk::frame $f] -column 0 -row 0 -sticky nswe;
grid [tk::listbox $f.num -width 4 -background #EBEBEB -foreground #7AA3CC \
-yscrollcommand "set_scroll $s" -relief flat] -column 0 -row 0 -sticky nswe;
grid [tk::text $n -state normal -wrap word -yscrollcommand "set_scroll $s"] -row 0 -column 1 -sticky nswe;
grid [ttk::scrollbar $s -orient vertical -command {sync_scroll "$f.num $n" yview}] -row 0 -column 2 -sticky nes;
#Sets the scrollbar to the text and listbox widgets
proc set_scroll {scroll_widget args} {
eval [list $scroll_widget set] $args;
eval [$scroll_widget cget -command] [list moveto [lindex [$scroll_widget get] 0]];
return;
}
#Synchronizes their scrolling
proc sync_scroll {widgets args} {
foreach w $widgets {eval [list $w] args}
return;
}
I saw this solution here: How to implement tk scrollbar for multiple listboxes (TCL)?
The problem is it's not working for me exactly. When I click on the scrollbar and drag it to scroll, it only scrolls my text widget; When I use the mouse wheel while my pointer is within the text widget, it still only scrolls the text widget. However, if I scroll with the mouse wheel while the pointer is over the listbox, both widgets scroll synchronously as they are supposed to. What's going on?
1: Did I do something wrong in my code?
2: Is this supposed to work with two different types of widgets like I am trying to do?
3: This above code, as mentioned in that linked post, works for Tk 8.4; I'm using tcl/tk 8.6. Would there be any issues for me regarding that version disparity?
4: Is this the best way to achieve what I am trying to do? My goal is to get the same effect as text editors like notepad++ or any IDE; with a section to the left keeping track of line numbers. This is working so far, but I'm not having a good time with these multi-scrolling issues.
Upvotes: 0
Views: 1114
Reputation: 137567
The first obvious problem is that you do: {sync_scroll "$f.num $n" yview}
when you'd be better using [list sync_scroll [list $f.num $n] yview]
. The second obvious problem is:
foreach w $widgets {eval [list $w] args}
As the author of the question you took the code from (;-) I can say for sure that args
refers to a variable which you want to read. Tcl's always explicit about that sort of thing; it really differentiates between mention and use of variables and commands. The code should be:
foreach w $widgets {$w {*}$args}
You're using 8.6, so you can use significantly less tricky idioms than eval
! (This is basically the code from the top half of my prior answer.)
Yes. It should work with two different widgets as long as you're scrolling in the same direction. I suppose you could hack it to scroll one widget horizontally in sync with another vertically, but why would you do that!?
Tk 8.6 is pretty similar to 8.5 in a very large number of respects, and not really all that hugely different to 8.4. (My tip of the day: the less effort you put into squeezing every little bit of customizability out widgets, the easier the version upgrades are. Tk has genuinely sensible defaults.) The main differences (8.4->8.5) that you're likely to notice are:
ttk
namespace).The main changes to 8.6 shouldn't affect what you're doing. (Native PNG support, rotated text on the canvas, stuff like that.) The script-visible changes from 8.5 to 8.6 in Tk are really quite small.
Consider using a ctext
widget from Tklib. It's a megawidget — scripted widget — that has a number of capabilities defined for you. In particular, you can turn on the -linemap
option to get a listing of line numbers on the left of the widget (I think it might be switched on my default, FWIW).
Upvotes: 2