代码之家  ›  专栏  ›  技术社区  ›  Spencer

Qt:在聚焦时更改QFrame边框颜色

  •  0
  • Spencer  · 技术社区  · 6 年前

    我在布局中有很多小部件,布局是QFrame的子级。这允许我在此布局周围创建边框。现在,当任何子对象接收到焦点时,我想更改QFrame的边框颜色,以向用户指示当前焦点所在的位置。如果不将每个子控件的focuInEvent/focusOutEvent子类化并回调到其父小部件(QFrame)的样式表中,该怎么做呢?当测试到QFrame的焦点时,我永远无法触发它。有什么儿童焦点事件吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Spencer    6 年前

    我想在尝试了一些事情并学习了很多关于event filter的知识之后,我想出了一个很好的解决方案。基本上,我发现您需要在父级中安装一个事件过滤器并捕获子级的所有焦点事件。举一个例子比较容易,这比它可能需要的复杂一些,但是它说明了一些重要的点:

    import os
    import sys
    from PyQt4 import QtGui, QtCore
    
    
    class BasePanel(QtGui.QWidget):
        """This is more or less abstract, subclass it for 'panels' in the main UI"""
        def __init__(self, parent=None):
            super(BasePanel, self).__init__(parent)
            self.frame_layout = QtGui.QVBoxLayout()
            self.frame_layout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(self.frame_layout)
    
            self.frame = QtGui.QFrame()
            self.frame.setObjectName("base_frame")
            self.frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
            self.frame.setLineWidth(1)
            self.frame_layout.addWidget(self.frame)
    
            self.base_layout = QtGui.QVBoxLayout()
            self.frame.setLayout(self.base_layout)
    
            self.focus_in_color = "rgb(50, 255, 150)"
            self.focus_out_color = "rgb(100, 100, 100)"
            self.frame.setStyleSheet("#base_frame {border: 1px solid %s}" % self.focus_out_color)
            self.installEventFilter(self) # this will catch focus events
            self.install_filters()
    
        def eventFilter(self, object, event):
            if event.type() == QtCore.QEvent.FocusIn:
                self.frame.setStyleSheet("#base_frame {border: 1px solid %s}" % self.focus_in_color)
            elif event.type() == QtCore.QEvent.FocusOut:
                self.frame.setStyleSheet("#base_frame {border: 1px solid %s}" % self.focus_out_color)
            return False # passes this event to the child, i.e. does not block it from the child widgets
    
        def install_filters(self):
            # this will install the focus in/out event filter in all children of the panel
            for widget in self.findChildren(QtGui.QWidget):
                widget.installEventFilter(self)
    
    
    class LeftPanel(BasePanel):
        def __init__(self, parent=None):
            super(LeftPanel, self).__init__(parent)
    
            title = QtGui.QLabel("Left Panel")
            title.setAlignment(QtCore.Qt.AlignCenter)
            self.base_layout.addWidget(title)
    
            edit = QtGui.QLineEdit()
            self.base_layout.addWidget(edit)
    
    
    
    class RightPanel(BasePanel):
        def __init__(self, parent=None):
            super(RightPanel, self).__init__(parent)
    
            title = QtGui.QLabel("Right Panel")
            title.setAlignment(QtCore.Qt.AlignCenter)
            self.base_layout.addWidget(title)
    
            edit = QtGui.QLineEdit()
            self.base_layout.addWidget(edit)
    
    class MainApp(QtGui.QMainWindow):
        def __init__(self):
            super(MainApp, self).__init__()
    
            main_layout = QtGui.QHBoxLayout()
            central_widget = QtGui.QWidget()
            central_widget.setLayout(main_layout)
            self.setCentralWidget(central_widget)
    
            left_panel = LeftPanel()
            main_layout.addWidget(left_panel)
    
            right_panel = RightPanel()
            main_layout.addWidget(right_panel)
    
    
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        ex = MainApp()
        ex.show()
    
        sys.exit(app.exec_())