I am building a simple QT UI that communicates with an Arduino. I implemented a simple mechanism for automatic device detection. The pc is looking for all the connected serial devices and tries to send a Hi! message to the available ports. If the Arduino is connected to the pc, it replies this message. I want to show the status of device search procedure on the status bar of the UI. However, the status bar is not updated. It only shows the latest message. The original idea is not even having a push button for device search. I was simply calling findDevice() in setupUi() but in that case the UI does not even start till the end of findDevice() execution. If I directly call the method during UI setup I see a white window and everything appears when findDevice() method finishes execution. So why the status bar message does not update till the end of findDevice() execution and how can I eliminate pushButton_Connect? The code does not complete. It is a bit long but most of it is the generated code. I added only a few lines.
EDIT: The answer of this question is here: https://stackoverflow.com/a/57500544/10370627. Additionaly my closeEvent() method is not working in below code. For that problem the solution is here: https://stackoverflow.com/a/22460392/10370627
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file C:\ard_serial\python_code\calibrator_ui.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from pyqtgraph import PlotWidget
import numpy as np
import sys, time, serial, glob
# Global constants
ENCODING = "UTF-8"
GREETING = "Hi!"
DATA_READ = '0'
LIGHT_OFF = '1'
LED_ON = '2'
LASER_ON = '3'
EX_LED_ON = '4'
EX_LASER_ON = '5'
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# STARTS: User added class members
self.ser_port = None
# ENDS: User added class members
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1070, 595)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(1070, 595))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.lineEdit_Input = QtWidgets.QLineEdit(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_Input.sizePolicy().hasHeightForWidth())
self.lineEdit_Input.setSizePolicy(sizePolicy)
self.lineEdit_Input.setObjectName("lineEdit_Input")
self.gridLayout.addWidget(self.lineEdit_Input, 0, 1, 1, 1)
self.graphicsView_PlotWidget = PlotWidget(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.graphicsView_PlotWidget.sizePolicy().hasHeightForWidth())
self.graphicsView_PlotWidget.setSizePolicy(sizePolicy)
self.graphicsView_PlotWidget.setMinimumSize(QtCore.QSize(1050, 490))
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.NoBrush)
self.graphicsView_PlotWidget.setBackgroundBrush(QtGui.QColor('black'))
self.graphicsView_PlotWidget.setObjectName("graphicsView_PlotWidget")
self.gridLayout.addWidget(self.graphicsView_PlotWidget, 1, 0, 1, 5)
self.label_Only_integers = QtWidgets.QLabel(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_Only_integers.sizePolicy().hasHeightForWidth())
self.label_Only_integers.setSizePolicy(sizePolicy)
self.label_Only_integers.setObjectName("label_Only_integers")
self.gridLayout.addWidget(self.label_Only_integers, 0, 0, 1, 1)
self.pushButton_Generate = QtWidgets.QPushButton(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_Generate.sizePolicy().hasHeightForWidth())
self.pushButton_Generate.setSizePolicy(sizePolicy)
self.pushButton_Generate.setObjectName("pushButton_Generate")
self.gridLayout.addWidget(self.pushButton_Generate, 0, 2, 1, 1)
self.pushButton_Connect = QtWidgets.QPushButton(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_Connect.sizePolicy().hasHeightForWidth())
self.pushButton_Connect.setSizePolicy(sizePolicy)
self.pushButton_Connect.setObjectName("pushButton_Connect")
self.gridLayout.addWidget(self.pushButton_Connect, 0, 3, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1070, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
# STARTS: User added setup code
self.pushButton_Generate.clicked.connect(lambda:self.draw())
'''
I even do not want to use a push button for device search. But when I
call findDevice() method the UI appears after the execution of
findDevice() method.
'''
self.pushButton_Connect.clicked.connect(lambda:self.findDevice())
x = np.random.normal(size = 500)
y = np.random.normal(size = (3, 500))
for i in range(3):
self.graphicsView_PlotWidget.plot(x, y[i], pen = (i, 3))
# ENDS: User added setup code
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Calibrator"))
self.label_Only_integers.setText(_translate("MainWindow", "Only integers"))
self.pushButton_Generate.setText(_translate("MainWindow", "Generate"))
self.pushButton_Connect.setText(_translate("MainWindow", "Connect"))
# STARTS: User added methods
def findDevice(self):
'''
Here I expect to see all the status bar messages but I see only the last
one. For instance if there is no serial device is connected, I only see
<No serial device is connected> message on the status bar.
'''
self.statusbar.showMessage("Looking for device...")
print("Looking for device...")
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
import subprocess
# ports = glob.glob('/dev/tty[A-Za-z]*')
ports = glob.glob('/dev/ttyUSB[0-9]*')
for port in ports:
process = subprocess.Popen(["sudo", "chmod", "777", port], stdout = subprocess.PIPE)
output, error = process.communicate()
else:
raise EnvironmentError('Unsupported platform')
for port in ports:
try:
self.ser_port = serial.Serial(port, 115200)
time.sleep(1.8)
self.statusbar.showMessage("Trying: " + str(port))
print("Trying:", port)
self.ser_port.write(GREETING.encode(ENCODING))
time.sleep(0.1)
self.ser_port.reset_input_buffer()
time.sleep(1)
read_data = self.ser_port.read_all().decode(ENCODING)
if(GREETING == read_data):
self.statusbar.showMessage("Device detected on: " + str(port))
print("\nDevice detected on:", port)
else:
self.statusbar.showMessage("No device detected")
print("No device detected")
except (OSError, serial.SerialException):
pass
if(self.ser_port is None):
print("No serial device is connected")
self.statusbar.showMessage("No serial device is connected")
def draw(self):
self.graphicsView_PlotWidget.clear()
def closeEvent(self, event):
self.ledit.setText(LIGHT_OFF)
if(self.ser_port is not None):
ret_val = self.ser_port.close()
print("Program terminated with return code: ", ret_val)
# ENDS: User added methods
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())