python - 在 PyQt5 中创建复杂的自定义小部件并将其添加到 QGridlayout
问题描述
我必须创建一个如下所示的自定义小部件:
custom_widget_sketch
每个自定义小部件代表一个 LIPO 电池,并显示电池电压(V)
、状态文本(charging, discharging, etc)
、电池序列号(S/N)
和三种状态LEDs
(黄色、绿色和红色)
创建自定义小部件后,我需要在 6*5 的网格中添加其中的 30 个。我在这里的假设是,一旦我创建了该自定义小部件,它应该就像在 QGridLayout 中添加一个 QPushButton 一样简单,如下所示:
custom_layput = QGridLayout()
custom_layout.addWidget(custom_widget, 0, 0)
custom_layout.addWidget(custom_widget, 0, 1)
.
.
.
custom_layout.addWidget(custom_widget, 6, 5)
最终屏幕如下所示:
main_window_sketch
考虑到所有这些要求,我有以下问题:
- 我能否使用 PyQt5 创建如此复杂/丰富的自定义小部件?可行吗?
- 这是创建自定义小部件的正确方法吗:首先使用 QPainter 绘制一个正方形(这是 custom_widget_sketch 中的蓝色正方形),然后添加 QLineEdits 以显示电压 (V) 文本、序列号 (S/N) 文本和状态文本,添加一个 QLabel 用于在自定义小部件中显示“V”、“S/N”和“STATUS”标签,然后绘制三个圆圈:黄色、绿色和红色各一个
LEDs
,然后使用QVBoxLayout
和的组合QHBoxLayout 用于排列QLineEdits
、QLabels
、 正方形和圆形(LED 指示灯) - 如何打包这个自定义小部件,以便我可以像添加 a
QPushButton
或 a一样简单地将其添加到布局中QLineEdit
?
PS:custom_widget_sketch 在左上角还包含一条线和一个正方形,里面有三条线。这是为了描述 LIPO 电池的连接器。现在实施它可能太复杂了。因此,即使我能够实现这两个元素以外的所有内容,我也会很高兴
我经历了一些 SO 问题,但它们都参考了一个教程,这不是我的最终目标。
我将不胜感激任何代码片段、要遵循的代码/步骤的一般大纲或任何文章/教程的链接,这些文章/教程创建了类似于我希望创建的自定义小部件。
解决方案
我最终创建的自定义小部件的 Python 代码。小部件如下所示:
from PyQt5.QtGui import QPainter, QPen,QBrush,QColor
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout,QPushButton, QLineEdit, QLabel, QVBoxLayout, QHBoxLayout, QSizePolicy, QGroupBox
import sys
class BatteryStatusWidget(QWidget):
def __init__(self):
super(BatteryStatusWidget, self).__init__()
#Voltage widgets
self.voltage_text = QLineEdit()
self.voltage_text.setReadOnly(True)
self.voltage_label = QLabel("V")
self.voltage_label.setStyleSheet("QLabel {color : white}")
#Status widgets
self.status_text = QLineEdit()
self.status_text.setReadOnly(True)
self.status_label = QLabel("STATUS")
self.status_label_font = QtGui.QFont()
self.status_label_font.setPointSize(12)
self.status_label.setFont(self.status_label_font)
self.status_label.setAlignment(QtCore.Qt.AlignCenter)
self.status_label.setStyleSheet("QLabel {color : white}")
#Serial number
self.serial_number_text = QLineEdit()
self.serial_number_label = QLabel("S/N")
#LED widgets
self.yellow_led_label = QLabel()
self.yellow_led_label.setStyleSheet("QLabel {background-color : yellow; border-color : black; border-width : 1px; border-style : solid; border-radius : 10px; min-height: 20px; min-width: 20px}")
self.green_led_label = QLabel()
self.green_led_label.setStyleSheet("QLabel {background-color : green; border-color : black; border-width : 1px; border-style : solid; border-radius : 10px; min-height: 20px; min-width: 20px}")
self.red_led_label = QLabel()
self.red_led_label.setStyleSheet("QLabel {background-color : red; border-color : black; border-width : 1px; border-style : solid; border-radius : 10px; min-height: 20px; min-width: 20px}")
#Number Identifier Label
#This label is for tagging the widget with the same label as on the PCB
self.number_label = QLabel("Test")
self.number_label.setAlignment(QtCore.Qt.AlignCenter)
self.number_label_font = QtGui.QFont()
self.number_label_font.setPointSize(12)
self.number_label_font.setBold(True)
self.number_label.setFont(self.number_label_font)
#Layouts
#voltage layout
self.voltage_layout = QHBoxLayout()
self.voltage_layout.addWidget(self.voltage_text)
self.voltage_layout.addWidget(self.voltage_label)
#Serial number layout
self.serial_num_layout = QHBoxLayout()
self.serial_num_layout.addWidget(self.serial_number_label)
self.serial_num_layout.addWidget(self.serial_number_text)
#Voltage and status box layouts
self.blue_container = QWidget()
self.blue_container.setStyleSheet("background-color:rgb(77, 122, 194);")
self.blue_box_layout = QVBoxLayout()
self.blue_box_layout.addLayout(self.voltage_layout)
self.blue_box_layout.addWidget(self.status_text)
self.blue_box_layout.addWidget(self.status_label)
self.blue_container.setLayout(self.blue_box_layout)
#Blue box+ serial num layout
self.non_led_layout = QVBoxLayout()
#self.non_led_layout.addWidget(self.number_label)
self.non_led_layout.addWidget(self.blue_container)
self.non_led_layout.addLayout(self.serial_num_layout)
#LED layout
self.led_layout = QVBoxLayout()
self.led_layout.addWidget(self.yellow_led_label)
self.led_layout.addWidget(self.green_led_label)
self.led_layout.addWidget(self.red_led_label)
self.led_layout.addStretch(1)
#Main Layout
self.main_layout = QHBoxLayout()
self.main_layout.addLayout(self.non_led_layout)
self.main_layout.addLayout(self.led_layout)
#Main group box
self.main_group_box = QGroupBox()
self.main_group_box.setStyleSheet("QGroupBox{font-size: 10px}")
self.main_group_box.setTitle("Chan #")
self.main_group_box.setLayout(self.main_layout)
#Outer main layout to accomodate the group box
self.outer_main_layout = QVBoxLayout()
self.outer_main_layout.addWidget(self.main_group_box)
#Set the main layout
self.setLayout(self.outer_main_layout)
self.setWindowTitle("Battery Widget")
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = BatteryStatusWidget()
main_window.show()
app.exec_()
我能够轻松地创建自定义小部件的 30 个实例并将其添加到QGridLayout
我在我的问题中发布的。最终的 GUI 屏幕如下所示:
推荐阅读
- c++ - 递归模板函数内的无限循环
- python - 一维数组和二维数组元素搜索
- asp.net-core - 有没有办法确保实体框架核心中的数据库迁移?
- android - 如何在片段的活动中添加导航底栏
- python - 在多索引中移动值并输入总行 pandas
- jq - 将 jq 的输出组合到每条记录输出的单行上
- flutter - http Dart包示例已过时,如何使用client.get()
- javascript - 我只是想知道是否有人可以澄清为什么在 JavaScript 中的函数回调期间使用方括号?
- sql - 一个 INSERT ALL 中的最大行数
- ios - 带有 PageTabViewStyle() 的 TabView 不使用 ScrollView 中的可用高度