Search code examples
pythontkinterdialogwindowscrollbar

Adding a scroll bar to Tkinter with a long list of data


I currently have an issue with my Output in Tinker. So whenever I try to output my data read from a file the output dialog is too small to fit the huge list of data. For example:

screenshot with no scrollbars

The window is too large to display all my data so I looked into adding a scrollbar for the window in order to better fit the data and easily see all of it.

The issue arises in my code:

from Tkinter import *
import tkSimpleDialog
import tkMessageBox

root = Tk()
w = Label(root, text ="my Program")
w.pack()

tkMessageBox.showinfo("Welcome", "Add your welcome message here")

with open("Logs.txt", "rb") as f_input:
    start_token = tkSimpleDialog.askstring("Serial Number", "What is the device serial number?")
    end_token = tkSimpleDialog.askstring("End Keyword", "What is the end keyword")
    reText = re.search("%s(.*?)%s" % (re.escape(start_token + ",SHOWALL"), re.escape(end_token)), f_input.read(), re.S)
    if reText:
        output = reText.group(1)
        scrollbar = Scrollbar(root)
        scrollbar.pack( side = RIGHT, fill=Y, expand = False)

        mylist = Listbox(root, yscrollcommand = scrollbar.set )
        mylist.insert(END, output)

        mylist.pack( side = LEFT, fill = Y, expand = False)
        scrollbar.config( command = mylist.yview )
        mainloop()
        # tkMessageBox.showinfo("Output", output)
        print output
    else:
        print "not found"

When I add the scrollbar I get his as an output:

Scrollbar Error

So what I am trying to do is fit the data in a nice window dialog that has a scrollbar.

This is the output:

APN=""
APU=""
APP=""
DDC=
FMT=""
HDR=
AKR=
AKT=
AKP=
PMR=
PKA=
PHN=""
PHS=""
HBI=
PMF=
PMN=
PRN=
PRF=
RET=
SFR=
SFT=
SXD=
SXV=
SXW=
SXX=
SPM=
VIT=
VID=
VPT=
ATN=
ATF=
AMT=
AMD=
LGF=
GPA=
GFN=
GFO=
GDN=
GDF=
GPN=
SCN=
SCO=
SCP=
AEE=
AET=
AES=
OUA=
BWP=
MSO=
UPE=
UPC=
UPT=
VAA=
VAR=
VAI=
IVJ=
IGM=
IGA
IGB=
IGC=
IGD=
IGE=
IGF=
VOW=
VWD=

Solution

  • I think you need to change how the output is inserted into the Listbox, assuming its contents is newline separated (as shown in your updated question).

    The documentation presents the insert() method's calling sequence as:

        insert(index, *elements)

    So one way to do things would be to call it multiple times, once for each element, in a loop:

    for element in output.splitlines():
        mylist.insert(END, element)
    

    However, the * prefix on the second argument in the documentation means that the method accepts a variable number of arguments starting at the point (each of which will be put on a separate line).

    This means the same thing could accomplished in a single call:

    mylist.insert(END, *output.splitlines())
    

    What that does is first split the output data up into a list based upon the newlines in it, and then passes them as a bunch of separate arguments in the method call by prefixing the result returned from output.splitlines() with an *, which causes it to be "unpacked" into multiple calling arguments.

    This is a fairly common Python idiom, so is worth learning and remembering. See Unpacking Argument Lists in the documentation.