Constant jumps from release to debug made me pay attention to the fact that when closing the release version of the application (opened directly in Qt Creator, before WinDeployeeQt), this is displayed in the console:
qt.core.qobject.connect: QObject::connect: No such signal QObject::aboutToClose()
although I do not use this signal and did not redefine it. I have only redefined this:
void MainWindow::closeEvent(QCloseEvent *event) {
ClearNotes();
ClearClientOutputContacts();
ClearClientRedactContacts();
ClearContactOutputCompanies();
ClearDocuments();
ClearNewClientContacts();
event->accept();
}
in which I clear all dynamic fields, if any. The question is, close your eyes to this or try to understand where this message comes from? (This is not present in debug mode, only observed in release mode).
Related
I have asked the question QWidget::repaint: Recursive repaint detected on Windows in Debug without creation of new threads. It turned out that the crash (on Windows in DEBUG mode) is due the fact that auto-generated ui file contained:
<widget class="QToolButton" name="button_logout">
</widget>
which would generate the code
QToolButton *button_logout;
button_logout = new QToolButton(widget_session_list);
button_logout->setObjectName(QString::fromUtf8("button_logout"));
header_layout->addWidget(button_logout);
So having a clicked event due to this connection:
...
connect(_ui->button_logout, &QToolButton::clicked, this, &ViewImpl::performLogout);
...
void ViewImpl::performLogout()
{
emit onLogout();
}
led to the crash with QWidget::repaint: Recursive repaint detected after the window would be hidden and deleted as a reaction on the signal onLogout().
However, I discovered that if I replace the QToolButton with QPushButton I do not get the crash and everything is fixed.
So my question is why? What is wrong with the QToolButton? And why is the problem on Windows in Debug mode and I do not have it on Linux or on Window in Release mode. Honestly, I have already encountered strange crashes on Windows in Debug mode for Qt. E.g., I remember once that QVariantList failed there, so I got rid of it. I must note here that I build against debug qt libraries and tried \MT, \MDd, and \MTd runtime libraries.
Probably your shutdown / logout logic is flawed: I guess, that you delete the object from which you are running your logout code. Try to replace the call to delete() with
deleteLater() and see what happens. For further diagnosis, we'd need more information about your object tree, construction and destruction.
It has absolutely nothing to do with the kind of button you are using, that is absolutely accidental.
According to the release notes for 3.1.3 (https://raw.githubusercontent.com/wxWidgets/wxWidgets/v3.1.3/docs/changes.txt) dark mode support has been added to wxWidgets for Mojave+.
For the documentation for wxSysColourChanged, it still states that this is for Windows only but I thought the dark mode support for macOS should include this too? Dark mode is only a recent addition to Windows UWP apps and not Win32 (see dark mode on Windows 10 for a discussion of that on the forum).
In any case I cannot get the event to fire, although switching to dark mode does indeed correctly update the GUI elements eg. wxlistctrl and wxbutton without me having to manually enforce colour changes.
I am trying to capture the system colour change event so that I can manually redraw my own "owner-drawn" custom GUI elements correctly dark/light.
I hook up the Bind in the constructor to my event but nothing works:
Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);
void myFrame::OnSystemColourChanged(wxSysColourChangedEvent &event)
{
wxSystemAppearance s = wxSystemSettings::GetAppearance();
wxString dark = s.IsDark() ? "it's dark" : "it's light";
wxString m("System colour changed - ");
m += dark;
::wxMessageBox(m);
event.Skip();
}
I have got this open as a query on the forum (here) and they recommended the mailing list but I notice that wxWidgets questions are quickly addressed on here, particularly by VZ so here's hoping!
Am I missing some method of detecting colour changes?
OK, I managed to get the code to hit. I debugged it by adding a wxApp-level HandleEvent override function to see what events were being handled by the application (yes all events go through here):
void myApp::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const
{
wxApp::HandleEvent(handler, func, event);
}
wxSysColourChanged events are indeed passing through this.
I managed to get my main frame's handler to hit by hooking up differently. Instead of
Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);
I used this instead:
Bind(wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler(myFrame::OnSystemColourChanged), this);
I have no idea why &myFrame::OnSystemColourChanged wouldn't be recognised.
Also, I could not get any message boxes to show up in my event handler. ::wxMessageBox and wxMessageDialog did not show. cout output did show up but no popup GUI dialogs.
I am not going to be showing message boxes in this handler anyway so it isn't a problem but was trying to show a message for debugging/testing purposes.
I understand that a Qt signal is put onto the event queue, and then the connected slots are called later when the event loop sees it. So it doesn't make sense to "step into" it when debugging. But I really do want to see, in a large enough app that I can't keep all of it in mind at once, where the control flow ends up.
So is there a way to find the slot(s) that are connected to a signal, either potentially based on connect(...); calls or actually at the moment when debugging?
In Qt Creator 3.5.1 (Based on Qt 5.5.1 (GCC 5.2.1 20151129, 64 bit)):
Ctrl+Shift+U (find usages) only returns emit signal(); in the source and void signal(); in the header.
It'd be really nice if it would also return connect(..., SIGNAL(signal()), ..., SLOT(slot())); so I could then F2 (go to definition) on slot() and put a breakpoint in it.
A plaintext search returns a bunch of unrelated signals with the same name in other classes, so that's not really helpful either.
You can use New Signal Slot Syntax :
connect(sender, &Sender::valueChanged,receiver, &Receiver::updateValue);
With this connection you can find usage and Qt will find connection line.
I've connected the editingFinished signal of a QLineEdit to a slot in my application showing a QMessageBox if the input is in some way unexpected. Strangely enough the message box is shown twice, so I put a breakpoint where it is executed and had a look at the stack trace. There QMessageBox.exec() calls QApplication::processEvents() which seems to somehow forward and process the same event again.
My stack trace the first time looks sth like this:
MyApp::mySlot()
QLineEdit::editingFinished()
QGuiApplicationPrivate::processMouseEvent()
QEventLoop::processEvents()
QApplication::exec()
and the 2nd time like this:
MyApp::mySlot()
QLineEdit::editingFinished()
QGuiApplicationPrivate::processWindowSystemEvent()
QEventLoop::processEvents()
QDialog::exec()
// stack trace of run #1 here
// [...]
I've already checked for double signal connections or different events being connected to this slot but this doesn't seem to be the problem. Can someone explain what happens here and how to prevent it?
It is a Qt bug that editingFinished is emitted twice, you can read about it here:
https://forum.qt.io/topic/39141/qlineedit-editingfinished-signal-is-emitted-twice
There is also a workaround for it described.
if(lineEdit->text().toDouble()<1000) {
lineEdit->blockSignals(true);
QMessageBox::information(this, "Information", "Incorrect value");
lineEdit->blockSignals(false);
}
I'm building some code where I'm running a while loop and, within the loop, am trying to change the contents of a couple of textboxes with QLineEdit's setText(). However, merely calling setText within the loop does not work; the textboxes only change their actual value once the code has run through, instead of at each iteration.
I have little experience with C++ or Qt, but the project I'm working on must use them. Any help?
EDIT: I'm guessing this must be something simple that I simply am having troubles because of my lack of familiarity/knowledge, but if more information is needed I'll gladly provide it!
The problem is that QT needs control to return to the UI thread's event loop in order to update the QLineEdit's visual appearance. The quick and dirty way to run the event loop is to add QCoreApplication::processEvents() after each call to setText(). The proper way to fix it is to move the blocking process that sets the value of the text box into another thread, expose an updateText(QString text) signal, connect it to the TextBox's setText(const QString & text) slot and emit that signal whenever you want the text to be updated.
Please see my answer to a similar question for more detail: unexplained delay after QProgressBar finish loading
You might also want to check out some of the documentation on QThreads and the Qt signal slot system: http://harmattan-dev.nokia.com/docs/library/html/qt4/threads-qobject.html
In my case, calling only repaint() or processEvents() won't do the job.
Within your function loop, call both QCoreApplication::processEvents(); and repaint();:
for (i;...)
{
//do your calculations
//...
QCoreApplication::processEvents();
repaint();
}
Calling ui->mywidget->update() didn't make any different as well.
(Tested for Qt4.8.3 on Kubuntu 12.10 and Qt5.0.1 on Windows XP)