Vee
Vee

Reputation: 776

Text widget/listbox synchronous multi-scrolling? (Tcl/Tk)

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

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137567

  1. 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.)

  2. 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!?

  3. 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:

    • More widgets (the ones in the ttk namespace).
    • Text widget scrolling was completely redone. Hopefully you won't have any problems from this.
       

    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.

  4. 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

Related Questions