Qt show() function after hide(), worked when the window inactive but not active - qt

I have made a simple qt program that grabs a picture and display it using QPainter/QPaintEvent widget. I make it on QPainter so that I can put a X mark on the picture from a user input. I have made the program window to hide and show based on an external button input. It works well if I set the running program window inactive. But if I set the window to active and triggered the show/hide function, it crashes with error:
Fatal IO error: client killed
Also, when I tried to use show() function after hide(), it gives 2-3 of a same error (applies when the window either active and inactive):
QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread
Is this a bug in qt? Any suggestion on workaround this problem?

Related

Qt is activating window without my consent after using QFileDialog

Qt 5.12.6 MSVC2017 64-bit on Windows 10, Qt Creator 4.10.1.
I have a top level window derived from QMainWindow, which has a QMdiArea.
From the first main window I use a file open dialog to open a new document in a QMdiSubWindow and place it in the QMdiArea. After the file dialog returns but before I do the logic of opening the document, I have to call QApplication::setActiveWindow(this), to set it back to the main window, because the opening logic depends on the active window. The need for this somewhat appears related to https://www.qtcentre.org/threads/2950-ActiveWindow-changes-after-closing-QFileDialog in that the activeWindow becomes null, regardless of how I parent the file dialog.
I then open a second identical top level window and open another document using the same method.
What's very weird is that after the second QMdiSubWindow in the second QMainWindow is activated, the first QMainWindow gets activated again, and thus various follow-on operations affect the document in the first window rather than the second window which is the intended one. If I click back and forth on the main windows, the activation is correct.
If I create a new document directly from the second QMainWindow instead of using the file open dialog, then it works fine. The new QMdiSubWindow is created and shown in the second QMainWindow, without the first one getting activated. So this implicates the file dialog somehow.
When I put a breakpoint on a function triggered by the QMainWindow::activated signal, the stack trace shows this signal is coming from within Qt on its own accord, not from someplace in my code directly.
How can I find out why Qt is activating the first window when using the file dialog from the second window? At this point the code is too large to try to fit a minimal example here on SO.
--EDIT--
I added a one-shot QTimer at the end of the function that creates the QMdiSubWindow. Zero milliseconds after in creates the QMdiSubWindow it activates the first QMainWindow, then activates the current QMainWindow. That workaround seems to work, and the second QMainWindow becomes the active one. But only if I select away from it first. The fact that the hack works with 0 ms timer is also interesting. I'll be posting minimal example when I can.
thanks

Showing a QMessageBox breaks QLineEdit highlighting

I have a C++ Qt 4 application written for Raspberry Pi. I'm experiencing an odd side-effect of showing a QMessageBox and I don't know enough about Qt to debug it.
The pi has a touchscreen, so I launch the application with unclutter to hide the mouse cursor. (Though this doesn't affect my issue... I have tried without unclutter just in case.)
I have sub-classed QLineEdit to override focusInEvent() and focusOutEvent() to select-all when a LineEdit gets focus, and deselect-all when it loses focus.
Before showing any QMessageBoxes, everything works perfectly - tapping on a QLineEdit selects all the text; tapping the next one de-selects the previous QLineEdit, and selects the new QLineEdit.
After showing a QMessageBox, my overridden events stop working, and QLineEdits no longer auto-select and de-select.
If I add:
msgBox.setWindowFlags(msgBox.windowFlags() | Qt::Popup);
before I exec() the QMessageBox, then text highlighting continues working normally, but the cursor is displayed and flickers while the QMessageBox is on the screen.
It seems like there is a side-effect of showing the QMessageBox that affects the calling window and my sub-classed QLineEdit boxes... but not if the QMessageBox has the Popup flag set!
I've tried storing and manually re-loading the flags on the main window, and that does nothing, so it doesn't appear to be flags on the main window.
One more oddity: everything works fine if I run the application remotely over XMing and SSH... it's only when it's run locally on the Pi in plain-old X11 that it freaks out.
Any thoughts on how to debug this? Thank you!
I was able to work around this by doing two things.
First, I updated the flags of the QMessageBox before opening it:
msgBox.setWindowFlags(Qt::Popup);
msgBox.exec();
and second, I hid the cursor in Qt code, rather than relying on Unclutter; this fixed the flickering cursor issue:
QApplication::setOverrideCursor(Qt::BlankCursor);

QtQuick lower() and raise() does not work while close() works properly

I have 5 windows which i push and pop via a stackview. In the emulator the new window called by push gets on top as it should. However on my android it spawns behind the starting window. I tried using lower() to set the starting window behind the new window with no success
//start page
Button{myStack.push(page_2); lower()}
I also tried rasing the new window on completion with no success
//new page
Component.OnCompleted:raise()
However close() works properly closing the start page and thus making the new page visible.
//start page
Button{myStack.push(page_2); close()}
Qt doc goes as follows for lower()
lower()
Lowers the window in the windowing system.
Requests that the window be lowered to appear below other windows.
and for raise()
raise()
Raises the window in the windowing system.
Requests that the window be raised to appear above other windows.
Is my code correct? why does close() work and the others dont't
First of all, I don't think that Qt supports multi window on Android. One single window only.
Second - what you posted is not even valid QML code.
Third - in that case you use the the stack view within a single window, and push different GUI elements onto it. Refer to the documentation.

Eventloop is not updating the GUI widget opacity value

I have a button widget I'd like to fade out (self.button1)
def button_slot(self):
fade_effect = QtGui.QGraphicsOpacityEffect()
self.button1.setGraphicsEffect(fade_effect)
hideAnimation = QtCore.QPropertyAnimation(fade_effect, "opacity")
hideAnimation.setDuration(5000)
hideAnimation.setStartValue(1.0)
hideAnimation.setEndValue(0.0)
hideAnimation.start(QtCore.QPropertyAnimation.DeleteWhenStopped)
self.hideAnimation = hideAnimation
The code is in PyQt, but is the same as the original Qt.
For a reason, the when I try the code separately in a test file, it works well.
However, when trying to integrate it in my code, it seems like the fading out animation is running in the background, but not updated in the GUI itself:
The button is stuck at the "clicked" state.
If I minimize and enlarge the window, The button's opacity is right where it's supposed to be (for example, if the duration is 5000ms from 1.0 to 0.0, enlarging the window after 2500ms will show 0.5 opacity).
The button is clickable even though it looks "stuck".
Why could this be happening? How can I force the GUI to update itself at every event iteration?
The only possible explanation I have is that you're blocking the event loop somewhere else in your code. The animation will definitely run, as your test case shows, but it's invoked from the event loop. If your code blocks -- if there's any place in your code where you wait for things, sleep, etc., then that's your problem.
GUI code in Qt and many other frameworks must be written in run-to-completion fashion. Every slot and event handler must execute as quickly as it can, and then return. When you add a breakpoint in a slot, and look at the stack trace when the code stops, you'll see that QEventLoop::exec() is somewhere there. Ultimately, all GUI code is called from the event loop.
Try reducing your code piecewise until the problem vanishes. That's how you'll know where the blocking part is. Qt provides, unfortunately, many methods named waitxxx(), and they tend to be used without understanding that they block the event loop. A blocked event loop means that the application does not respond to user interaction, and eventually the OS will detect it and issue a spinning beachball (OS X), a spinning circle (Vista/Win7) or perhaps a message about a stuck application. A spinning beachball/circle means that the application's main event loop is blocked.

QMessageBox blocks QDialog

I don't really know how to formulate my question this time...
I have my application with a QDialog as a main window.
The application is getting different values like temperature, humidity and so on from a remote machine.
For development I added a group box with different widgets to simulate these values. I have different limits for throwing warnings and alarms to the user.
For example if temperature rises over 30°C then I open a QMessageBox with the request time (the application does polling at the remote machine) and the current temperature. So this is updated each request cycle.
I use the show() method to bring up the message box which keeps my application running in background. The problem now is: the focus is at the message box and nothing in my main window/ QDialog can be clicked until the message box is not accepted/ has finished.
And that's my problem: in simulation mode I want to play around with different temperature values which I can adjust by slider in the main window. How can I access these widgets/ make the message box somehow "not-blocking"?
Best regards,
Matthias
What you're experiencing is called "modality" of a window. By default, a QMessageBox is "application modal". This means that input to all other application windows is blocked.
To change the modality, use setWindowModality() with a value from Qt::WindowModality just before you call show(). In your case:
box->setWindowModality(Qt::NonModal);
box->show();
Indeed you have a modal message box which is the way QMessageBox is intended to work - ie the user is to be alerted and the ui is protected from further interaction until the user has registered the message, closed the message box and (if necessary) taken any action required in response to the message.
Now if you set the message box modality to Qt::NonModal, (remember to assign it to a variable that won't go out of scope when your application continues after popping up the messagebox) you'll be able to interact with the ui even while the message box is displayed., which I have to say is 'unusual'. If I understand your requirement you will already have the message box up - then while this is still up, you'll then want to play around with different temp values in the main window - to what effect? Until another message dialog box is produced? The message box is going to have to be discarded at some point.
Not only that, but if you show a non modal message box and then interact with the main window, you're quite likely to just have the message box disappear behind the main window, out of sight anyway.
I'd suggest that message boxes are generally treated as intended - transient, temporary modal alert boxes only and that perhaps you require a clearly visible live report/status area in your main window rather than utilizing a non-modal QMessageBox.
Hope this helps
Regards
Roger

Resources