In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "the process of PyQt5 GUI receiving UDP data and dynamic drawing". In daily operation, I believe that many people have doubts about the process of PyQt5 GUI receiving UDP data and dynamic drawing. Xiaobian consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for everyone to answer the doubts of "PyQt5 GUI receiving UDP data and dynamic drawing process introduction". Next, please follow the editor to study!
Catalogue
1. The usage of Qt
2. Pycharm settings
2.1 install Pyqt5 and pyinstaller packages
2.2 Pycharm pyqt tool configuration
3 UDP graphical interface design
3.1 GUI Design
3.2 convert GUI files to py files
3.3 widget forms upgrade to integrate matplotlib functions
3.4 GUI design results
4 UDP communication with multithread programming
4.1 signal and slot function
4.2 Multithreading
5 Pyinstaller is packaged into exe
1. The usage of Qt
pyqt5 is the python version of qt, which mainly exists in the form of objects, which can not be visualized in the process of programming, which brings a lot of inconvenience. To simplify the interface design of pyqt5, we can use the designer Qt Designer (C:\ Qt\ 5.12.11\ mingw73_32\ bin\ designer.exe) in qt to design the graphical interface, which is usually saved in a file with the * .ui suffix.
pyqt5 can directly call the .ui file, or it can convert the designed .ui file into a .py format pyqt5 class through pyqt5's own pyuic.exe, which can be called by other modules.
There are many installation tutorials for Qt on the CSDN forum, so it is recommended to use Qt5. The high version of Qt6 has not yet been included in the back-end support of matplotlib.
2. Pycharm settings
first Amway wave, Pycharm in the code color theme, function interface, python environment switching, open terminal, jupyter notebook support, variable view, Markdown support, console multi-open and other aspects have a high convenience, so I mainly use pychrm for related code development, recommended.
2.1 install Pyqt5 and pyinstaller packages
opens the terminal at the bottom of pycharm and enters the following code to install the pyqt5 package and the pyinstaller package. The Pyinstaller package is a tool for packaging pyqt5GUI designs into exe executables, with which you can copy programs to other windows computers.
Pip install pyqt5,pyinstaller
also needs to install the matplotlib package later, which will be installed in a similar manner and will not be discussed in detail. After installing pyqt5, matplotlib will automatically use pyqt5 as the backend, the image drawn is better, and the toolbar is more practical, so it is recommended for daily use.
2.2 Pycharm pyqt tool configuration
When uses Qt for interface design, several tools that come with Qt software can be configured as external tools in pycharm (this is one of the many advantages of pycharm), which is easy to call at any time. In pycharm and click File-Settings-tools-external tools (self-check English version), you can enter the external tools add interface.
Qt Designer tools (design Qt interface)
Program path:
C:\ Qt\ 5.12.11\ mingw73_32\ bin\ designer.exe
Working directory:
$ProjectFileDir$
Qt Creator tools (design Qt interface)
The program path is under the Script directory of the corresponding environment:
C:\ Anaconda3\ envs\ tensor37\ Scripts\ pyuic5.exe
The parameter is set as follows:
$FileName$-o $FileNameWithoutExtension$.py
working directory:
$ProjectFileDir$
PyUI tool (Qt UI interface is converted to python code)
program path:
C:\ Qt\ Tools\ QtCreator\ bin\ qtcreator.exe
working directory:
$ProjectFileDir$
After completes the above settings, you can open the two GUI design applications, designer.exe and creator.exe, in the right-click menu. Selecting the .ui file and running pyuic.exe will generate a .py file with the same name, which contains pyqt5 classes that can generate the same GUI.
3 UDP graphical interface design 3.1 GUI design
right-click in the pycharm space to select an external tool, open designer, and create a new Main Window form.
according to the needs, I designed a UDP network programming interface, the main function is to receive the sinusoidal data sent by the UDP client, save the data to the txt file and draw it in the bottom widget (form parts).
The target operation interface is as follows:
3.2 convert GUI files to py files
After designs the interface, save the widget_recev.ui drawing file. In the project explorer on the left, you can select the ui file right-click utility external pyuic tool to convert it to widget_recev.py file for program call. This operation is often used in subsequent debugging, changing the GUI at any time to generate a new py file. The newly created py file will overwrite the original content, so it is recommended to build another python module to call this module to avoid information loss.
3.3 widget forms upgrade to integrate matplotlib functions
it should be noted here that FigureCanvas in matplotlib and widget in GUI are subclasses of Qwidget. Matplotlib cannot draw directly in widget. You need to promote widget to Qwidget class in Designer. Right-click widget in GUI to select the lift widget, select Qwidget, and give the ascending class an easy-to-remember name. Here I am using mplwidget.
The final face of the widget_recev.py generated by generates a sentence:
From mplwidget import mplwidget
puts it at the beginning of the class file, otherwise an error will be reported.
The mplwidget.py module needs to build its own, and create a mplwidget.py file under the corresponding path. The main function is to create a class that inherits both FigureCanvas and QWidget, and name it the mplwidget class according to the predefined above. This operation makes the original widget form have the function of matplotlib canvas, and you can draw on it. The mplwidget.py file is as follows:
# _ * _ coding: UTF-8_*_# developer author: TXH# Development time: 2021-09-05 14 TXH# 4 import FigureCanvasQTAgg as FigureCanvasfrom matplotlib.figure import Figurefrom PyQt5.QtCore import QThreadclass MplCanvas File name: mplwidget.py# Development tool: Python 3.7 + Pycharm IDEfrom PyQt5 import QtGui,QtWidgetsfrom matplotlib.backends.backend_qt5agg\ import FigureCanvasQTAgg as FigureCanvasfrom matplotlib.figure import Figurefrom PyQt5.QtCore import QThreadclass MplCanvas (FigureCanvas QThread): def _ init__ (self): self.fig = Figure () FigureCanvas.__init__ (self, self.fig) FigureCanvas.setSizePolicy (self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) FigureCanvas.updateGeometry (self) class mplwidget (QtWidgets.QWidget): def _ init__ (self, parent=None): QtWidgets.QWidget.__init__ (self Parent) self.canvas = MplCanvas () self.vbl = QtWidgets.QVBoxLayout () self.vbl.addWidget (self.canvas) self.setLayout (self.vbl) 3.4 GUI design results
The content of the pyqt5 UI (widget_recev.py) generated by is as follows. The file is automatically generated according to the Qt ui file, so generally you only need to know which parts are in it, and you don't have to pay attention to the details of some size and location settings, because it has been done at the time of GUI design.
From PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt_Learning.UDP.GUI.mplwidget import mplwidget # change class Ui_Widget (object) according to the location of mplwidget: def setupUi (self, Widget): Widget.setObjectName ("Widget") Widget.resize (280,165) self.label_2 = QtWidgets.QLabel (Widget) self.label_2.setGeometry (QtCore.QRect (110,10,55) 16) self.label_2.setObjectName ("label_2") self.lineEdit_2 = QtWidgets.QLineEdit (Widget) self.lineEdit_2.setGeometry (QtCore.QRect (110,30,61,21) self.lineEdit_2.setObjectName ("lineEdit_2") self.pushButton = QtWidgets.QPushButton (Widget) self.pushButton.setGeometry (QtCore.QRect (10,120,71) 24) self.pushButton.setObjectName ("pushButton") self.label = QtWidgets.QLabel (Widget) self.label.setGeometry (QtCore.QRect (12,10,55,16) self.label.setObjectName ("label") self.lineEdit = QtWidgets.QLineEdit (Widget) self.lineEdit.setGeometry (QtCore.QRect (12,30,81) 21) self.lineEdit.setObjectName ("lineEdit") self.pushButton_2 = QtWidgets.QPushButton (Widget) self.pushButton_2.setGeometry (QtCore.QRect (180,120,75,24) self.pushButton_2.setObjectName ("pushButton_2") self.lineEdit_5 = QtWidgets.QLineEdit (Widget) self.lineEdit_5.setGeometry (QtCore.QRect (190,80,61) 21) self.lineEdit_5.setObjectName ("lineEdit_5") self.label_3 = QtWidgets.QLabel (Widget) self.label_3.setGeometry (QtCore.QRect (190,60,71,16) self.label_3.setObjectName ("label_3") self.label_4 = QtWidgets.QLabel (Widget) self.label_4.setGeometry (QtCore.QRect (10,60,71) 16) self.label_4.setObjectName ("label_4") self.lineEdit_3 = QtWidgets.QLineEdit (Widget) self.lineEdit_3.setGeometry (QtCore.QRect (10,80,51,21) self.lineEdit_3.setObjectName ("lineEdit_3") self.label_5 = QtWidgets.QLabel (Widget) self.label_5.setGeometry (QtCore.QRect (110,60,71) 16) self.label_5.setObjectName ("label_5") self.lineEdit_4 = QtWidgets.QLineEdit (Widget) self.lineEdit_4.setGeometry (QtCore.QRect (110,80,51,21) self.lineEdit_4.setObjectName ("lineEdit_4") self.label_6 = QtWidgets.QLabel (Widget) self.label_6.setGeometry (QtCore.QRect (70,80,21) 16) self.label_6.setObjectName ("label_6") self.retranslateUi (Widget) QtCore.QMetaObject.connectSlotsByName (Widget) def retranslateUi (self, Widget): _ translate = QtCore.QCoreApplication.translate Widget.setWindowTitle (_ translate ("Widget", "data sender")) self.label_2.setText (_ translate ("Widget") "Port") self.lineEdit_2.setText (_ translate ("Widget", "9999")) self.pushButton.setText (_ translate ("Widget", "send sine")) self.label.setText (_ translate ("Widget", "IP address") self.lineEdit.setText (_ translate ("Widget", "127.0.0.1")) self.pushButton_2.setText (_ translate ("Widget") "stop sending") self.lineEdit_5.setText (_ translate ("Widget", "8")) self.label_3.setText (_ translate ("Widget", "number of sinusoidal channels") self.label_4.setText (_ translate ("Widget", "sinusoidal frequency")) self.lineEdit_3.setText (_ translate ("Widget") "50") self.label_5.setText (_ translate ("Widget", "sinusoidal amplitude") self.lineEdit_4.setText (_ translate ("Widget", "1")) self.label_6.setText (_ translate ("Widget", "Hz")) 4 Multithreaded programming UDP communication
It is very convenient for to use Qt for interface design. The difficulty of pyqt programming lies in the underlying signal-slot function mechanism and multi-thread programming. Let's put aside multithreaded UDP programming and give a simple example of the principle of signal-slot function.
4.1 signal and slot function
The signal is equivalent to an event in the main loop of GUI. Once an event is triggered, the corresponding slot function (object method) will run.
The signal can be a built-in signal or a custom signal. The built-in signal is generally directly associated with the component, and the corresponding slot function can be constructed according to certain rules, for example:
Def on_pushButtom_clicked (self):... def on_pushButtom_2_clicked (self):... def on_pushButtom_3_clicked (self):...
Respectively corresponds to the automatic correlation slot function when the three pushButtom,pushButtom_2,pushButtom_3 buttons are triggered by the clicked () event, and the corresponding slot function is run immediately after the event is triggered. Similarly, when checkBox_5 is triggered, the following slot function is automatically associated by default to transmit the chencked Boolean signal:
Def on_checkBox_5_toggled (self,checked):...
custom signals are more flexible, sending data through the emit () function when the event is triggered. In pyqt5, the data type of signal transmission can be any type supported by python. Current tests show that numpy.array, list, str, int, float and other data types can be passed to the slot function through the signal as the input of the slot function.
Within the main thread (or GUI main loop), a simple custom signal and slot function pair is as follows.
From PyQt5.QtCore import QObjectfrom PyQt5 import QtCoreclass Test (QObject): test_signal = QtCore.pyqtSignal (list) # defines the test_signal signal def _ _ init__ (self, parent=None): super (). _ init__ (parent) self.test_signal.connect (self.print_data) # Associates the signal with the test slot function def toggle (self): a = list ([1,2,3,4) 5]) self.test_signal.emit (a) # sends a signal to the slot function @ QtCore.pyqtSlot (list) def print_data (self, list_var): # defines the slot function # once the slot function receives the data sent by test_signal Immediately execute the following content print (list_var) test = Test () test.toggle () > > [1, 2, 3, 4, 5]
The signal is generally defined before the initialization method, and as a member of the Qt class, the data type of the signal sent is given when defining the signal. The list type is used in the following example. The signal is associated with the corresponding slot function during initialization. Then send a signal to the slot function in different methods as needed, and the slot function executes the contents of the function immediately after receiving the data. The above example is relatively simple, mainly in the main thread to trigger the signal and slot function. Later, a case of multi-thread signal and slot function data transmission will be given.
4.2 Multithreading
The main interface of pyqt uses the main thread, which can be seen as an endless loop. Once a more time-consuming operation occurs in the main thread, it will lead to the false death of the main thread, which is reflected in the fact that the GUI interface is unresponsive and unable to do any operation.
When designing GUI programs, generally follows the principle of separate design of GUI interface and code interface. The main thread is only responsible for managing the actions of the basic GUI, while time-consuming operations are calculated through sub-threads.
returns to the topic of "multithreaded UDP communication". Based on the creation of GUI, the main function of the receiver of UDP communication is as follows. The code realizes three cases in which the main thread transfers data to the child thread, the child thread to the child thread and the child thread to the main thread.
Of course, all connections between signals and slot functions must be done in the main thread.
The specific method is to create a child thread instance in the main thread and take the child thread as a member of the main thread, so that the signal transmission between the child thread and the child thread, the child thread and the main thread can be realized.
# _ * _ coding: UTF-8_*_# developer author: TXH# Development time: 2021-08-26 18 TXH# 2pm File name: Receiver.py# Development tool: Python 3.7 + Pycharm IDEimport socketimport sysfrom PyQt5.QtWidgets import QApplication, QMainWindowfrom PyQt_Learning.UDP.GUI.widget_recev import Ui_MainWindowfrom PyQt5 import QtCore,uicfrom PyQt5.QtCore import QThread PyqtSlotclass QmyDialog (QMainWindow): # the main form itself occupies a main thread UDP_para = QtCore.pyqtSignal (list) sender_para = QtCore.pyqtSignal (list) def _ _ init__ (self, parent=None): super (). _ init__ (parent) self.pause=False self.statusBar (). ShowMessage ('Load UI...') If 0: self.ui = uic.loadUi # else: self.ui = Ui_MainWindow () self.ui.setupUi (self) self.statusBar (). ShowMessage ('Init Canvas...') Self.canvas = self.ui.widget.canvas # drawing setup self.canvas.ax1 = self.canvas.fig.add_subplot (111l) self.canvas.ax1.get_yaxis () .grid (True) self.statusBar () .showMessage ('Init UDP...') # status bar update self.UDP = UDPThread (self.para (1)) # create child thread 1 self.UDP_ Para.connect (self.UDP.UDP_para_update) # main thread passes the parameter self.statusBar () .showMessage ('Init plot sender...') to the UDP thread Self.Plot_fig = Plot_Thread (self.para (2)) # create child thread 2 self.UDP.send_data.connect (self.Plot_fig.send) # UDP child thread sends data to drawing child thread self.sender_para.connect (self.Plot_fig.Sender_para_update) # main thread passes parameter self.Plot_fig.plot_data.connect (self) to drawing child thread .plot _ fig) # Mapping child thread sends data to the main thread plot_fig function Let it draw self.statusBar (). ShowMessage ('Readyweights') Def on_pushButton_clicked (self): # set parameter self.update_udp_para () self.update_sender_para () self.statusBar () .showMessage ('Para changed...') Def on_pushButton_2_clicked (self): # receive data self.update_udp_para () self.update_sender_para () self.UDP.pause = False self.Plot_fig.pause=False self.UDP.start () self.ui.lineEdit.setReadOnly (True) self.ui.lineEdit_2.setReadOnly (True) self.Plot_fig.start () Self.statusBar () .showMessage ('Receiving data...') Def on_pushButton_3_clicked (self): # stop receiving and drawing self.pause=True self.update_udp_para () self.update_sender_para () self.statusBar () .showMessage ('Receiving pausedposts') Def plot_fig (self,temp): # drawing function, do not calculate, avoid main thread blocking Immediately after receiving the data, draw self.canvas.ax1.clear () self.canvas.ax1.plot (temp) self.canvas.fig.tight_layout () self.canvas.draw () def update_udp_para (self): # UPD child thread parameter setting self.UDP_para.emit (self.para (1)) def update_sender_para (self): # plotter Operator thread parameter setting self.sender_para.emit (self.para (2)) def para (self Flag): if flag==1: return list ([self.ui.lineEdit.text (), int (self.ui.lineEdit_2.text ()), self.pause]) else: return list ([int (self.ui.lineEdit_3.text ()), self.pause]) # defines the UDP receiving thread class class UDPThread (QThread): send_data = QtCore.pyqtSignal (str) def _ init__ (self Udp_para_list): super (). _ init__ () self.IP,self.Port,self.pause = udp_para_list self.s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) # set the socket protocol to UDP self.s.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR) 1) def run (self)-> None: # receiving UDP data in an endless loop try: self.s.bind ((self.IP, self.Port)) except:pass I = 1 with open ('out.txt' 'w') as f: # Save the acquired UDP data to the local txt while True: temp = self.s.recv (1024). Decode ('utf-8') # receive socket data if iComplete1: self.send_data.emit (temp) f.writelines (temp +'\ n') I = (iTun1)% 2000 if self.pause: # determine whether to jump out of the loop break def UDP_para_update (self Udp_para_list): self.Ip,self.Port,self.pause=udp_para_list# defines the drawing calculation subthread class class Plot_Thread (QThread): plot_data = QtCore.pyqtSignal (list) def _ _ init__ (self) Para_list): super (). _ _ init__ () self.pause = False self.data = [] self.max_len = para_list [0] self.i=1 def change_Len (self Len): # drawing length setting if lenself.max_len: self.data=self.data [(len (self.data)-self.max_len):] self.i= (self.i+1)% (1000) if self.i==0: self.plot_data.emit (self.data) # send data data to GUI for drawing def Sender_para_update (self) every 1000 points received Para_list): # Update the drawing length self.max_len,self.pause=para_list# if _ _ name__ = = "_ _ main__": app = QApplication (sys.argv) # call the parent constructor according to the signal of the main thread Create form form = QmyDialog () # create UI object form.show () # sys.exit (app.exec ()) #
The effect is shown as follows:
Click to record and draw, the program saves the data received by UDP at the same time, send part of the data to the GUI interface for drawing.
5 Pyinstaller is packaged into exe
When pyinstaller packages the code into exe, it is faced with the situation that the generated exe is too large, and the size of a small function exe is as high as 200m. In the final analysis, pyinstaller packages some interrelated installation packages into exe, and most installation packages are not actually used in the current project.
has been tested that pipenv can be used to create a clean virtual environment and reduce the size of exe. Install only the required pyinstaller, pyqt5, numpy and so on in the environment. The pyqt5 exe executable files generated in the virtual environment are only tens of megabytes.
If wants to further compress, you can download upx.exe, which will be placed in the Script folder under the pipenv virtual environment, and will be called automatically when pyinstaller is packaged. The amount of compression is small, but it is effective. After all, there are no other remedial measures.
runs the following code in the pipenv virtual environment:
# Gen_EXE.pyimport oserror = os.system ('pyinstaller-- clean-Fw E:\\ Pywork\ PyQt_Learning\\ UDP\\ GUI\\ Receiver.py E:\\ Pywork\\ PyQt_Learning\\ UDP\\ GUI\\ widget_recev.py E:\\ Pywork\\ PyQt_Learning\\ UDP\\ GUI\ mplwidget.py') # add all related py files if not error: print (' successfully generated exe file!')
The final size of the is about 44m, which makes it feel OK.
At this point, the study of "introduction to the process of receiving UDP data and dynamic drawing by PyQt5 GUI" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.