如何使用来自 USB 串口(来自 Arduino)的数据刷新/更新 QLabel? [英] How do I refresh/update QLabel with data from USB serial (from Arduino)?

查看:23
本文介绍了如何使用来自 USB 串口(来自 Arduino)的数据刷新/更新 QLabel?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这是一个菜鸟问题;对不起.我为 Cub Scouts 构建了一个 Pinewood Derby 比赛计时器(小型汽车赛道),使用 Arduino 控制计时和 RasPi 的组合,用于车道位置(第 1、第 2、第 3 等)的 GUI 显示和以秒为单位的运行时间(例如"2.1234").我在 QT Creator 中设置了基本的 shell GUI 并成功连接了 Arduino &通过 USB 的 RasPi.我也成功地将 Arduino 串行数据拉入 RasPi(使用单独的小 Python 代码测试).

I know this is a NOOB question; forgive me. I built a Pinewood Derby race timer (small car track) for Cub Scouts using a combination of an Arduino to control timing and RasPi for GUI display of lane place (1st, 2nd, 3rd, etc.) and run time in seconds (e.g. "2.1234"). I have the basic shell GUI setup in QT Creator and have successfully connected the Arduino & RasPi via USB. I am also successfully pulling the Arduino serial data into RasPi (tested with separate small Python code).

我遇到的问题是一旦 Arduino 通过 USB 触发比赛结果字符串,GUI 中 QLabel 的动态更新.换句话说,当比赛开始时,Arduino 发送B"作为开始(需要 GUI 来清除之前的结果);比赛结束后,Arduino 发送F",然后发送位置1"以及时间2.1234",我需要 Python 来更新/更改每个车道位置和车道时间的相应 QLabel.我相信有一种简单的方法可以做到这一点,但我无法通过搜索这个很棒的网站和其他网站来找到方法.

Problem I am having is the dynamic update of the QLabels in the GUI once the Arduino fires the race result strings via USB. in other words, when a race starts the Arduino sends "B" for begin (need GUI to blank previous results); when race is finished, Arduino sends "F" and then sends place "1" along with time "2.1234" and I need Python to update/change respective QLabels for each lane place and lane time. I am sure there is an easy way to do this, but I am unable to find how via searching this awesome website and others.

非常感谢,对于接下来可能是 FUBAR 编码的内容,我深表歉意!下面的示例仅显示了一个车道与 4x 车道的对比,一旦我弄清楚如何做到这一点,我将使用它.

Thanks much in advance and I apologize for what is probably FUBAR coding that follows! The sample below only shows one lane vs. the 4x lanes I will use once I figure out how to do this.

我正在使用两个 Python 代码:

与 QT Creator 生成的 XML 代码交互的 Python 代码:

import sys
import time
import serial

from PyQt4 import QtCore, QtGui, uic

global ser

ser=serial.Serial("/dev/ttyUSB1",115200)
ser.flushInput()

qtCreatorFile = "PinewoodDisplay.ui" # Enter file here.

Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)

class MyApp(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

while True:
    if ser.inWaiting()>0:
        inputValue = (ser.readline().strip())
        self.Lane1_Place.setText(inputValue)

从 QT Creator 生成的 XML(不确定我发布的是否正确)--文件名是PinewoodDisplay.ui":

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>619</width>
    <height>1051</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="styleSheet">
   <string notr="true">background-color: rgb(102, 102, 108)</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QGroupBox" name="Lane1_Group">
    <property name="geometry">
     <rect>
      <x>50</x>
      <y>20</y>
      <width>481</width>
      <height>741</height>
     </rect>
    </property>
    <property name="cursor">
     <cursorShape>CrossCursor</cursorShape>
    </property>
    <property name="autoFillBackground">
     <bool>false</bool>
    </property>
    <property name="styleSheet">
     <string notr="true">background-color : rgb(0, 75, 0)</string>
    </property>
    <property name="title">
     <string/>
    </property>
    <property name="alignment">
     <set>Qt::AlignHCenter|Qt::AlignTop</set>
    </property>
    <layout class="QGridLayout" name="gridLayout">
     <item row="2" column="0">
      <widget class="QLabel" name="Lane1_Place">
       <property name="sizePolicy">
        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
         <horstretch>0</horstretch>
         <verstretch>0</verstretch>
        </sizepolicy>
       </property>
       <property name="palette">
        <palette>
         <active>
          <colorrole role="WindowText">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Button">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Text">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="ButtonText">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Base">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Window">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
         </active>
         <inactive>
          <colorrole role="WindowText">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Button">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Text">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="ButtonText">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Base">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Window">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
         </inactive>
         <disabled>
          <colorrole role="WindowText">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Button">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Text">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="ButtonText">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>255</red>
             <green>255</green>
             <blue>255</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Base">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
          <colorrole role="Window">
           <brush brushstyle="SolidPattern">
            <color alpha="255">
             <red>0</red>
             <green>75</green>
             <blue>0</blue>
            </color>
           </brush>
          </colorrole>
         </disabled>
        </palette>
       </property>
       <property name="font">
        <font>
         <family>Gentium Book Basic</family>
         <pointsize>350</pointsize>
         <weight>75</weight>
         <bold>true</bold>
        </font>
       </property>
       <property name="autoFillBackground">
        <bool>false</bool>
       </property>
       <property name="styleSheet">
        <string notr="true">color: rgb(255, 255, 255)</string>
       </property>
       <property name="lineWidth">
        <number>0</number>
       </property>
       <property name="text">
        <string>4</string>
       </property>
       <property name="scaledContents">
        <bool>true</bool>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
      </widget>
     </item>
     <item row="3" column="0">
      <widget class="QLabel" name="Lane1_Time">
       <property name="font">
        <font>
         <pointsize>90</pointsize>
         <weight>75</weight>
         <bold>true</bold>
        </font>
       </property>
       <property name="styleSheet">
        <string notr="true">color: rgb(255, 255, 255)</string>
       </property>
       <property name="text">
        <string>4.5678</string>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
      </widget>
     </item>
     <item row="1" column="0">
      <widget class="QLabel" name="lblLane1">
       <property name="font">
        <font>
         <pointsize>36</pointsize>
         <weight>75</weight>
         <bold>true</bold>
        </font>
       </property>
       <property name="styleSheet">
        <string notr="true">color: rgb(255, 255, 255)</string>
       </property>
       <property name="text">
        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#e9e9e9;&quot;&gt;Lane 1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
      </widget>
     </item>
    </layout>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>619</width>
     <height>27</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
  <action name="actionTest">
   <property name="text">
    <string>test</string>
   </property>
  </action>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

推荐答案

需要读取串口数据的 while True 等阻塞任务不是 GUI 友好的,所以不要在同一个线程上运行,适当的选项是在另一个线程上执行它们,并通过信号将必要的信息发送到主线程.

Blocking tasks such as the while True that you need to read the serial data are not GUI-friendly, so you should not run on the same thread, the appropriate option is to execute them on another thread, and send the necessary information to the main thread by signals.

import sys
import serial

from PyQt4 import QtCore, QtGui, uic

qtCreatorFile = "PinewoodDisplay.ui"

Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)

class SerialThread(QtCore.QThread):
    dataChanged = QtCore.pyqtSignal(str)
    def __init__(self, *args, **kwargs):
        QtCore.QThread.__init__(self, *args, **kwargs)
        self.ser = serial.Serial("/dev/ttyUSB1",115200)

    def run(self):
        while True:
            if self.ser.inWaiting()>0:
                inputValue = self.ser.readline().strip()
                self.dataChanged.emit(inputValue)

class MyApp(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
        thread = SerialThread(self)
        thread.dataChanged.connect(self.Lane1_Place.setText, QtCore.Qt.QueuedConnection)
        thread.start()

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

同样的任务可以用 QRunnableQThreadPool 完成,也可以发送数据,你可以使用 QMetaObject::invokeMethod()

The same task could be done with QRunnable and QThreadPool, also to send the data you could use QMetaObject::invokeMethod()

这篇关于如何使用来自 USB 串口(来自 Arduino)的数据刷新/更新 QLabel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆