The last time I posted a question here, I got a rather nasty response, so please just constructive stuff!

I want to make a scrollable entrybox for Tkinter GUI, the scrollbar shows up and works, but text does not move. Am I missing something?

import Tkinter as tk
 
root = tk.Tk()
 
enter1 = tk.Entry(root, bg='yellow', width=30)
enter1.grid(row=0, column=0)
 
# create a horizontal scrollbar at bottom of enter1
# (similar to code shown for a listbox)
xscroll = tk.Scrollbar(orient='horizontal', command=enter1.xview)
xscroll.grid(row=1, column=0, sticky='ew')
enter1.configure(xscrollcommand=xscroll.set)
 
enter1.insert('end', 'just a very long sentence to put into the enter space')
 
root.mainloop()

So I usually test my Tkinter apps from IDLE; in this case, I get the following error message every 'pixel' I scroll:

Traceback (most recent call last):
  File "C:\Python24\lib\lib-tk\Tkinter.py", line 1345, in __call__
    return self.func(*args)
TypeError: xview() takes exactly 2 arguments (3 given)

I interpret that to mean that enter1 is passing too many arguments to xview.

Sure 'nuff, when we examine what gets passed ...

import Tkinter as tk

def wrapper(master, *args):
    # intercept the arguments and print before passing along
    print args
    enter1.xview(master,*args)
    
root = tk.Tk()
 
enter1 = tk.Entry(root, bg='yellow', width=30)
enter1.grid(row=0, column=0)
 
# create a horizontal scrollbar at bottom of enter1
# (similar to code shown for a listbox)
xscroll = tk.Scrollbar(orient='horizontal', command=wrapper) # <<<
xscroll.grid(row=1, column=0, sticky='ew')
enter1['xscrollcommand']=xscroll.set
 
enter1.insert('end', 'just a very long sentence to put into the enter space')
 
root.mainloop()

We get lots of these:

('0.0065',)
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python24\lib\lib-tk\Tkinter.py", line 1345, in __call__
    return self.func(*args)
  File "C:/Python24/scrollentry.py", line 5, in wrapper
    enter1.xview(master,*args)
TypeError: xview() takes exactly 2 arguments (3 given)

Which indicates that entry widgets are somehow passing a tuple instead of a single argument on to xview. On the hunt...

def wrapper(master, *args):
    print args
    enter1.xview(args[0])

yields

TclError: bad entry index "0.0839"

Hmm... wonder what arguments are supposed to be passed? AH-HA: according to the manual,

The Entry widget does not have an .xview() method. See
Section 8.1, “Scrolling an Entry widget” (p. 32).

And from p. 32,


Making an Entry widget scrollable requires a little extra code on your part to adapt the Scrollbar
widget's callback to the methods available on the Entry widget. Here are some code fragments illustrating
the setup. First, the creation and linking of the Entry and Scrollbar widgets:

self.entry = Entry ( self, width=10 )
self.entry.grid(row=0, sticky=E+W)
self.entryScroll = Scrollbar ( self, orient=HORIZONTAL,
command=self.__scrollHandler )
self.entryScroll.grid(row=1, sticky=E+W)
self.entry["xscrollcommand"] = self.entryScroll.set

def __scrollHandler(self, *L):
    op, howMany = L[0], L[1]
    if op == "scroll":
    units = L[2]
    self.entry.xview_scroll ( howMany, units )
    elif op == "moveto":
    self.entry.xview_moveto ( howMany )

And sure nuff, this works:

import Tkinter as tk

def wrapper(*args):
    op, howMany = args[0], args[1]
    if op == "scroll":
        units = args[2]
        enter1.xview_scroll ( howMany, units )
    elif op == "moveto":
        enter1.xview_moveto ( howMany )
    
root = tk.Tk()
 
enter1 = tk.Entry(root, bg='yellow', width=30)
enter1.grid(row=0, column=0)
 
# create a horizontal scrollbar at bottom of enter1
# (similar to code shown for a listbox)
xscroll = tk.Scrollbar(orient='horizontal', command=wrapper)
xscroll.grid(row=1, column=0, sticky='ew')
enter1['xscrollcommand']=xscroll.set
 
enter1.insert('end', 'just a very long sentence to put into the enter space')
 
root.mainloop()

Hope it helps,
Jeff

Comments
well explained

Wow, that was quick detective work!
My problem was that I used PSPad for my editor and that does not show runtime error messages. So IDLE is good for some things!

The code works well, and I learned something new. Thanks for the well explained path to the truth. I shall follow it in the future.

This question has already been answered. Start a new discussion instead.