2

我正在使用 NI 仪器读取数据并将其显示在 GUI 上。用过tkinter。但是找不到使用 while 循环更新数据的方法。

import nidaqmx
import time
from tkinter import *
master = Tk()
while True:
    with nidaqmx.Task() as task:
        task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
        print('1 Channel 1 Sample Read: ')
        data = task.read()
        sensor_value ='%.2f' % data #said sensor value
        master.minsize(width=400, height=400)
        w = Label(master, text=sensor_value) #shows as text in the window
        w.pack() #organizes widgets in blocks before placing them in the parent.          
        time.sleep(5)
        mainloop()
4

4 回答 4

1

试试这个代码:

import time
from tkinter import *
import nidaqmx

master = Tk()

def test():
    while True:
        with nidaqmx.Task() as task:
            task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
            print('1 Channel 1 Sample Read: ')
            data = task.read()
            sensor_value = '%.2f' % data  # said sensor value
            
            w['text'] = sensor_value
            master.update()
            time.sleep(2)

w = Label(master)
w.pack()
btn = Button(text="Start read from sensor", command=test)
btn.pack()
mainloop()
于 2020-06-27T09:54:30.907 回答
1

在使用 Tkinter 时,我们应该避免使用线程,while使用它循环root.update()并不是我们不能使用它们,而是不建议使用after(delay_ms, callback=None, *args)Tkinter 本身提供的方法,这是有原因的。

现在到您的代码,您的代码中几乎没有问题。

  1. while循环中,您每 5 秒创建一个标签,并使用 or 更新循环Labelw['text'] = '...'内该标签的值w.configure(text='...')

  2. 不要放在mainloop循环内,而是在最后一行使用您的案例mastermaster.mainloop())中的主窗口实例调用它。

  3. 与 相同master.minsize(width=400, height=400)您不必每 5 秒告诉主窗口将最小尺寸设置为 400x400,如果不决定将最小尺寸更改为不同的几何图形,则应调用一次。

您的代码应如下所示。

import nidaqmx
from tkinter import *

master = Tk()
master.minsize(width=400, height=400)
w = Label(master) #shows as text in the window
w.pack() #organizes widgets in blocks before placing them in the parent.   

def run():
    with nidaqmx.Task() as task:
        task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
        print('1 Channel 1 Sample Read: ')
        data = task.read()
        w['text'] = '%.2f' % data #said sensor value
    master.after(5000, run)

run() # run the function once.
master.mainloop()

这应该是这样做的正确方法,因为如果任何事情不起作用,我将无法运行您的代码,否则请告诉我。

于 2020-06-27T10:27:42.870 回答
1

您可能需要第二个线程来轮询传感器。

import nidaqmx
import time
import threading
from tkinter import *


stop_signal = threading.Event()


def read_loop():
    with nidaqmx.Task() as task:
        task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
        while True:
            data = task.read()
            label["text"] = "%.2f" % data

            # Wait for the signal, or 5 seconds
            if stop_signal.wait(timeout=5):
                break  # If the signal was set, break


# Build window
master = Tk()
master.minsize(width=400, height=400)
label = Label(master, text="")
label.pack()

# Set up & start reading thread
threading.Thread(target=read_loop).start()

try:
    # Enter Tk main loop
    mainloop()
finally:
    # Clean up afterwards
    stop_signal.set()
于 2020-06-27T10:04:08.143 回答
1

请记住,这mainloop()是阻塞的,所以time.sleep()没有用,因为您不会回到task.read()线路。考虑使用线程库中的 Thread 模块,像这样导入它:

from threading import Thread

或使用按钮刷新其他人建议您的值。

于 2020-06-27T10:06:49.600 回答