user1584421
user1584421

Reputation: 3843

Tkinter: scrollbar fails

I am trying to create a scrollbar and attach it to frame 2. This is the code:

import tkinter as tk
import tkinter.ttk as ttk
import serial.tools.list_ports

#global variable that will hold the COM port
COMPort = 0


#to be used on our canvas
HEIGHT = 700
WIDTH = 800

#hardcoded baud rate
baudRate = 9600


#make our own buffer
#useful for parsing commands
#Serial.readline seems unreliable at times too
serBuffer = ""

ser = 0 #initial  value. will chane at 'on_select('

# --- functions ---

#the following two functtions are for the seria port selection, on frame 1
def serial_ports():    
    return serial.tools.list_ports.comports()

def on_select(event=None):

    global COMPort
    COMPort = cb.get()
    print(COMPort)
    # get selection from event    
    #print("event.widget:", event.widget.get())

    # or get selection directly from combobox
    #print("comboboxes: ", cb.get())
    global ser
    ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0) #ensure non-blocking



def readSerial():
    while True:
        c = ser.read() # attempt to read a character from Serial
        
        #was anything read?
        if len(c) == 0:
            break
        
        # get the buffer from outside of this function
        global serBuffer
        
        # check if character is a delimeter
        if c == '\r':
            c = '' # don't want returns. chuck it
            
        if c == '\n':
            serBuffer += "\n" # add the newline to the buffer
            
            #add the line to the TOP of the log
            log.insert('0.0', serBuffer)
            serBuffer = "" # empty the buffer
        else:
            serBuffer += c # add to the buffer
    
    root.after(10, readSerial) # check serial again soon

# --- functions ---



# --- main ---
root = tk.Tk() #here we create our tkinter window
root.title("Sensor Interface")

#we use canvas as a placeholder, to get our initial screen size (we have defined HEIGHT and WIDTH)
canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()

#we use frames to organize all the widgets in the screen

# --- frame 1 ---
frame1 = tk.Frame(root)
frame1.place(relx=0, rely=0.05, relheight=0.03, relwidth=1, anchor='nw') #we use relheight and relwidth to fill whatever the parent is - in this case- root

label0 = tk.Label(frame1, text="Select the COM port that the device is plugged in: ")
label0.config(font=("TkDefaultFont", 8))
label0.place(relx = 0.1, rely=0.3, relwidth=0.3, relheight=0.5)


cb = ttk.Combobox(frame1, values=serial_ports())
cb.place(relx=0.5, rely=0.5, anchor='center')
# assign function to cmbobox
cb.bind('<<ComboboxSelected>>', on_select)
# --- frame 1 ---




# --- frame 2 ---
frame2 = tk.Frame(root, bg='#80c1ff') #remove color later
frame2.place(relx=0, rely=0.1, relheight=0.07, relwidth=1, anchor='nw')

# make a scrollbar
scrollbar = Scrollbar(frame2)
scrollbar.pack(side=RIGHT, fill=Y)

# make a text box to put the serial output
log = Text ( frame2, width=30, height=30, takefocus=0)
log.pack()

# attach text box to scrollbar
log.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=log.yview)

# --- frame 2 ---



# after initializing serial, an arduino may need a bit of time to reset
root.after(100, readSerial)
root.mainloop() #here we run our app

However, i get this error:

    scrollbar = Scrollbar(frame2)
NameError: name 'Scrollbar' is not defined

I don't understand what i am doing wrong...

EDIT: This is my original program that contains many frames.

[![enter image description here][1]][1]

In the big empty sapce, i was hoping to hook up the frame that will display the serial data, with the scrollbar to the right. [1]: https://i.sstatic.net/IOguE.png

Upvotes: 0

Views: 49

Answers (1)

TheLizzard
TheLizzard

Reputation: 7680

You shouldn't use more than 1 geometry manager in a single tkinter window/frame. Also you don't need to use a <tkinter.Canvas> to reserve space for your window. The is the <tkinter.Tk>.geometry(...) method for that.

I think that this is the GUI stuff that you wanted:

# --- main ---
root = tk.Tk() #here we create our tkinter window
root.title("Sensor Interface")

# Set the initial screen size
root.geometry("%ix%i" % (WIDTH, HEIGHT))

#we use frames to organize all the widgets in the screen

# --- frame 1 ---
frame1 = tk.Frame(root)
frame1.pack(side="top")

label0 = tk.Label(frame1, text="Select the COM port that the device is plugged in: ", font=("TkDefaultFont", 8))
label0.grid(row=1, column=1)

cb = ttk.Combobox(frame1, values=serial_ports())
cb.grid(row=1, column=2)
# assign function to cmbobox
cb.bind('<<ComboboxSelected>>', on_select)
# --- frame 1 ---


# --- frame 2 ---
frame2 = tk.Frame(root, bg='#80c1ff') #remove color later
frame2.pack(side="bottom", fill="both", expand=True)

# make a scrollbar
scrollbar = tk.Scrollbar(frame2)
scrollbar.pack(side="right", fill="y")

# make a text box to put the serial output
log = tk.Text (frame2, width=30, height=30, takefocus=0)
log.pack(side="left", fill="both", expand=True)

# attach text box to scrollbar
log.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=log.yview)
# --- frame 2 ---


# after initializing serial, an arduino may need a bit of time to reset
root.after(100, readSerial)
root.mainloop() #here we run our app```

Upvotes: 1

Related Questions