ClemZer
ClemZer

Reputation: 17

Setting the focuspolicy of differents class of widgets

I am currently learning PyQt concepts. Through easy examples, I am trying to play with the tab key to jump from one widget to another.

I manage to disable the focus policy on a PushButton, making it impossible to get the focus on it while pushing Tab. However, with a DialogButton, I do not manage to do so.

I feel managing this policy is possible with every type of widget, but I feel a bit lost with all their specificities.

Here is my current code :

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

The involved button is my "buttonbox" of type QDialogButton. I have set the focus policy to NoFocus. But when I launch the script and use the tab key in FourthTab, the focus still goes on OK / Cancel.

Are there some restrictions about this option? Or is there something I am missing?

Upvotes: 0

Views: 2990

Answers (1)

musicamante
musicamante

Reputation: 48499

The focus policy is not propagated to the children.

When you set the focus policy on the button box, its children (the buttons) still have their default policy (which is StrongFocus).

If you want to disable that for all buttons, you need to do it explicitly, for instance:

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

Or, for any button:

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

Note that the keyPressEvent is only received by a parent if none of its children has handled it, so if you're trying to capture the Tab you need to install an event filter on the whole QApplication instead, otherwise it's still possible that some widget will capture and accept it, thus preventing you to receive it.

Upvotes: 1

Related Questions