I'm using a QListWidget to control and display some state.
Now to control the state, user-selection in the widget is used.
to respond to that, I've connected the selectionChanged signal.
However the state can change by itsself and when that happens, I have a complete new state and want the selection to change.
To achieve that I'm iterating over the state and the items like this:
for item, s in zip(items, state):
item.setSelected(s)
However this triggers selectionChanged (even in every single iteration)
I don't want that to happen at all.
is there another way to respond to the selection-change?
You can simply use the QSignalBlocker class. Before calling a function which emits a signal, instantiate a QSignalBlocker object.
// ui->ListWidget is available.
{
QSignalBlocker blocker( ui->ListWidget );
for ( auto item : items )
{
item->setSelected();
}
}
Related
I need to block specific buttons on an MMI.
I implemented a button blocking function in a subclass of QPushButton.
For this, I used the clicked() signal and blocked the button with blockSignals(true).
This means that with each button clicked on my MMI, 2 SLOTS are always called.
But when calling the blocking of a specific button, I get the first SLOT (clicked()) of my subclass, in which I block the button, then I then arrive in the original SLOT linked to this button, which is still called despite the blocking (the first time only).
How can I in my QPushButton subclass know the subsequent SLOTs linked to this button and avoid them (delete them)?
void QbtnStandardButton::slotButtonClicked(void)
{
if (modeProtection)
{
// Special mode to protect/unprotect the button
if (isProtected())
{
// Reset the protection
this->blockSignals(false);
}
else
{
// Set the protection: button will be unclickable
this->blockSignals(true);
}
modeProtection = false;
}
if (isProtected())
{
QMessageBox *pMsgBox = new QMessageBox(QMessageBox::Information,
"Protection",
"This button is protected!",
QMessageBox::Ok);
pMsgBox->exec();
pMsgBox->deleteLater();
// Here: remove subsequent SLOT of this button ?
}
}
I think it's very difficult if not impossible to find SLOTS linked to a button.
I worked around the problem by using an eventFilter() instead of a SIGNAL() in my base class.
In this case, I can filter the "clicked()" event before it is reissued.
A am using QComboBox derived class to show my items. My combo box is read only. But how can I catch the event when popup view of combo box closes?.For example, when user clicks a mouse button somewhere out of my combo box?
Thank you very much in advance.
What for do you want this event? If the QComboBox closes without selection nothing changed. The signals given will only be activated when a selection has been made.
If you insist on reading a "close-event", you could subclass focusOutEvent(QFocusEvent*) or use an event handler for the focus out event and emit a custom signal. Eventually you want to have a boolean flag set on hadEditFocus() before, so you can see if the dropdown would be opened.
Edit:
Eventually it would be easier to subclass and reimplement showPopup() and hidePopup() as:
void MyClass::showPopup()
{
QComboBox::showPopup();
emit signalPopupShown();
}
void MyClass::hidePopup()
{
QComboBox::hidePopup();
emit signalPopupHidden();
}
but I am not sure if hidePopup() gets called on focus-loose.
In a current Flex project, i have an issue where a certain child component must be initialized and ready when the user clicks a button. the button is a mouseClick Event.
//mouseClick Event
protected function tableSearch_searchClickHandler(event:MouseEvent):void
{
parentXml = event.xmlNode;
if(classifierInfo)
classifierInfo.variables = parentXml;
else //initialize it dynamically..but how?
{};
}
in the function the component (classifierInfo) is checked to see if it is initialized and ready== that is, it is not null. then the variables property is populated with the parentXml value else, if it is not ready, [i want to initialize it dynamically] but do not know how.
does any one know how i could fill up the else statement such that the classifierInfo component is initialized dynamically? Is this even possible?
you have to try to initialize the object and add it to the correct parent UI Object if it is a visual component.
classifierInfo = new WhateverClass();
classifierInfo.somePropertySet
...
yourUIComponent.addElement(classifierInfo);
Is it that what you are trying to do?
I am creating an app in qt, and i have come to a problem.
I have a qgraphics scene.
I create the scene and I have put some actions to take place when the user clicks
on a scene item.
I can detect the selectionChanged() signals, but:
The signal is emitted twice (once for the clicked item and once for the previously selected item (deselection), so the required actions take place twice for both items).
When an item is clicked, it remains selected and i can't click it again...
(i tried setting item->setSelected(false) but it gets in an infinite loop of selection/deselection...).
Anyone has any idea how to fix that?
What I am trying to achieve, is to have no action performed on deselection,
and to be able to re-click a clicked item and re-perform the action.
Define a slot yourSlot() and connect it to the signal selectionChanged(). In this slot you check if the item responsible for the signal emission is selected or not.
void yourSlot() {
QGraphicsItem *item = qobject_cast<QGraphicsItem *>(sender());
if (item) {
if ( item->isSelected() ) { //this item is selected
doSomethin();
//*deselect* the item so that it can be selected again
item->setSelected(false);
}
else { //the signal was fired because the item was deselected
//ignore()
}
}
}
I can't try it right now because I don't have Qt installed in this computer by I think it should work.
In Qt, either implementing keyPressEvent or creating a QAction and assigning it a key combination allow me to act based on the keyboard.
Which of these methods is generally preferred?
You should use QAction whenever the same event that is triggered by the key sequence you want may be triggered through other ways like from a menu, toolbar or other buttons. This way you can use the same action on several widgets that should do the same trick.
Excerpt from QAction doc:
The QAction class provides an abstract
user interface action that can be
inserted into widgets.
In applications many common commands
can be invoked via menus, toolbar buttons, and
keyboard shortcuts. Since the user
expects each command to be performed
in the same way, regardless of the
user interface used, it is useful to
represent each command as an action.
I'd prefer to overwrite the keyPressEvent. I don't like the idea of a QAction "lying around somewhere". Just overwrite the keyPressedEvent. I usually do it with a switch-case in which I check the pressed key. Just don't forget to call the keyPressEvent of the base class if you don't want to disable the standard behaviour of a key. Additionally you can check if a "modifier" is pressed while a keyPressEvent occurs. (e.g. Shift or Ctrl). IMHO for general purposes overwriting the keyPressEvent is better than creating invisible, secret actions, unless you want your application to contain all those actions visible for the user.
void my_widget::keyPressEvent( QKeyEvent* p_event )
{
bool ctrl_pressed = false;
if( p_event->modifiers() == Qt::ControlModifier )
{
ctrl_pressed = true;
}
switch( p_event->key() )
{
case Qt::Key_F:
focus_view();
break;
case Qt::Key_I:
if( ctrl_pressed )
{
toggle_interface();
}
else
{
QWidget::keyPressEvent( p_event );
}
break;
case Qt::Key_Return: // return key
case Qt::Key_Enter: // numpad enter key
update_something();
break;
default:
QSpinBox::keyPressEvent( p_event );
}
}
Would depend on what you need it for.
Is it for a menu like action that may be triggered by a menu, button, toolbar too, then go for the QAction. Especially if this action should work all over your program, not only in a single widget.
Is it more like a local activity in a single widget (say for example controlling movement in a game), I would use the keypress event.