【问题标题】:Qt: change QFrame border color on focus inQt:在焦点上更改 QFrame 边框颜色
【发布时间】:2018-06-17 02:11:17
【问题描述】:

我在布局中有一堆小部件,布局是 QFrame 的子级。这允许我围绕这个布局创建一个边框。现在,当任何孩子获得焦点时,我想更改 QFrame 的边框颜色以向用户指示当前焦点所在的位置。如何最好地做到这一点,而无需将每个子类的 focuInEvent/focusOutEvent 子类化并回调其父小部件(QFrame)的样式表?在测试 QFrame 的 focusInEvent 时,我永远无法触发它。是否有某种儿童焦点事件之类的?

【问题讨论】:

  • 您可以将每个孩子连接到某个处理程序,该处理程序将运行类似 sender()->parent()->doSomeThingWithBorder();
  • 谢谢@JLev,这可能行得通。实际上,我在晚上结束时使用事件过滤器(我之前只是模糊地意识到)让这个工作。我很快就会发布答案,我只是在寻找对所有内容进行子类化以保持整洁的最佳方法。

标签: python qt pyqt4


【解决方案1】:

我认为在尝试了一些事情并了解了有关 eventFilter 的更多信息之后,我想出了一个很好的解决方案。基本上我发现您需要在父级中安装一个事件过滤器并捕获子级的所有焦点事件。展示一个例子更容易,这比它可能需要的要复杂一些,但它说明了一些要点:

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_())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-29
    • 2022-11-27
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 2016-11-08
    相关资源
    最近更新 更多