PyQt5 – 当鼠标悬停时为不可编辑的组合框添加边框

  • Post category:Python

对于 PyQT5 中的组合框,我们可以使用 QComboBox 控件来实现。当鼠标悬停时,我们可以添加边框来表示该组合框处于不可编辑状态。下面是详细的步骤和代码示例。

步骤

1.导入必要的库

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QComboBox, QStyle, QStyleOptionComboBox, QProxyStyle

2.创建一个自定义的样式类

class CustomComboBoxStyle(QProxyStyle):
    def subControlRect(self, control, option, subControl, widget=None):
        r = QProxyStyle.subControlRect(self, control, option, subControl, widget)
        if subControl == QStyle.SC_ComboBoxArrow and control == QStyle.CC_ComboBox and widget:
            if widget.property('hovered') or not widget.isEditable():
                r.setWidth(widget.width() - r.x() - self.pixelMetric(QStyle.PM_ScrollBarExtent))
        return r

    def drawComplexControl(self, control, option, painter, widget=None):
        if control == QStyle.CC_ComboBox and widget:
            if widget.property('hovered') or not widget.isEditable():
                option.state |= QStyle.State_On
        super().drawComplexControl(control, option, painter, widget)

3.在组合框的构造函数中使用自定义样式

class MyComboBox(QComboBox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setStyle(CustomComboBoxStyle())

示例

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QComboBox
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPalette

class CustomComboBoxStyle(QProxyStyle):
    def subControlRect(self, control, option, subControl, widget=None):
        r = QProxyStyle.subControlRect(self, control, option, subControl, widget)
        if subControl == QStyle.SC_ComboBoxArrow and control == QStyle.CC_ComboBox and widget:
            if widget.property('hovered') or not widget.isEditable():
                r.setWidth(widget.width() - r.x() - self.pixelMetric(QStyle.PM_ScrollBarExtent))
        return r

    def drawComplexControl(self, control, option, painter, widget=None):
        if control == QStyle.CC_ComboBox and widget:
            if widget.property('hovered') or not widget.isEditable():
                option.state |= QStyle.State_On
        super().drawComplexControl(control, option, painter, widget)

class MyComboBox(QComboBox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setStyleSheet("""
            QComboBox {
                height: 30px;
                width: 100px;
                font-size: 16px;
            }
        """)
        self.setStyle(CustomComboBoxStyle())

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        centralWidget = QWidget()
        self.setCentralWidget(centralWidget)

        layout = QVBoxLayout()
        centralWidget.setLayout(layout)

        comboBox1 = MyComboBox()
        comboBox2 = MyComboBox()

        comboBox2.setEditable(True)

        layout.addWidget(comboBox1)
        layout.addWidget(comboBox2)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = MainWindow()
    window.show()

    sys.exit(app.exec_())

上述示例中,我们创建了一个主窗口和两个自定义的组合框。其中,第一个组合框不可编辑,第二个组合框可编辑。在自定义的组合框 MyComboBox 的构造函数中,我们通过 self.setStyle(CustomComboBoxStyle()) 使用了自定义的样式类 CustomComboBoxStyle。在样式类 CustomComboBoxStyle 中,我们通过重写 subControlRectdrawComplexControl 方法,实现了在组合框不可编辑或鼠标悬停时添加边框的效果。

注意,在自定义的组合框构造函数中,我们通过 self.setStyleSheet() 来设置组合框的样式,这里我们设置了组合框的高度、宽度和字体大小。如果你想使组合框具有更多的样式,可以考虑在样式表中添加更多的属性。