Apr-26-2021, 12:50 AM
Thanks. I tried your approach, but it does not work.
I get no error, but i see nothing printed on tkinter. Full code here:
I get no error, but i see nothing printed on tkinter. Full code here:
import tkinter as tk import tkinter.ttk as ttk import serial.tools.list_ports #for a list of all the COM ports from tkinter import scrolledtext from time import sleep #to be used on our canvas HEIGHT = 800 WIDTH = 800 #hardcoded baud rate baudRate = 9600 # this is the global variable that will hold the serial object value ser = None #initial value. will change at 'on_select()' after_id = None #this is the global variable that will hold the value from the dropdown for the sensor select dropdown_value = None # --- functions --- #the following two functtions are for the seria port selection, on frame 1 #this function populates the combobox on frame1, with all the serial ports of the system def serial_ports(): return serial.tools.list_ports.comports() #when the user selects one serial port from the combobox, this function will execute def on_select(event=None): global ser COMPort = cb.get() string_separator = "-" COMPort = COMPort.split(string_separator, 1)[0] #remove everything after '-' character COMPort = COMPort[:-1] #remove last character of the string (which is a space) ser = serial.Serial(port = COMPort, baudrate=9600, timeout=0) #readSerial() #start reading shit. DELETE. later to be placed in a button # get selection from event #print("event.widget:", event.widget.get()) # or get selection directly from combobox #print("comboboxes: ", cb.get()) #ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0) #ensure non-blocking def readSerial(): if reading_serial: while (ser_bytes := ser.readline()): try: text.insert("end", ser_bytes.decode("utf-8")) if vsb.get()[1]==1.0: #if the scrollbar is down to the bottom, then autoscroll text.see("end") except UnicodeExceptionError: print("Oops") root.after(50,readSerial) # this function is triggered, when a value is selected from the dropdown def dropdown_selection(*args): global dropdown_value dropdown_value = clicked.get() button_single['state'] = 'normal' #when a selection from the dropdown happens, change the state of the 'Measure This Sensor' button to normal # this function is triggered, when button 'Measure all Sensors' is pressed, on frame 2 def measure_all(): global reading_serial reading_serial = True button_stop['state']='normal' #make the 'Stop Measurement' button accessible ser.write("rf".encode()) #Send string 'rf to arduino', which means Measure all Sensors sleep(0.05) # 50 milliseconds readSerial() #Start Reading data # this function is triggered, when button 'Measure this Sensor' is pressed, on frame 2 def measure_single(): print(dropdown_value) global stop_ stop_=False button_stop['state']='normal' string_to_send = 'r' + ' ' + str(dropdown_value)#CHANGE ser.write(string_to_send.encode()) #Send string 'rf to arduino', which means Measure all Sensors!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! readSerial() # this function is triggered, when button 'STOP measurement(s)' is pressed, on frame 2 def stop_measurement(): global reading_serial reading_serial=False button_stop['state']='disabled' ser.write("c".encode()) root.after_cancel(after_id) #do i need after_id to be global? # --- 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 ''' relheight, relwidth - Height and width as a float between 0.0 and 1.0, as a fraction of the height and width of the parent widget. relx, rely - Horizontal and vertical offset as a float between 0.0 and 1.0, as a fraction of the height and width of the parent widget. ''' # --- 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 combobox, that will run when an item is selected from the dropdown cb.bind('<<ComboboxSelected>>', on_select) # --- frame 1 --- # --- frame 2 --- frame2 = tk.Frame(root, bd=5) #REMOVED THIS bg='#80c1ff' (i used it to see the borders of the frame) frame2.place(relx=0, rely=0.1, relheight=0.07, relwidth=1, anchor='nw') #Button for 'Measure All Sensors' #it will be enabled initially button_all = tk.Button(frame2, text="Measure all Sensors", bg='#80c1ff', fg='red', state='normal', command=measure_all) #bg='gray' button_all.place(relx=0.2, rely=0.5, anchor='center') #label label1 = tk.Label(frame2, text="OR, select a single sensor to measure: ") label1.config(font=("TkDefaultFont", 9)) label1.place(relx = 0.32, rely=0.3, relwidth=0.3, relheight=0.4) #dropdown #OPTIONS = [0,1,2,3,4,5,6,7] OPTIONS = list(range(8)) #[0,1,2,3,4,5,6,7] clicked = tk.StringVar(master=frame2) # Always pass the `master` keyword argument, in order to run the function when we select from the dropdown clicked.set(OPTIONS[0]) # default value clicked.trace("w", dropdown_selection) #When a value from the dropdown is selected, function dropdown_selection() is executed drop = tk.OptionMenu(frame2, clicked, *OPTIONS) drop.place(relx = 0.65, rely=0.25, relwidth=0.08, relheight=0.6) #Button for 'Measure Single Sensor' #this will be disabled initially, and will be enabled when an item from the dropdown is selected button_single = tk.Button(frame2, text="Measure this Sensor", bg='#80c1ff', fg='red', state='disabled', command=measure_single) #bg='gray' button_single.place(relx = 0.85, rely=0.5, anchor='center') # --- frame 2 --- # --- frame 3 --- frame3 = tk.Frame(root, bd=5) #REMOVED THIS bg='#80c1ff' (i used it to see the borders of the frame) frame3.place(relx=0, rely=0.2, relheight=0.07, relwidth=1, anchor='nw') #Button for 'STOP Measurement(s)' #this will be disabled initially, and will be enabled only when a measurement is ongoing button_stop = tk.Button(frame3, text="STOP measurement(s)", bg='#80c1ff', fg='red', state='disabled', command=stop_measurement) button_stop.place(relx=0.5, rely=0.5, anchor='center') # --- frame 3 --- # --- frame 4 --- frame4 = tk.Frame(root, bd=5) frame4.place(relx=0, rely=0.3, relheight=0.09, relwidth=1, anchor='nw') label2 = tk.Label(frame4, text="Select a sensor to plot data: ") label2.place(relx = 0.1, rely=0.3, relwidth=0.3, relheight=0.5) clickedForPlotting = tk.StringVar() clickedForPlotting.set(OPTIONS[0]) # default value dropPlot = tk.OptionMenu(frame4, clickedForPlotting, *OPTIONS) dropPlot.place(relx=0.5, rely=0.5, anchor='center') #CHANGE LATER #dropDownButton = tk.Button(frame4, text="Plot sensor data", bg='#80c1ff', fg='red', command=single_Sensor) #bg='gray' #dropDownButton.place(relx = 0.85, rely=0.5, anchor='center') # --- frame 4 --- #frame 5 will be the save to txt file #frame 6 will be the area with the text field # --- frame 6 --- frame6 = tk.Frame(root, bg='#80c1ff') #remove color later frame6.place(relx=0.0, rely=0.4, relheight=1, relwidth=1, anchor='nw') text_frame=tk.Frame(frame6) text_frame.place(relx=0, rely=0, relheight=0.6, relwidth=1, anchor='nw') text=tk.Text(text_frame) text.place(relx=0, rely=0, relheight=1, relwidth=1, anchor='nw') vsb=tk.Scrollbar(text_frame) vsb.pack(side='right',fill='y') text.config(yscrollcommand=vsb.set) vsb.config(command=text.yview) # --- frame 6 --- reading_serial=False # 'Stop' flag. True when no measuring is happening root.mainloop() #here we run our app #Any code after mainloop() will be halted as long as the window stays alive, so placing the code after mainloop() would execute it after the window is closed. ser.close() # --- main ---By the way, do youi happen to understand why this behaviour is happening on my original question?