Search code examples
pyqt5focusqspinboxqwizardqwizardpage

QSpinbox in QWizardPage gets initial focus even if its focus-policy is set to NoFocus


I create a QSpinBox in a QWizardPage. It get focus at the start of the wizardpage even when I set the focusPolicy to Qt.Nofocus.

What I set in Qt creator is:

enter image description here

But When the wizardpage start, I got:

enter image description here

Then, if I press Tab for several times, the focus will move between Finish and Cancel as expected.

I am using PyQt 5.15.6 on Windows 10. My python codes consists of a WizardPage.py file generated by pyuic5 and a test_wizard.py file.

WizardPage.py file :

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'wizardpage.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_WizardPage(object):
    def setupUi(self, WizardPage):
        WizardPage.setObjectName("WizardPage")
        WizardPage.resize(400, 300)
        self.spinBox = QtWidgets.QSpinBox(WizardPage)
        self.spinBox.setGeometry(QtCore.QRect(40, 50, 42, 22))
        self.spinBox.setFocusPolicy(QtCore.Qt.NoFocus)
        self.spinBox.setObjectName("spinBox")

        self.retranslateUi(WizardPage)
        QtCore.QMetaObject.connectSlotsByName(WizardPage)

    def retranslateUi(self, WizardPage):
        _translate = QtCore.QCoreApplication.translate
        WizardPage.setWindowTitle(_translate("WizardPage", "WizardPage"))

test_wizard.py file:

from PyQt5 import QtCore, QtGui, QtWidgets
from WizardPage import *
from PyQt5.Qt import *
from PyQt5.QtCore import *
import sys


class test_wizard_page(QtWidgets.QWizardPage, Ui_WizardPage):
    def __init__(self, parent):
        super().__init__(parent)
        self.setupUi(self)


class MyWizard(QtWidgets.QWizard):
    def __init__(self):
        super().__init__()

        self.test_wizard_page = test_wizard_page(self)
        # self.test_wizard_page.setE
        self.addPage(self.test_wizard_page)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    wizard = MyWizard()
    wizard.show()
    sys.exit(app.exec_())

And .ui file I create using the Qt Creator:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>WizardPage</class>
 <widget class="QWizardPage" name="WizardPage">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>WizardPage</string>
  </property>
  <widget class="QSpinBox" name="spinBox">
   <property name="geometry">
    <rect>
     <x>40</x>
     <y>50</y>
     <width>42</width>
     <height>22</height>
    </rect>
   </property>
   <property name="focusPolicy">
    <enum>Qt::NoFocus</enum>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

This question may be related to my question. I also tried to reproduce their problem but fails with PyQt I currently uses. Is my question also a bug of Qt? And how can deal with this?


Solution

  • I can reproduce the behaviour, and it is still present in PyQt6. A work-around is to set the focus-policy on the line-edit of the spin-box (it isn't necessary to set it on spin-box as well). If you also want to restore the normal focus behaviour, it can be done using a single-shot timer:

    class test_wizard_page(QtWidgets.QWizardPage, Ui_WizardPage):
        def __init__(self, parent):
            super().__init__(parent)
            self.setupUi(self)
            for spinbox in self.findChildren(QtWidgets.QSpinBox):
                edit = spinbox.lineEdit()
                policy = edit.focusPolicy()
                edit.setFocusPolicy(QtCore.Qt.NoFocus)
                QtCore.QTimer.singleShot(
                    0, lambda edit=edit, policy=policy:
                        edit.setFocusPolicy(policy))