5

Let's say I have an application with a number of QGroupBoxes like so:

import sys


from PyQt4 import QtGui, QtCore


class Main(QtGui.QWidget):
    # pylint: disable=too-many-statements
    def __init__(self, main):
        super(Main, self).__init__()
        self.grid_layout = QtGui.QGridLayout()

        self.line_edit = QtGui.QLineEdit()
        self.grid_layout.addWidget(self.create_settings_group(), 0, 0, 2, 1)

        self.push_button = QtGui.QPushButton("go", self)
        self.grid_layout.addWidget(self.create_controls_group(), 0, 1)

        self.setLayout(self.grid_layout)
        main.setCentralWidget(self)

    def create_settings_group(self):
        group_box_settings = QtGui.QGroupBox(self)
        group_box_settings.setTitle("group1")
        grid = QtGui.QGridLayout()
        grid.addWidget(self.line_edit, 0, 0)
        group_box_settings.setLayout(grid)
        return group_box_settings

    def create_controls_group(self):
        group_box_settings = QtGui.QGroupBox(self)
        group_box_settings.setTitle("group2")
        grid = QtGui.QGridLayout()
        grid.addWidget(self.push_button, 0, 0, 1, 2)
        group_box_settings.setLayout(grid)
        return group_box_settings


class GUI(QtGui.QMainWindow):

    def __init__(self):
        super(GUI, self).__init__()
        self.ui = Main(self)
        self.show()


app = QtGui.QApplication(sys.argv)
ex = GUI()
app.exec_()

When I open my simple application I see that the cursor is blinking in the line edit. But I just want the push button in another group box to be highlighted and to have enter press connected to it? how do I do that? using self.push_button.setFocus() doesn't do anything.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Bob Sacamano
  • 699
  • 15
  • 39

2 Answers2

7

You can try setting the button Default property:

self.push_button.setDefault(True)
self.push_button.setFocus()
Degang Guo
  • 475
  • 8
  • 18
5

You have to set the focus a moment after showing up for it you can use a QTimer::singleShot() or QMetaObject::invokeMethod():

1. QTimer::singleShot()

...
self.push_button = QtGui.QPushButton("go", self)
self.grid_layout.addWidget(self.create_controls_group(), 0, 1)

self.push_button.setDefault(True)
QtCore.QTimer.singleShot(0, self.push_button.setFocus)

2. QMetaObject::invokeMethod()

...
self.push_button = QtGui.QPushButton("go", self)
self.grid_layout.addWidget(self.create_controls_group(), 0, 1)

self.push_button.setDefault(True)
QtCore.QMetaObject.invokeMethod(self.push_button, 
    "setFocus",
    QtCore.Qt.QueuedConnection)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks, the first option worked. I didn't try the second one. Can you please expand on it? – Bob Sacamano Oct 18 '18 at 07:41
  • 1
    @BobSacamano The problem is that the focus is set correctly in a widget if it is visible, what is the point of establishing the focus when the widget is hidden? none, so Qt cleverly ignores it. The QTimer.singleShot() is executed after the synchronous task ends and the event loop works, so it is set to 0, that is, it will have priority over other asynchronous tasks. the same happens with invokeMethod. – eyllanesc Oct 18 '18 at 07:45