【问题标题】:Tkinter, create frame with scrolling bar, to receive arduino serialTkinter,创建带有滚动条的框架,以接收 arduino 串行
【发布时间】:2020-08-04 17:34:24
【问题描述】:

我想在我的应用程序的某个部分创建一个框架,来自我的 arduino 的串行输入将显示在那里,以及一个滚动条,以便向上滚动。

理想情况下,我想要自动滚动的功能。 基本上,我想做的是用我自己的程序替换用于接收串行数据的 arduino IDE。

我确定有人已经这样做了,所以我在这里发布一些指针。

我已经创建了基本的 tkinter 窗口,它将为我的应用程序奠定基础。

这是我的代码(功能不完整 - 只是图形):

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


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

# --- functions ---
def serial_ports():    
    return serial.tools.list_ports.comports()

def on_select(event=None):

    # get selection from event    
    print("event.widget:", event.widget.get())

    # or get selection directly from combobox
    print("comboboxes: ", cb.get())

def single_Sensor():    
    clicked_new = int(clicked)
# --- 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 combobox
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
button = tk.Button(frame2, text="Measure all Sensors", bg='#80c1ff', fg='red')  #bg='gray'
button.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]
clicked = tk.StringVar()
clicked.set(OPTIONS[0]) # default value
drop = tk.OptionMenu(frame2, clicked, *OPTIONS)
drop.place(relx = 0.65, rely=0.25, relwidth=0.08, relheight=0.6)

dropDownButton = tk.Button(frame2, text="Measure this sensor", bg='#80c1ff', fg='red', command=single_Sensor) #bg='gray'
dropDownButton.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')

stop_button = tk.Button(frame3, text="STOP measurement(s)", bg='#80c1ff', fg='red')
stop_button.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')

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


root.mainloop() #here we run our app
# --- main ---

这就是我得到的:

如您所见,在带有滚动条的框架的底部有很多空间。这是 arduino 串行文本将出现的位置。

【问题讨论】:

标签: python tkinter arduino serial-port pyserial


【解决方案1】:

我最近在我的机器人的控制程序中构建了类似的东西。以下是我所做的一些 sn-ps:

我创建了框架和滚动条(self是一个类继承框架):

self.logFrame = tk.Frame(self, **SharedDiscoBot.frameConfig)
self.scrollbar = tk.Scrollbar(self.logFrame)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.log = tk.Text(self.logFrame, width=60, height=10, padx=5, pady=5, takefocus=0, yscrollcommand=self.scrollbar.set, **SharedDiscoBot.textboxConfig)
self.scrollbar.config(command=self.log.yview)
self.log.pack()    
self.logFrame.pack(side=tk.TOP)

我还有一个 tk IntVar 对象来设置自动滚动和一个复选框来设置它。

self.autoscroll = tk.IntVar()
self.asCheck = tk.Checkbutton(self.checkFrame, variable=self.autoscroll, text='Auto-Scroll   ', **SharedDiscoBot.checkboxConfig)
self.asCheck.select()

然后我的程序读取串行数据并对其进行解析或将其传递给该函数以显示在该文本区域上。

 def redirect(self, aString):
        self.log.insert(tk.END, str(aString))
        if self.autoscroll.get() == 1:
            self.log.see(tk.END)        
        return

如果您想查看该代码的其余部分,它是我 github 上该项目的一部分。 https://github.com/delta-G/DiscoBot 具体来说:https://github.com/delta-G/DiscoBot/blob/master/GUI/TermFrame.py

【讨论】:

  • 连续读取串口数据的函数。难道我们不需要把它放在一个无限循环中吗?
  • 那种。整个事情在一个更大的循环中运行。这个想法是从主循环每隔几毫秒调用一次。
猜你喜欢
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多