我在布局中有一堆小部件,布局是QFrame的子级。这允许我在这个布局周围创建一个边框。现在当任何一个孩子获得焦点时,我想改变QFrame的边框颜色,以向用户指示焦点当前所在的位置。如何最好地做到这一点,而不是将每个孩子的focuInEvent / focusOutEvent子类化回其父窗口小部件(QFrame)的样式表?在测试QFrame的focusInEvent时,我永远无法触发它。是否存在某种儿童焦点事件?
答案 0 :(得分: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_())