0

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?

1
  • For future reference, please try to keep your examples as minimal as possible (read how to create a minimal reproducible example if you didn't yet). Almost 80% of your code (all the tab classes) is completely unnecessary and distracting. Commented Sep 9, 2021 at 17:24

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I tried with both solutions and it worked fine. It even helped me to fix other similar issues with other widgets. Thank you for the precisions.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.