ToSimplicity
ToSimplicity

Reputation: 303

How to run code just after signals and events in QT QWidget initiation are processed?

import sys
from PyQt5.Qt import *

app = QApplication([])


class MyDialog(QDialog):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout(self)
        self.list_widget = QListWidget()
        layout.addWidget(self.list_widget)
        self.list_widget.currentRowChanged.connect(self.on_cur_row_changed)
        self.list_widget.addItems(['apple', 'orange'])

        # code block A # start #
        self.clear_qt_currentRow()
        # code block A # end   #

        print('End of MyDialog.__init__')

    def on_cur_row_changed(self, row):
        print('Current row changed to: ', row)

    def clear_qt_currentRow(self):
        print('Clear Qt currentRow')
        self.list_widget.selectionModel().clear()


dialog = MyDialog()
dialog.show()
sys.exit(app.exec())

As in code above, I don't like QT to set the currentRow property of list widget to 0(the first row).I'd like to run code inside clear_qt_currentRow(), after after signals and events in QT QWidget initiation are processed(In this case, setting the currentRow property to None) But self.clear_qt_currentRow() in code block A run too early(before QT changing the currentRow). The result showed as:

Clear Qt currentRow
End of MyDialog.__init__
Current row changed to:  0

Then, I tried below two alternatives for code block A but still didn't get self.clear_qt_currentRow() to run late enough.

# alternative 1
app.processEvents()
self.clear_qt_currentRow()

# result:
# Clear Qt currentRow
# End of MyDialog.__init__
# Current row changed to:  0
# alternative 2
QTimer.singleShot(0, self.clear_qt_currentRow)

# result:
# End of MyDialog.__init__
# Clear Qt currentRow
# Current row changed to:  0

I know that QTimer.singleShot(10000, self.clear_qt_currentRow) can make it. But it can't be a "real" solution because users may have computers with different specs.

Any suggestion for me?

Edit: add what I want to do in BOLD text.

Edit: with help from @zariiii9003, I change to below code, which does the job inside the class.

import sys
from PyQt5.Qt import *

app = QApplication([])


class MyDialog(QDialog):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout(self)
        self.list_widget = QListWidget()
        layout.addWidget(self.list_widget)
        self.list_widget.currentRowChanged.connect(self.on_cur_row_changed)
        self.list_widget.addItems(['apple', 'orange'])
        # code block A # start #
        QTimer.singleShot(0, self.clear_qt_currentRow)
        # code block A # end   #
        print('End of MyDialog.__init__')

    def on_cur_row_changed(self, row):
        print('Current row changed to: ', row)

    def clear_qt_currentRow(self):
        print('Process events')
        # add here
        app.processEvents()
        print('Clear Qt currentRow')
        self.list_widget.selectionModel().clear()


dialog = MyDialog()
dialog.show()
sys.exit(app.exec())

Upvotes: 0

Views: 205

Answers (1)

zariiii9003
zariiii9003

Reputation: 356

You could take a look at Spyder, an IDE that is implemented with Qt:

If you look here:

    # Main window
    main = MainWindow(options)

    main.show()
    main.post_visible_setup()

they first initialize the MainWindow, then they call show() and then they perform a post_visible_setup().

For your case, this:

dialog = MyDialog()
dialog.show()
app.processEvents()
dialog.clear_qt_currentRow()
sys.exit(app.exec())

results in

End of MyDialog.__init__
Current row changed to:  0
Clear Qt currentRow
Current row changed to:  -1

Upvotes: 1

Related Questions