QSpinBox and double slot invocation
-
Hi,
I have a weird behavior on a QSpinBox.
It is connected to a slot with the following sequence located in a constructor. It is called one time only.connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateStatistics);
Sometimes, depending on the item, as I click on the upper arrow of the spinbox, the sequence from the beginning is 1 - 2 - 3 - 4 - 6 - 7 - 8 - 10 - 11 - 12 - 14 - 15 - 16 - 18 - 20 - 2 ... (item has 20 elements).
As you can see, for example, I'm unable to gain access to the fifth element.
While debugging, I state that the slot is called twice.
There is no other connect to this slot.I made another test with another item. This item has 9 elements. It runs perfectly from 1 - 2 ... to 9.
Would you have any idea ?
Thank you folks !
-
Hi,
Fastest thing you can try is to switch toQt::UniqueConnection
and if the problem persists you can be sure it's not double connect. Aside from that, I'd break in the slot and see how many times it's called between each value change of the spin box. -
I have found something.
In fact the same signal triggers 4 slots:connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateStatistics); connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateDescription); connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateCommand); connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateOutput);
When I deactivate the 3rd connect about updateommand, it perfectly runs.
-
Here is updateCommand:
void ADiSScoreGen::updateCommand(int number) { --number; // display command file content if (m_commandEdit[number].size() != 0) { m_commandPlainTextEdit->setPlainText(m_commandEdit[number]); m_tools->toHtml(m_commandPlainTextEdit, 0, 17 + msg_descriptionItem.length(), 0, 133, 255, 25, false, false); }
Here is toHtml:
void Tools::toHtml(QPlainTextEdit* edit, int location, int charcount, int red, int green, int blue, int fontsize, bool bold, bool underlined) { QTextCursor cursor(edit->document()); QString highlight; QString sfont_beg = "<FONT "; QString sfont_end = "</FONT>"; QString scolor = "color=#" + toHexString(red) + toHexString(green) + toHexString(blue) + " "; QString sbold = "span style=font-weight:bold "; QString sunderlined = "span style=text-decoration:underline "; QString ssize = "size=" + QString::number(fontsize) + ">"; QString sHtml; cursor.setPosition(location, QTextCursor::MoveAnchor); cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, charcount); highlight = cursor.selectedText(); sHtml = sfont_beg + scolor.toUpper(); if (bold) sHtml = sHtml.append(sbold); if (underlined) sHtml = sHtml.append(sunderlined); sHtml = sHtml + ssize + highlight + sfont_end; cursor.insertHtml(sHtml); // if I remove from here everything OK cursor.setPosition(charcount, QTextCursor::MoveAnchor); cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, edit->document()->characterCount() - 26); highlight = cursor.selectedText(); sHtml = "<FONT face=\"Arial\" font-weight=\"normal\" COLOR=#000000 size=\"3\">" + highlight + "</FONT>"; cursor.insertHtml(sHtml); }
If I remove from the comment // if ... everything runs perfectly.
I can't see the link between toHtml and the connect -
If I replace
edit->document()->characterCount() - 26
with 4000. It's OK
It could be an issue about size.The biggest files sent to the QPlainTextEdit are about 20KB.
-
Any idea ?
-
I found a way to fix the issue.
In fact I have a signal connected to 4 slots.
Each slot updates 4 independent widgets.
The solution is to add Qt::UniqueConnection to each connect.And it gives this:
connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateStatistics, Qt::UniqueConnection);
connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateDescription, Qt::UniqueConnection);
connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateCommand, Qt::UniqueConnection);
connect(ui.spinBox_Statistics_ItemSelection, static_cast<void(QSpinBox::)(int)>(&QSpinBox::valueChanged), this, &ADiSScoreGen::updateOutput, Qt::UniqueConnection);My explanation: when the file managed in updateCommand is big, the time needed to display it into the widget is longer ant the slot is interrupted by another slot. Adding Qt::UniqueConnection insure that one slot is executed at a time.
Are you OK with that explanation ? -
I'm pretty sure you've called
QObject::connect
multiple times somewhere. There's no way Qt can break the execution of one slot to allow another to be called, so my advice is to trace where you've duplicated the connection. -
@m.sue said in QSpinBox and double slot invocation:
I use MSVC 2015 on Windows 10 and also get this behaviour in all my spinboxes: clicking the arrow sends two events in debug mode.
I don't use that compiler. But if you could prepare MWE you should post it with a bugreport (assuming it isn't already reported).