设置不同 class 个小部件的焦点策略

Setting the focuspolicy of differents class of widgets

我目前正在学习 PyQt 概念。通过简单的示例,我正在尝试使用 Tab 键从一个小部件跳转到另一个小部件。

我设法禁用了 PushButton 上的焦点策略,使得在按下 Tab 键时无法获得焦点。但是,使用 DialogBu​​tton,我无法做到这一点。

我觉得管理此策略对于每种类型的小部件都是可能的,但我对它们的所有特性感到有点迷茫。

这是我当前的代码:

from PyQt5 import QtWidgets, QtCore, QtGui
import sys

class TabWidget(QtWidgets.QDialog): # class to implement dialog box
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Tab Widget App")

        tabWidget = QtWidgets.QTabWidget() # creation of the tab widget object
        tabWidget.addTab(FirstTab(), "First Tab") # fill with first widget
        tabWidget.addTab(SecondTab(), "Second Tab")
        tabWidget.addTab(ThirdTab(), "Third Tab")

        self.buttonbox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
        self.buttonbox.setFocusPolicy(QtCore.Qt.NoFocus)
        self.buttonbox.accepted.connect(self.accept)
        self.buttonbox.rejected.connect(self.reject)
                    
        tabWidget.addTab(FourthTab(), "Fourth Tab")            
        vbox_layout = QtWidgets.QVBoxLayout()
        vbox_layout.addWidget(tabWidget)
        vbox_layout.addWidget(self.buttonbox)
        self.setLayout(vbox_layout)

    def keyPressEvent(self, event):
        print(event.key())


class FirstTab(QtWidgets.QWidget): # class to implement simple widget
    def __init__(self):
        super().__init__()

        name = QtWidgets.QLabel("Name:")
        nameEdit = QtWidgets.QLineEdit()

        dob = QtWidgets.QLabel("Birth Date:")
        dobEdit = QtWidgets.QLineEdit()

        age = QtWidgets.QLabel("Age:")
        ageEdit = QtWidgets.QLineEdit()

        phone = QtWidgets.QLabel("Phone:")
        phoneEdit = QtWidgets.QLineEdit()

        vbox_layout = QtWidgets.QVBoxLayout()
        vbox_layout.addWidget(name)
        vbox_layout.addWidget(nameEdit)
        vbox_layout.addWidget(dob)
        vbox_layout.addWidget(dobEdit)
        vbox_layout.addWidget(age)
        vbox_layout.addWidget(ageEdit)
        vbox_layout.addWidget(phone)
        vbox_layout.addWidget(phoneEdit)
        self.setLayout(vbox_layout)
        
class SecondTab(QtWidgets.QWidget): # class to implement simple widget
    def __init__(self):
        super().__init__()

        selectGroup = QtWidgets.QGroupBox("Select Operating Systems")
        combo = QtWidgets.QComboBox()
        list = {"Windows", "Mac", "Linux"}
        combo.addItems(list)

        selectLayout = QtWidgets.QVBoxLayout()
        selectLayout.addWidget(combo)
        selectGroup.setLayout(selectLayout)

        checkGroup = QtWidgets.QGroupBox("Which Operation System Do You Like?")
        windows = QtWidgets.QCheckBox("Windows")
        mac = QtWidgets.QCheckBox("Mac")
        linux = QtWidgets.QCheckBox("Linux")

        checklayout = QtWidgets.QVBoxLayout()
        checklayout.addWidget(windows)
        checklayout.addWidget(mac)
        checklayout.addWidget(linux)
        checkGroup.setLayout(checklayout)

        mainlayout = QtWidgets.QVBoxLayout()
        mainlayout.addWidget(selectGroup)
        mainlayout.addWidget(checkGroup)
        self.setLayout(mainlayout)

class ThirdTab(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        label = QtWidgets.QLabel("Terms And Conditions")
        listwidget = QtWidgets.QListWidget()
        list = []
        
        for i in range(1,20):
            list.append("This Is Terms And Conditions")

        listwidget.insertItems(0, list)

        checkbox = QtWidgets.QCheckBox("Agree The Terms And Condition")

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(label)
        layout.addWidget(listwidget)
        layout.addWidget(checkbox)
        self.setLayout(layout)

class FourthTab(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.groupBox = QtWidgets.QGroupBox("Issue", objectName = 'groupBox')

        self.grid_layout = QtWidgets.QGridLayout(self.groupBox)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)

        self.widgetOne = QtWidgets.QTextEdit(self.groupBox, tabChangesFocus = True)
        self.widgetOne_label = QtWidgets.QLabel("widgetOne")
        self.widgetOne.setObjectName("WidgetOne")
        self.grid_layout.addWidget(self.widgetOne, 1, 0, 1, 1)
        self.grid_layout.addWidget(self.widgetOne_label, 0, 0, 1, 1)

        sizePolicy.setHeightForWidth(self.widgetOne.sizePolicy().hasHeightForWidth())
        self.grid_layout.addWidget

        self.widgetTwo = QtWidgets.QTextEdit(self.groupBox, tabChangesFocus = True)
        self.widgetTwo_label =  QtWidgets.QLabel("widgetTwo")
        self.widgetTwo.setObjectName("widgetTwo")
        self.grid_layout.addWidget(self.widgetTwo, 1, 1, 1, 1)
        self.grid_layout.addWidget(self.widgetTwo_label, 0, 1, 1, 1)
        
        sizePolicy.setHeightForWidth(self.widgetTwo.sizePolicy().hasHeightForWidth())
        self.grid_layout.addWidget

        self.widgetThree = QtWidgets.QTextEdit(self.groupBox, tabChangesFocus = True)
        self.widgetThree_label =  QtWidgets.QLabel("widgetThree")
        self.widgetThree.setObjectName("widgetThree")
        self.grid_layout.addWidget(self.widgetThree, 4, 0, 1, 1)
        self.grid_layout.addWidget(self.widgetThree_label, 3, 0, 1, 1)

        sizePolicy.setHeightForWidth(self.widgetThree.sizePolicy().hasHeightForWidth())
        self.grid_layout.addWidget

        self.widgetFour = QtWidgets.QTextEdit(self.groupBox, tabChangesFocus = True)
        self.widgetFour_label =  QtWidgets.QLabel("widgetFour")
        self.widgetFour.setObjectName("WidgetFour")
        self.grid_layout.addWidget(self.widgetFour, 4, 1, 1, 1)
        self.grid_layout.addWidget(self.widgetFour_label, 3, 1, 1, 1)

        sizePolicy.setHeightForWidth(self.widgetFour.sizePolicy().hasHeightForWidth())
        self.grid_layout.addWidget

        v_layout = QtWidgets.QVBoxLayout()
        v_layout.addWidget(self.groupBox)
        self.setLayout(v_layout)

        self.setTabOrder(self.widgetOne, self.widgetTwo)
        self.setTabOrder(self.widgetTwo, self.widgetThree)
        self.setTabOrder(self.widgetThree, self.widgetFour)
        self.setTabOrder(self.widgetFour, self.widgetOne)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    tabwidget = TabWidget()
    tabwidget.show()
    sys.exit(app.exec_())

涉及的按钮是我的QDialogBu​​tton类型的“按钮框”。我已将焦点策略设置为 NoFocus。但是当我启动脚本并在 FourthTab 中使用 Tab 键时,焦点仍然在确定/取消上。

这个选项有什么限制吗?还是我遗漏了什么?

焦点策略未传播给子项。

当您在按钮框上设置焦点策略时,它的子项(按钮)仍然有它们的默认策略(即 StrongFocus)。

如果你想为所有按钮禁用它,你需要明确地做,例如:

self.buttonbox.button(self.buttonbox.Ok).setFocusPolicy(QtCore.Qt.NoFocus)

或者,对于任何按钮:

    for button in self.buttonbox.findChildren(QtWidgets.QAbstractButton):
        button.setFocusPolicy(QtCore.Qt.NoFocus)

请注意,keyPressEvent 仅在其子项的 none 已处理时才由父项接收,因此如果您尝试捕获 Tab 你需要在整个 QApplication 上安装一个事件过滤器,否则仍然有可能某些小部件会捕获并接受它,从而阻止你接收它。