Reputation: 1201
I have multiple buttons. When I click one of them, I call a function that iterates over rows of a table (say, changes the background colour of the row). During the execution of this function, in the middle of the iteration, I'd like to "pause" and wait for another button to be clicked in order to resume the execution of the function. During this "pause" I'd like all other buttons (that is, the ones I'm not waiting to be clicked) to be disabled or ignored.
I've looked into QTimer and QThread, but I think that I'm unnecessarily over-complicating things. Looking for suggestions...
Upvotes: 1
Views: 3556
Reputation: 3945
First of all you need to call QtGui.qApp.processEvents()
method at the end or beginning of the iteration in order to make the gui responsive during the execution of the loop. Then you need to maintain a list
of rows (say, self.allRows
), in each iteration pop one row from the list
change the background color and append it to a second list
(say, self.doneRows
). Also declare a boolean variable as False
(say, self.pause = False
) inside __init__
and add a check statement at the beginning of the loop, if the self.pause
is True
, break
the loop. Then you need to add a slot to update the value of self.pause
to True.
def pause_execution(self):
self.pause = True
# loop through all the buttons to make them disabled excluding the pause and resume buttons
for btn in self.buttons:
btn.setEnabled(False)
QtGui.qApp.processEvents()
Connect Pause
button's clicked signal to this slot. Now the loop will be broken and self.allRows
contains only the rows with no background color changed yet. Create another slot to resume the loop again. This time the loop will change the background color of only remaining rows.
def resume(self):
self.stop = False
# loop through all the buttons that were disabled, to make them enabled (if you need to)
for btn in self.buttons:
btn.setEnabled(True)
QtGui.qApp.processEvents()
# call the method which contains the background color changing loop.
Upvotes: 3
Reputation: 53175
I think you are looking for this to execute on each method depending on the mouse button click:
myWidget.setDisabled(true)
Then, you could find all the children of the main window or the root widget whatever that is, this way:
widgets = form.findChildren(QtGui.QWidget)
Then, you could connect your push button click to the desired method as follows:
button.clicked.connect(setDisableWidgets)
So, here is a simple example:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
g_disable = true
g_mainWidget = ...
def setDisableWidgets():
''' This will get more exciting when you have other widgets, too, for sure '''
widgets = mainWidget.findChildren(QtGui.QWidget)
for widget in widgets:
# filter out push button though based objectName for instance
widget.setDisabled(disable)
# Toggle for the next run
disable = not disable
app = QApplication(sys.argv)
button = QPushButton("Click me")
button.clicked.connect(setDisableWidgets)
button.show()
app.exec_()
In your QThread run, you could extend the code that runs that function the way that, for instance is checks against the disable variable after processing each row or even small units if you wish and if that is false, it runs QThread.sleep(100) or so, and then wakes up for a check against disable. If it is false, then it continues the execution, otherwise sleeps back.
Here is the pseudo code:
class MyThread (QThread):
def run():
isEnd = false
while not isEnd:
while disable:
self.msleep(200)
# Process next row
# if we are done, isEnd = true
Upvotes: 2