Turn off PyQt event loop when editing a table

I am developing a GUI with PyQt. The GUI has qListWidget, qTableWidget, and a plot implemented with Mayavi. The list refers to figures that are plotted (for example, cylinders and cones). When a figure is selected in the list, I want the form properties to be loaded into the table (from the dictionary variable) and the figure highlighted on the chart. I have a Mayavi job that works perfectly. In addition, if the table is edited, I need a form that needs to be redrawn to reflect the new property value (for example, for a cylinder, if the radius is changed).

So, when a list item is selected โ†’ update the table using the properties of the item (from the dictionary variable), highlight the item in the graph

When the table is edited -> update the dictionary variable and redo the item

Problem: when I select a list item and load data into a table, the qTableWidget ItemChanged signal is triggered every time the cell is updated, which causes the form to be rebuilt repeatedly with incomplete data.

Is there a typical way to disable the GUI event loop when updating a table? (I have experience with Excel VBA, in this context the Application.EnableEvents = False parameter will prevent the WorksheetChange event from being triggered every time the cell is updated.) Should I have a "table update" variable to prevent actions from occurring while updating the table? Is there a way to update a table widget at the same time, rather than an item by position? (I agree that I intentionally avoid the Model-View framework at the moment, hence qListWIdget and qTableWidget).

Any suggestions?

This is my first time poster, but for a long time StackOverflow, so I just want to say thanks in advance for being such an amazing community!

+4
source share
3 answers

blockSignals(bool) designed to suppress QObjects and their subclasses from emitting signals, which prevents the reception of other objects in slots. But this is a QObject method. If you are specifically trying to prevent one object from emitting signals in response to changes you made that could cause calculations or some other expensive processing in the slot, then this is what you want.

But if your situation is that repeated changes cause repeated paint operations (or other expensive events generated by widgets), then you have the option to disable updates using updatesEnabled(bool) . The advantage of this method is that it recursively disables the children of the target widget, preventing them from being updated as well. Therefore, nothing in the hierarchy will receive updates until you turn it on again.

 mainWidget.setUpdatesEnabled(False) # do a bunch of operations that would trigger expensive events # like repaints mainWidget.setUpdatesEnabled(True) 

Ultimately, it depends on whether the source of your problem comes from triggering signals or triggering widget events. Signal blocking still allows the widget to process its events, but simply does not notify other listeners about it. updatesEnabled is a common way to wrap multiple list / table / tree updates. When it is turned back on, one update will be performed for publication.

+10
source

Signals can be temporarily blocked for any object that inherits QObject :

 self.tableWidget.blockSignals(True) # perform updates, etc self.tableWidget.blockSignals(False) 
+5
source

If you disable the entire event loop, the application stops responding. And even if the user does not notice, the OS may issue some kind of โ€œhangingโ€ notification (for example, OS X is a brightly colored rotating beach ball that no one will miss).

You might want to disable renaming without completely disabling the event loop. But even that is probably too drastic.

All you are really trying to do is make sure that the table stops redrawing (without changing the way you implement your table view, which you recognize as not ideal, but you have reasons).

So, just turn off ItemChanged updates. The easiest way to do this in almost every case is to call blockSignals(True) in widgets.

In rare cases when this does not work (or when you are dealing with ancient code that is intended to be used both in Qt4-based projects and in previous projects), you can still get a signal handler, hide them and delete them , then do your job, then restore the previous handler (s).

Instead, you can create a flag that handlers can access, and change them so they donโ€™t do anything if the flag is set. This is the traditional way of doing things, but usually this is not what you want to do in Python.

0
source

All Articles