Article Directory
one. foreword
Recently, on a whim, I want to make a task manager imitating win10, practice the basic layout and the use of QChart, realize task management, chart viewing and other functions, write this podcast to record some experience and experience in the development process, and provide readers with some ideas. The software is packaged and placed at the end of the article.
two. exhibit
1. Main interface
1. Process
The detailed information table supports sorting by table header, and clicking the table header will automatically sort.
2. Performance
1.CPU
The software will obtain the current CPU information every second, draw it into a chart and display it on the page, and the information below is also updated in real time.
Animation display
2. Memory
The memory also refreshes the interface every 1 second, and draws a line graph and a memory combination graph.
Animation display
3. Brief information
Click the button in the lower left corner on the "Detailed Information" page to jump to the "Brief Information" page.
Animation display
4. Detailed information
The detailed information table also supports sorting by table header, and clicking the table header will automatically sort.
5. New task
You can enter the cmd command or click Browse to open a file
three. Design ideas
1. UI design
1. Main interface
The overall layout is a vertical layout of two frames, a stackWidget is stored in the upper frame, a tabWidget is placed on the first page, and there are three tabs in the tabWidget, which are "process", "performance" and "detailed information", and another frame is placed in the "performance tab". , with chart details below. A listWidget is placed on the second page of stackWidget, which is used to place a custom "detailed information widget".
1. Process
2. Performance
3. Detailed information
4. New task
The new task is an independent widget whose property is QWidget.
5. Chart information component
It is used to generate the chart and the basic information of the chart, and its content will be changed after instantiation. It is also an independent widget, and its property is QWidget.
2. Overall code design
1. Project design experience
Before designing the Pyqt project, the author will conduct research to evaluate the overall difficulty of the UI and functions, cut the complexity and simplify it, and look at the project as a whole. Usually my Pyqt project will have at least four parts: 1. main_ui.py The main window UI is converted from the ui file in xml format into Python code by the pyuic tool. 2. engine.py The software engine is the core code executed by the software after the user operates, and it can exist independently of the project in theory. 3. CWidgets.py, this file is used to store custom Widgets and debugging codes of related sub-windows. 4. main_GUI.py main window logic call is that it links engine, Cwidgets and main_ui together, which includes main window-related scheduling, sub-window instantiation, and core engine calling code.
2. Other experience in project design
Always maintain the code design idea of "high cohesion and low coupling" in project design, look at the parts from the whole, and then look at the whole from the parts, carefully split each component, and finally call each sub-component from the main file.
3. Other experience
Four. source code
Here is the main window code of the UI, which is converted from pyuic and includes the main layout.
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'task_god_ui.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(725, 522)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/icons/icons/QQ截图20230709080218.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
MainWindow.setStyleSheet("#QTableWidget,QListWidget,#toolButton_showDetail{border:none;}\n"
"*{font-family:\"微软雅黑\"}\n"
"QFrame,#tabWidget,QStackedWidget,QStackedWidget::page{\n"
" background-color: rgb(255, 255, 255);\n"
"}\n"
"QFrame,QTabWidget,QStackedWidget::page,#scrollArea,#scrollAreaWidgetContents{\n"
" background-color: rgb(255, 255, 255);\n"
"}\n"
"#tableWidget::item,#tableWidget_2::item{border-left:1px solid rgb(229, 229, 229);}\n"
"QTableWidget::item:hover,QTableWidget::item:selected{\n"
" background-color:rgb(229, 243, 255);\n"
"}\n"
"QScrollArea{border:none;}")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setSpacing(0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.stackedWidget = QtWidgets.QStackedWidget(self.frame)
self.stackedWidget.setObjectName("stackedWidget")
self.page = QtWidgets.QWidget()
self.page.setObjectName("page")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.page)
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setSpacing(0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.tabWidget = QtWidgets.QTabWidget(self.page)
self.tabWidget.setAutoFillBackground(False)
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.tab)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setSpacing(0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.tableWidget = QtWidgets.QTableWidget(self.tab)
self.tableWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tableWidget.setAutoFillBackground(True)
self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tableWidget.setAlternatingRowColors(False)
self.tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableWidget.setShowGrid(False)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(7)
self.tableWidget.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(5, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(6, item)
self.tableWidget.horizontalHeader().setVisible(True)
self.tableWidget.horizontalHeader().setCascadingSectionResizes(True)
self.tableWidget.horizontalHeader().setSortIndicatorShown(True)
self.tableWidget.horizontalHeader().setStretchLastSection(True)
self.tableWidget.verticalHeader().setVisible(False)
self.tableWidget.verticalHeader().setCascadingSectionResizes(True)
self.tableWidget.verticalHeader().setSortIndicatorShown(True)
self.tableWidget.verticalHeader().setStretchLastSection(True)
self.horizontalLayout_4.addWidget(self.tableWidget)
self.tabWidget.addTab(self.tab, "")
self.tab_3 = QtWidgets.QWidget()
self.tab_3.setObjectName("tab_3")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_3)
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.frame_3 = QtWidgets.QFrame(self.tab_3)
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.frame_3)
self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_5.setSpacing(0)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.scrollArea = QtWidgets.QScrollArea(self.frame_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth())
self.scrollArea.setSizePolicy(sizePolicy)
self.scrollArea.setMinimumSize(QtCore.QSize(240, 0))
self.scrollArea.setMaximumSize(QtCore.QSize(240, 16777215))
self.scrollArea.setStyleSheet("")
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 240, 30))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollAreaWidgetContents.sizePolicy().hasHeightForWidth())
self.scrollAreaWidgetContents.setSizePolicy(sizePolicy)
self.scrollAreaWidgetContents.setMinimumSize(QtCore.QSize(240, 0))
self.scrollAreaWidgetContents.setMaximumSize(QtCore.QSize(240, 16777215))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout_8.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_8.setSpacing(0)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.verticalLayout_5 = QtWidgets.QVBoxLayout()
self.verticalLayout_5.setContentsMargins(-1, 0, 3, -1)
self.verticalLayout_5.setSpacing(0)
self.verticalLayout_5.setObjectName("verticalLayout_5")
spacerItem = QtWidgets.QSpacerItem(0, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_5.addItem(spacerItem)
self.verticalLayout_8.addLayout(self.verticalLayout_5)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.horizontalLayout_5.addWidget(self.scrollArea)
self.line_2 = QtWidgets.QFrame(self.frame_3)
self.line_2.setFrameShape(QtWidgets.QFrame.VLine)
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_2.setObjectName("line_2")
self.horizontalLayout_5.addWidget(self.line_2)
self.stackedWidget_2 = QtWidgets.QStackedWidget(self.frame_3)
self.stackedWidget_2.setObjectName("stackedWidget_2")
self.page_3 = QtWidgets.QWidget()
self.page_3.setObjectName("page_3")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.page_3)
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_6.setSpacing(0)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.stackedWidget_2.addWidget(self.page_3)
self.page_4 = QtWidgets.QWidget()
self.page_4.setObjectName("page_4")
self.stackedWidget_2.addWidget(self.page_4)
self.horizontalLayout_5.addWidget(self.stackedWidget_2)
self.horizontalLayout_5.setStretch(0, 1)
self.horizontalLayout_5.setStretch(2, 4)
self.verticalLayout_3.addWidget(self.frame_3)
self.tabWidget.addTab(self.tab_3, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.tab_2)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.tableWidget_2 = hoverTableWidget(self.tab_2)
self.tableWidget_2.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tableWidget_2.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tableWidget_2.setShowGrid(False)
self.tableWidget_2.setObjectName("tableWidget_2")
self.tableWidget_2.setColumnCount(5)
self.tableWidget_2.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.tableWidget_2.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget_2.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget_2.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget_2.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget_2.setHorizontalHeaderItem(4, item)
self.tableWidget_2.horizontalHeader().setStretchLastSection(False)
self.tableWidget_2.verticalHeader().setVisible(False)
self.tableWidget_2.verticalHeader().setSortIndicatorShown(False)
self.tableWidget_2.verticalHeader().setStretchLastSection(False)
self.horizontalLayout.addWidget(self.tableWidget_2)
self.tabWidget.addTab(self.tab_2, "")
self.verticalLayout_2.addWidget(self.tabWidget)
self.stackedWidget.addWidget(self.page)
self.page_2 = QtWidgets.QWidget()
self.page_2.setObjectName("page_2")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.page_2)
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_4.setSpacing(0)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.listWidget = QtWidgets.QListWidget(self.page_2)
self.listWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.listWidget.setObjectName("listWidget")
self.verticalLayout_4.addWidget(self.listWidget)
self.stackedWidget.addWidget(self.page_2)
self.horizontalLayout_2.addWidget(self.stackedWidget)
self.verticalLayout.addWidget(self.frame)
self.line = QtWidgets.QFrame(self.centralwidget)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.verticalLayout.addWidget(self.line)
self.frame_2 = QtWidgets.QFrame(self.centralwidget)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.toolButton_showDetail = HoverBtn(self.frame_2)
self.toolButton_showDetail.setIconSize(QtCore.QSize(30, 30))
self.toolButton_showDetail.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.toolButton_showDetail.setObjectName("toolButton_showDetail")
self.horizontalLayout_3.addWidget(self.toolButton_showDetail)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem1)
self.termite_bt = QtWidgets.QPushButton(self.frame_2)
self.termite_bt.setEnabled(False)
self.termite_bt.setObjectName("termite_bt")
self.horizontalLayout_3.addWidget(self.termite_bt)
self.verticalLayout.addWidget(self.frame_2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 725, 23))
self.menubar.setObjectName("menubar")
self.menu = QtWidgets.QMenu(self.menubar)
self.menu.setObjectName("menu")
self.menu_2 = QtWidgets.QMenu(self.menubar)
self.menu_2.setObjectName("menu_2")
self.menu_3 = QtWidgets.QMenu(self.menubar)
self.menu_3.setObjectName("menu_3")
self.menu_4 = QtWidgets.QMenu(self.menu_3)
self.menu_4.setObjectName("menu_4")
MainWindow.setMenuBar(self.menubar)
self.actionrun = QtWidgets.QAction(MainWindow)
self.actionrun.setShortcutContext(QtCore.Qt.WindowShortcut)
self.actionrun.setObjectName("actionrun")
self.actionexit = QtWidgets.QAction(MainWindow)
self.actionexit.setObjectName("actionexit")
self.actiontop = QtWidgets.QAction(MainWindow)
self.actiontop.setCheckable(True)
self.actiontop.setChecked(True)
self.actiontop.setObjectName("actiontop")
self.actionfre = QtWidgets.QAction(MainWindow)
self.actionfre.setObjectName("actionfre")
self.actionhi = QtWidgets.QAction(MainWindow)
self.actionhi.setCheckable(True)
self.actionhi.setObjectName("actionhi")
self.actionnor = QtWidgets.QAction(MainWindow)
self.actionnor.setCheckable(True)
self.actionnor.setChecked(True)
self.actionnor.setObjectName("actionnor")
self.actiondi = QtWidgets.QAction(MainWindow)
self.actiondi.setCheckable(True)
self.actiondi.setObjectName("actiondi")
self.actiontm = QtWidgets.QAction(MainWindow)
self.actiontm.setCheckable(True)
self.actiontm.setObjectName("actiontm")
self.actionabu = QtWidgets.QAction(MainWindow)
self.actionabu.setObjectName("actionabu")
self.menu.addAction(self.actionrun)
self.menu.addAction(self.actionexit)
self.menu_2.addAction(self.actiontop)
self.menu_4.addAction(self.actionhi)
self.menu_4.addAction(self.actionnor)
self.menu_4.addAction(self.actiondi)
self.menu_4.addAction(self.actiontm)
self.menu_3.addAction(self.actionfre)
self.menu_3.addAction(self.menu_4.menuAction())
self.menu_3.addAction(self.actionabu)
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.menubar.addAction(self.menu_3.menuAction())
self.retranslateUi(MainWindow)
self.stackedWidget.setCurrentIndex(0)
self.tabWidget.setCurrentIndex(0)
self.stackedWidget_2.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "任务管理器"))
self.tableWidget.setSortingEnabled(True)
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "名称"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "状态"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "CPU"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "内存"))
item = self.tableWidget.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "磁盘"))
item = self.tableWidget.horizontalHeaderItem(5)
item.setText(_translate("MainWindow", "网络"))
item = self.tableWidget.horizontalHeaderItem(6)
item.setText(_translate("MainWindow", "PID"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "进程"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "性能"))
self.tableWidget_2.setSortingEnabled(True)
item = self.tableWidget_2.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "名称"))
item = self.tableWidget_2.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "PID"))
item = self.tableWidget_2.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "状态"))
item = self.tableWidget_2.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "用户名"))
item = self.tableWidget_2.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "CPU"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "详细信息"))
self.toolButton_showDetail.setText(_translate("MainWindow", "简略信息"))
self.termite_bt.setText(_translate("MainWindow", "结束任务"))
self.menu.setTitle(_translate("MainWindow", "文件"))
self.menu_2.setTitle(_translate("MainWindow", "选项"))
self.menu_3.setTitle(_translate("MainWindow", "查看"))
self.menu_4.setTitle(_translate("MainWindow", "更新速度"))
self.actionrun.setText(_translate("MainWindow", "运行新任务"))
self.actionexit.setText(_translate("MainWindow", "退出"))
self.actiontop.setText(_translate("MainWindow", "置于顶层"))
self.actionfre.setText(_translate("MainWindow", "立即刷新"))
self.actionhi.setText(_translate("MainWindow", "高"))
self.actionnor.setText(_translate("MainWindow", "正常"))
self.actiondi.setText(_translate("MainWindow", "低"))
self.actiontm.setText(_translate("MainWindow", "已暂停"))
self.actionabu.setText(_translate("MainWindow", "关于作者"))
from CWidgets import HoverBtn, hoverTableWidget
import resources_rc
five. Summarize
This time, I used Pyqt5 to make a win10-like task manager, which supports process management, visually displays the memory, CPU and other information of windows devices, and supports new tasks. Write this article to record my development ideas and share my development results with you by the way. The software is packaged and placed on Lanzuo Cloud , and you can pick it up yourself. Finally, I hope everyone can discuss more, you can leave a message or send me a private message, I will read it, and everyone should not be stingy with your praise! thank you all!
six. refer to
- QCharts - 4. Detailed explanation of QValueAxis class
- "Python" uses psutil to obtain parameter information such as computer CPU memory
- pyqt5, Qchart draws a line chart, sets multiple Y axes with different scales, modifies the coordinate axis of the custom line chart, and changes the background color of the line chart
- python --psutil(cpu, memory, disk condition, end specified process, port occupation)
- Win10 Tips: Knowledge Introduction of Win10 Task Manager