Disabling user interaction with window
-
I want to disable my window so that user cannot trigger some action at my application end by interacting with some widget/action/menu item etc and I also want to throw a message via message box to indicate reason for disabling window. What would be the recommended way to achieve this?
I way planning to use setEnabled to disable window but I am not sure how to generate message to indicate reason for disabling.
Additoinally in setEnabled documentation I saw below lineIn general an enabled widget handles keyboard and mouse events; a disabled widget does not. An exception is made with QAbstractButton.
I am not sure what is the exception for QAbstractButton here
-
Hi,
Can you tell a bit more about how your application works ?
Is it the main widget ?
What determines that the widget is disabled ? -
@SGaist I have a main window created from QMainWindow which has different widgets laid out.
It shows data from a sqlite database using QTableView and also presents some data based on some in memory data.
Whenever that in memory data or sqlite databse changes we need to disable the window because window is now out of sync and ask user to refresh or relaunch window via a command. -
The question is when the user should be notified:
- When the widgets get disabled? In that case you could just bring up a QMessageBox.
- When the user wants to interact with such a widget anyway? In that case it’s not really disabled, because it should react to user interaction, just in a different way, i.e. by bringing up the dialog / message box. That’s more cumbersome to implement. You have to take care of the drawing, and then divert interaction slots to the message box.
But I wonder whether this is necessary at all: since the application knows that the screen is out of sync, why not refresh automatically when it happens?
-
@Axel-Spoerl
Sorry for the delay in response.
As a short term quick solution, I wanted to explore if there is some easy way to just disable the window so that user's interaction doesn't result in any callback which may result in undefined behavior if data has been modified and GUI is no longer in sync.
In future, we may consider it updating automatically, but data changes that happen in the process, they happen over time incrementally so the sync operation I would like to do at some well defined points and not at every modification, I need to figure out these well defined points.
For now, I just wanted to ensure that out of sync GUI doesn't result in some crash or some other undefined behavior
Is there no easy way to disable window such that if user tries to click somewhere they get a message box saying window is disabled and asking them to resync plus no additional callback is triggered that causes me to query the data at backend? -
As a short term quick solution, I wanted to explore if there is some easy way to just disable the window
QWidget::setEnabled(false)
In future, we may consider it updating automatically, but data changes that happen in the process, they happen over time incrementally so the sync operation I would like to do at some well defined points and not at every modification, I need to figure out these well defined points.
I don’t understand this line of argumentation. When you know about every modification, why disabling instead of updating? It doesn’t matter how fast / often modifications occur.
Is there no easy way to disable window such that if user tries to click somewhere they get a message box saying window is disabled and asking them to resync plus no additional callback is triggered that causes me to query the data at backend?
No.
-
I agree with @Axel-Spoerl. Blocking the whole app to wait for a specific point in time while everything is already known sounds error prone and inefficient.
Knowing a bit more about what your application may help us help you devise a better strategy. -
A mask label or widget cover on it would be good,and you can installEventFilter on your mask
-
If you really want to disable the window
setEnabled
is the right choice. However, it seems that you don't want to disable the window.Some widgets allow you to set them to read-only. This might help if the user is not supposed to edit the values while the window is refreshed.
Another thing you might consider is using
blockSignals
. This means that all changes to the widgets don't trigger any signals. Even your own update does not trigger signals (only bad, if you rely on this).You could also try to have a model and the widgets just showing the data from the model. Then you have two copies of the model: one for display and one for update. After an update you just swap pointers between these two models (basically double buffering). There is only a very small point in time where you need to synchronize the update and the display.
-
Thanks for all the inputs. Let me describe my requirement more.
This window is not the only GUI for my application. So its not like everything is blocked until this window is updated. There are other windows also with which user can interact.
Incremental updates that happen in background that require me to update this window, can happen in batches but operations needed to make window in sync are as of now not incremental, they require full redo (we will review how to make this also incremental in future) .
And what if user keeps on triggering operations that requires me to redo analysis for displaying in this window continuously even when user actually isnt using this specific window.
We will review this use model later but for short term I was looking to disable the window and ask user themselves to manually trigger resync when they intend to use it. This disabling of window is needed to avoid any undefined behavior when window is out of sync.
If there is no easy way to disable like that, as a short term solution I will maybe just close the window internally when user triggers something that makes it out of sync