以多选一的选择器为例,来实践一下工程实用级别的组合式部件设计。自己之前做的自定义的组合式部件,结构不够简单优化,在实际的工程里面,使用部件的过程比较繁琐。所以,这里来做一个优化的实验。
之所以做这个组合部件,而不用Qt Designer自带的QRadioButton,是因为我不会修改自带的QRadioButton,无法改变它的指示器圆点尺寸和颜色,我希望实现一些自定义的特殊效果和功能。
这个部件的特点是有着若干个相同品种的子部件,但不确定数量。子部件由两部分组成:控制器和指示器,“就地控制”、“远程控制”、“自动运行”这几个文字标签构成了控制器,后面的方框是指示器。当点击控制器,指示器做出颜色状态改变,并发射信号。
设计的目标:
1、尽量在python程序里面不要手动逐个输入各个子部件的具体名称,因为当画面复杂时这将是一个很大的工作量。
2、把部件做成模块,在Qt Designer里面可以简单ctrl+拖拽复制。
3、当Qt Designer里面放置好部件以后,有简单的方法实现部件的自动或半自动初始化和特性定义。
过程记录:
1、Qt Designer里面新建一个QGroupBox作为容器部件,三个纯文字QLabel作为控制器,三个圆角矩形QLabel作为指示器。各个部件命名如下:
父部件:_selector_1
子部件:_control0_selector_1:选择器0
_control1_selector_1:选择器1
_control2_selector_1:选择器2
_state0_selector_1:指示器0
_state1_selector_1:指示器1
_state2_selector_1:指示器2
命名的规律:需要自动运行初始化的自定义的组合部件首字母为"_ ",用以和其他不用初始化部件区分开(例如固定内容的文字标签、装饰用的线条之类的);子部件的名称的前半部分是子部件的分类和编号,如control0,后半部分是容器部件的名字,如selector_1,从命名上就可以看出子部件的功能以及它属于哪个容器部件;容器部件的最后一位数字是顺序号,当需要多个相同的容器部件时,直接ctrl+拖拽复制,顺序号就会自动递增。
完成之后,将所有的子部件拖入容器部件,构成一个组合部件,如图:
至此,前端工作告一段落,开始后端的编程。
2、自定义的QLabel
由于默认的QLabel是不带鼠标事件的,需要自定义一下鼠标的进入、点击、释放、离开等各个事件。代码如下:
from PyQt5.QtWidgets import QLabel
from PyQt5.Qt import pyqtSignal
class MyLabel(QLabel): # 自定义的Qlabel
Entry = pyqtSignal() # 鼠标进入
Leave = pyqtSignal() # 鼠标离开
clicked = pyqtSignal() # 鼠标点击
Release = pyqtSignal() # 鼠标释放
def __init__(self, parent=None):
super(MyLabel, self).__init__(parent)
self.style_normal = None
self.style_last = None
self.style_on = None
self.style_enter = None
self.style_clicked = None
self.Entry.connect(lambda: self.set_style(self.style_enter)) # 鼠标进入后改变样式表
self.clicked.connect(lambda: self.set_style(self.style_clicked))
self.Release.connect(lambda: self.set_style(self.style_last)) # 鼠标释放后改变样式表
self.Leave.connect(lambda: self.set_style(self.style_last)) # 鼠标离开后改变样式表
def init(self, style_normal='color: rgb(0, 0, 0);background-color: rgba(255, 255, 255, 0);',
style_enter='border:1px solid #039806;border-radius:2px;background-color: rgba(194, 194, 194, 150);',
style_clicked='border-radius:2px;background-color: rgba(194, 194, 194, 150);',
style_on='border-radius:2px;background-color: #039806;border:2px solid #868686;border-radius:2px;'):
self.style_normal = style_normal # 常态style
self.style_enter = style_enter # 鼠标悬停后的style
self.style_clicked = style_clicked # 鼠标点击后的style
self.style_on = style_on
def set_style(self, style):
self.setStyleSheet(style)
def mousePressEvent(self, event): # 重写鼠标点击事件
self.clicked.emit() # 左单击
def enterEvent(self, event): # 重新定义鼠标悬停事件
self.style_last = self.styleSheet()
self.Entry.emit()
def leaveEvent(self, event): # 重新定义鼠标离开事件
self.Leave.emit()
def mouseReleaseEvent(self, event): # 重新定义鼠标释放事件mouseReleaseEvent
self.Release.emit()
代码里面有两个初始化函数__init__和init,第一个是默认在后台自动运行的初始化,第二个是需要在主程序里面运行一次的初始化,第二个初始化的目的是可以灵活定义一些特性,比如同一个项目中需要有不同背景颜色的同类部件,就可以根据需要单独修改相对应的参数来实现。
将以上代码保存在主程序同文件夹下,并命名为MyLabel.py。
回到Qt Designer,打开之前的ui文件,在画面空白处点右键:
填写类和头文件的名称,然后点“添加”:
在三个控制器上分别点右键,提升为,将其提升为刚刚自定义的QLabel:
这样,控制器就基本完成了 。新建python文件,输入代码:
from PyQt5 import uic
from sys import exit, argv
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == '__main__':
app = QApplication(argv)
# 读取 UI 文件并转换为 Python 代码
ui_file = '../UIS/test2.ui' # 更换为实际的ui文件地址
form0 = uic.loadUi(ui_file) # 创建显示界面
form0._control0_selector_1.init() # 部件的初始化
form0._control1_selector_1.init()
form0._control2_selector_1.init(style_enter='border:1px solid #868686;border-radius:2px;background-color: rgba(194, 56, 37, 200);') # 控制器的control2需要单独定义
form0.show()
exit(app.exec_())
运行截图:
可以看到,控制器control2由于采用了单独的init初始化参数,其显示效果是与默认的效果有区别的。这也正是自己制作部件的优势所在,你可以实现一些默认部件不具备的特殊效果和功能。
下一步的任务是继续定义容器部件和指示器部件,以及实现预期的功能。