首页 > 编程问答 >未从 Tkinter 刷新 GUI 中的值时出错

未从 Tkinter 刷新 GUI 中的值时出错

时间:2024-07-31 08:40:35浏览次数:14  
标签:python tkinter arduino pyserial

我绝对是编码初学者,目前正在尝试使用 Arduino Uno 设计涡轮机性能显示器,该显示器将使用引脚 A1 的输入传达电压读数。

然后将该读数发送到 Python,然后发送到 Python GUI 是根据 Arduino 的原始串行输入显示电流等读数。根据我所学到的知识,我从 Arduino 端进行了简单的编码,然后使用 Figma 设计了一个 GUI 并对其进行了转换。我的问题是,数据仅显示为电压和电流的样本,但我无法随着电流或电压值的变化自动不断刷新数据。我缺少什么?当我尝试执行循环时,它会错误地显示整个代码。

这是我一直在循环中尝试的代码:

# Tkinter-Designer


from pathlib import Path

# from tkinter import *
# Explicit imports to satisfy Flake8
import serial

ser = serial.Serial ('COM4', baudrate = 9600, timeout = 1)

while:1

arduinoData = ser.readline().decode('ascii')
int(float(arduinoData))

voltageval = int(arduinoData)/204.6
currentval = int(arduinoData)/1.96



from tkinter import Tk, Canvas, Entry, Text, Button, PhotoImage


OUTPUT_PATH = Path(__file__).parent
ASSETS_PATH = OUTPUT_PATH / Path(r"C:\Users\haeyl\Downloads\tkinter\build\assets\frame0")


def relative_to_assets(path: str) -> Path:
    return ASSETS_PATH / Path(path)


window = Tk()

window.geometry("1280x720")
window.configure(bg = "#600000")


canvas = Canvas(
    window,
    bg = "#600000",
    height = 720,
    width = 1280,
    bd = 0,
    highlightthickness = 0,
    relief = "ridge"
)

canvas.place(x = 0, y = 0)
canvas.create_rectangle(
    0.0,
    0.0,
    1280.0,
    90.0,
    fill="#474646",
    outline="")

canvas.create_text(
    423.0,
    37.0,
    anchor="nw",
    text="TURBINE PERFORMANCE DISPLAY",
    fill="#FFFFFF",
    font=("Inter", 24 * -1)
)

image_image_1 = PhotoImage(
    file=relative_to_assets("image_1.png"))
image_1 = canvas.create_image(
    262.0,
    182.0,
    image=image_image_1
)

image_image_2 = PhotoImage(
    file=relative_to_assets("image_2.png"))
image_2 = canvas.create_image(
    909.0,
    182.0,
    image=image_image_2
)

image_image_3 = PhotoImage(
    file=relative_to_assets("image_3.png"))
image_3 = canvas.create_image(
    909.0,
    344.0,
    image=image_image_3
)

image_image_4 = PhotoImage(
    file=relative_to_assets("image_4.png"))
image_4 = canvas.create_image(
    262.0,
    348.0,
    image=image_image_4
)

image_image_5 = PhotoImage(
    file=relative_to_assets("image_5.png"))
image_5 = canvas.create_image(
    262.0,
    519.0,
    image=image_image_5
)

canvas.create_text(
    105.0,
    168.0,
    anchor="nw",
    text="VOLTAGE",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    752.0,
    168.0,
    anchor="nw",
    text="RPM",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    740.0,
    330.0,
    anchor="nw",
    text="POWER",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    105.0,
    335.0,
    anchor="nw",
    text="CURRENT",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    105.0,
    506.0,
    anchor="nw",
    text="TORQUE",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    323.0,
    168.0,
    anchor="nw",
    text=(0 + voltageval),
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    970.0,
    168.0,
    anchor="nw",
    text="rpmval",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    970.0,
    330.0,
    anchor="nw",
    text="0 W ",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    323.0,
    335.0,
    anchor="nw",
    text=(0 + currentval),
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

canvas.create_text(
    323.0,
    506.0,
    anchor="nw",
    text="0 N/M",
    fill="#FFFFFF",
    font=("Inter", 32 * -1)
)

image_image_6 = PhotoImage(
    file=relative_to_assets("image_6.png"))
image_6 = canvas.create_image(
    1132.0,
    563.0,
    image=image_image_6
)

button_image_1 = PhotoImage(
    file=relative_to_assets("button_1.png"))
button_1 = Button(
    image=button_image_1,
    borderwidth=0,
    highlightthickness=0,
    command=lambda: print("button_1 clicked"),
    relief="flat"
)
button_1.place(
    x=709.0,
    y=476.0,
    width=264.0,
    height=108.0
)


    
     
    

window.resizable(False, False)
window.mainloop()



你的代码的主要问题是你试图在 Tkinter 的主循环之外更新 GUI 元素。Tkinter 有一个内部循环,该循环处理诸如更新文本、处理事件等事件。你不能只是设置一次你的 GUI 然后通过更新一个变量来更新它。你需要告诉 Tkinter 使用 mainloop() 函数来更新它。

以下是如何修复代码的方法:

  1. 从无限 while 循环中移出 GUI 更新代码: 你不应该在 while 循环中运行你的 Tkinter 应用程序。 while 循环会阻止 Tkinter 的主循环,从而导致 GUI 无响应。

  2. 创建一个用于从 Arduino 读取数据并更新 GUI 的函数: 该函数将从串行端口读取数据,计算电压和电流,然后使用新的电压和电流值更新相应的 Tkinter 文本元素。

  3. 使用 after() 方法调用更新函数: after() 方法允许你安排一个函数在 Tkinter 主循环中的一段时间后运行。这将创建一个定期更新 GUI 的循环。

以下是代码:

import serial
import tkinter as tk

# Arduino 串口配置
ser = serial.Serial('COM4', baudrate=9600, timeout=1)

def update_gui():
    """从 Arduino 读取数据并更新 GUI。"""
    try:
        arduino_data = ser.readline().decode('ascii').strip()
        if arduino_data:  # 仅在接收到数据时更新
            # 将数据转换为整数
            arduino_data = int(float(arduino_data))

            # 计算电压和电流
            voltage_val = arduino_data / 204.6
            current_val = arduino_data / 1.96

            # 更新画布上的文本标签
            canvas.itemconfig(voltage_text, text=f"{voltage_val:.2f}")
            canvas.itemconfig(current_text, text=f"{current_val:.2f}")

    except ValueError:
        # 处理无效数据(例如,如果读取为空)
        print("从 Arduino 收到无效数据。")

    # 每 100 毫秒安排 update_gui() 再次运行
    window.after(100, update_gui)

# 创建主窗口
window = tk.Tk()
window.geometry("1280x720")
window.configure(bg="#600000")

# 创建画布
canvas = tk.Canvas(window, bg="#600000", height=720, width=1280, bd=0, highlightthickness=0, relief="ridge")
canvas.place(x=0, y=0)

# ... (其余的画布元素,如矩形、图像和静态文本) ...

# 创建电压和电流文本标签
voltage_text = canvas.create_text(
    323.0, 168.0, anchor="nw", text="0.00", fill="#FFFFFF", font=("Inter", 32 * -1)
)
current_text = canvas.create_text(
    323.0, 335.0, anchor="nw", text="0.00", fill="#FFFFFF", font=("Inter", 32 * -1)
)

# ... (按钮和其他 GUI 元素) ...

# 启动更新函数
update_gui()

# 运行主循环
window.resizable(False, False)
window.mainloop()

此代码创建了一个名为 update_gui 的函数,该函数负责从 Arduino 读取数据并更新 GUI。然后,使用 window.after(100, update_gui) 方法安排此函数每 100 毫秒调用一次。这将创建定期更新 GUI 的循环。

此外,你应该确保 Arduino 代码不断向串口发送数据。

标签:python,tkinter,arduino,pyserial
From: 78814062

相关文章

  • 具有自引用的类装饰器的 Python 类型提示
    我的最终目标是编写一个系统来轻松记录函数调用(特别是类方法)。我首先编写一个带有包装方法的类Loggable,该方法允许我装饰子类方法并记录它们的调用|||现在我可以编写子类并记录它们的调用:Param=ParamSpec("Param")RetType=TypeVar("RetType")CountType=......
  • 如何在for循环中使用curve_fit函数在python中一次性创建多个回归?
    简而言之,我有两个矩阵,一个称为t,另一个称为y。每个都有7列。假设它们被称为a、b、c、d、e、f和g。我想要的是从a对a、b对b、...、g对g这两个矩阵进行回归。我已经设法使我的算法使用curve_fit对一列进行回归一次。但我真正希望的是它能够一次性完成7个回归......
  • 激活虚拟环境会让python消失?
    VisualStudioCode终端的屏幕截图如屏幕截图所示,python在Powershell中运行得很好。然后我在E:\DrewFTCAPI\ftcapivenv激活虚拟环境,然后python就消失了。不仅没有消失,它不运行任何东西,也不产生任何输出。我至少预计会出现某种类型的"python"i......
  • Python 3.6 中的相互递归类型,使用命名元组语法
    我正在尝试实现图的节点和边。这是我的代码:fromtypingimportNamedTuple,ListclassNode(NamedTuple):name:stredges:List[Edge]classEdge(NamedTuple):src:Nodedest:Node这会引发错误,因为创建Edge时未定义Node类型。......
  • 使用 keras 模型对函数进行 Python 类型提示
    如果我创建这样的函数:defmdl(input_shape):model=Sequential()model.add(Conv2D(depth=64,kernel_size=(3,3),input_shape=input_shape,activation='relu'))model.add(Dense(32),activation='relu')model.add(Dropout(0.3))m......
  • Python:自动完成可以用于列表中的元素吗?
    Python在函数参数和函数返回类型中具有类型提示。类的元素是否有类似的东西?我希望能够在如下示例中使用自动完成功能:classMyClass:defhello(self):print("Hello")mylist=[]mylist.append(MyClass())foriinmylist:i.hello()#Noautocomplete......
  • python 中 COM 对象的正确类型提示是什么?
    我在python中使用COM对象来向3rd方软件公开可编程接口。这是通过使用Dispatchfromwin32com.client来实现的。我的项目也一直在使用python.3.7中的类型提示,但是我不确定如何为了类型提示的目的定义这些COM对象的类型。这个问题涉及我拥有的所有COM......
  • 如何遍历Python字典同时避免KeyErrors?
    解析大型JSON时,某些键可能仅在某些情况下存在,例如出现错误时。从服务器的API获取200OK的情况并不少见,但是您得到的响应包含应检查的错误。处理此问题的最佳方法是什么?我知道使用类似||之类的东西。|是处理KeyError的一种方法。get()但是如果......
  • Python 中的递归数据类型
    Python中最接近Haskell中的递归数据类型的是什么?(即在定义自身时使用类型自己的定义。)编辑:为了给出递归类型的更具体定义,下面是Haskell中的二叉树:dataTreea=Leafa|Branch(Treea)(Treea)我的阅读方式如下:二叉树可以是叶子,也可以包含两......
  • 如何在Python中平滑相邻的多边形?
    我正在寻找一种平滑多边形的方法,以便相邻/接触的多边形保持接触。单个多边形可以轻松平滑,例如使用PAEK或Bezier插值(https://pro.arcgis.com/en/pro-app/latest/tool-reference/cartography/smooth-polygon.htm),这自然会改变它们的边界边缘。但是如何平滑所有多边形......