Problem with event handling on QToolButton in Linux - c++

I am developing an application, I have added a QToolBar object in that, and have added the QToolButton object on that, I have also connect the clicked() event with that but the problem is that the mouse click event don't work on QToolButton but when I bring focus on that using Tab, then space button works fine, but I want it with mouse click.. any idea? here is the code.
pToolBar = new QToolBar(this);
pToolBar->setAllowedAreas(Qt::NoToolBarArea);//NoToolBarAreaAllToolBarAreas
pToolBar->setFloatable(false);
pToolBar->setGeometry(300,0,160,30);
QToolButton *playButton=new QToolButton(pToolBar);
playButton->setIcon(QIcon("/images/play.png"));
playButton->setGeometry(10,0,40,30);
playButton->setToolTip("Play/Pause");
connect(playButton, SIGNAL(clicked()),SLOT(playButtonClicked()));

The Tool buttons are normally created when new QAction instances are created with QToolBar::addAction() or existing actions are added to a toolbar with QToolBar::addAction().
Example:
QAction *newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
newAct->setShortcut(tr("Ctrl+N"));
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
fileToolBar = addToolBar(tr("File"));
fileToolBar->addAction(newAct);
You can use triggered signal, This signal is emitted when the given action is triggered.
Your example:
QToolButton *playButton=new QToolButton(pToolBar);
connect(playButton, SIGNAL(triggered()),SLOT(playButtonClicked()));

Try explicitly adding the toolbutton to the toolbar. The following code works perfectly for me:
QToolBar *pToolBar = new QToolBar(this);
QToolButton *playButton=new QToolButton(pToolBar);
playButton->setIcon(QIcon("/images/play.png"));
playButton->setText("Play");
playButton->setToolTip("Play/Pause");
playButton->setGeometry(10,0,40,30);
QAction *a = pToolBar->addWidget(playButton);
a->setVisible(true);
connect(playButton, SIGNAL(clicked()),SLOT(playButtonClicked()));
You should probably save the QAction pointer somewhere, since it's the easiest way to assign keyboard shortcuts, enable / disable the button etc. Let me know if this works for you. If it doesn't, perhaps posting a complete compilable example here will help us help you. You should be able to get a small demo program that shows your problem within one or two files.
Cheers,

As jordenysp indirectly explains, the API is QAction centric

Related

QT dialog close and delete

I have a MainWindow and Type class.
A button in the MainWindow sends a signal to a slot with this code:
dialog = new QDialog(this);
Ui_type typeui;
typeui.setupUi(dialog);
dialog->show();
The dialog then shows. When a button is clicked on the dialog, I want to close the dialog and delete it.
I don't understand how to refer to the dialog from the dialog itself.
Any help would be appreciated. Thanks.
You can set Qt::WA_DeleteOnClose attribute on your dialog. This will ensure that the dialog gets deleted whenever it is closed.
Then call close() method in the dialog when your button is clicked.
dialog = new QDialog(this);
Ui_type typeui;
typeui.setupUi(dialog);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
Refer to the documentation for details :
QWidget::setAttribute ( Qt::WidgetAttribute attribute, bool on = true )
Qt::WidgetAttribute
First the close button is at the dialog window right, then most easy way to do it, is create a button, and connect the close() function to response the click() signal.
like:
Dialog::Dialog(){
// other code
QPushButton *closeButton = new QPushButton(tr("Close"));
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
// other code
}
Under the Qt/examples/dialog projects are good reference for your question. check it out.
The simple way to get input from a modal dialog is QDialog::exec(). This may handle everything you need.

How to add QLabel to QGraphicsItem

I have a QGraphicsItem that has text on it. I want this text to be editable, so that if the user double-clicks it, it will enter an edit mode. It seems like the easiest way to do this would be to change the text into a QLineEdit and let the user click away the focus or press enter when they're done.
How can I add a QLineEdit to a QGraphicsItem? I have subclassed the QGraphicsItem so I have access to its internals.
To add any QWidget based object to a QGraphicsScene, a QGraphicsProxyWidget is required.
When you call the function addWidget on QGraphicsScene, it embeds the widget in a QGraphicsProxyWidget and returns that QGraphicsProxyWidget back to the caller.
The QGraphicsProxyWidget forwards events to its widget and handles conversion between the different coordinate systems.
Now that you're looking at using a QLineEdit in the QGraphicsScene, you need to decide if you want to add it directly:
QGraphicsScene* pScene = new QGraphicsScene;
QLineEdit* pLineEdit = new QLineEdit("Some Text");
// add the widget - internally, the QGraphicsProxyWidget is created and returned
QGraphicsProxyWidget* pProxyWidget = pScene->AddWidget(pLineEdit);
Or just add it to your current QGraphicsItem.
Here, you can either add it as a child of the QGraphicsItem:
MyQGraphicsItem* pMyItem = new MyQGraphicsItem;
QGraphicsProxyWidget* pMyProxy = new QGraphicsProxyWidget(pMyItem); // the proxy's parent is pMyItem
pMyProxy->setWidget(pLineEdit); // adding the QWidget based object to the proxy
Or you could add the QGraphicsProxyWidget as a member of your class and call its relevant functions, but adding it as a child is probably much simpler.
QGraphicsTextItem::setTextInteractionFlags (Qt::TextInteractionFlags flags)
API can be used. But you need to create QGraphicsTextItem inside it.
Please check following link for details: Implementation details
You need to create a proxy widget by extending QGraphicsProxyWidget in the case you need some specific behavior or just use a QGraphicsProxyWidget. Take a look at the "Embedded Dialogs" example in your Qt SDK and the QGraphicsProxyWidget documentation. It has been there for a long time so it should be for your version. I hope this helps.

Change text in a QAction that's inside of a QMenu

I have a QMenu objects to which I've added several QAction objects with a certain text. All works well, except that I would like to change the text of those QActions at runtime. I've looked at the QMenu API and didn't find any way to to get them. I also tried actions.at(x) and a few other things. What's the right way to do this?
It really depends on how you are structuring your app. In some circumstances you might be saving your QAction's as members, to which you could access directly. Or you might just be saving the QMenu and populating it with QAction's. Either way, once you have your action, you just call setText(QString) on it:
// init
menu = new QMenu(this);
...
menu->addAction("foo");
// later on
QAction *action = menu->actions().at(0); // access just the first QAction
action->setText("bar");
QMenu also allows you to look up actions by a QPoint location. Again, it really depends on exactly how you will be determining which action you want to change.

How to prevent closing QMessageBox after clicking a button

I have 3 buttons on QMessageBox added by QMessageBox::addButton() method. Is it possible to prevent closing the message box if a button has been clicked? By default every button closes the window, but I don't want to do it for one button.
One interesting way to approach it that worked for me is to completely disconnect the signals for the target button created, and then re-add the intended functionality. This won't work for everyone, especially if the button isn't created this way and/or you still want to close the dialog correctly. (There might be a way to add it back and/or simulate the behavior with QDialog::accept, QDialog::reject, QDialog::done - haven't tried yet.)
Example:
QMessageBox *msgBox = new QMessageBox(this);
QAbstractButton *doNotCloseButton = msgBox->addButton(tr("This button will not close anything"), QMessageBox::ActionRole);
// Disconnect all events - this will prevent the button from closing the dialog
doNotCloseButton->disconnect();
connect(doNotCloseButton, &QAbstractButton::clicked, this, [=](){ doNotCloseButton->setText("See? Still open!"); });
If you can get a pointer to the QMessageBox widget, you can try to install a QObject::eventFilter on it which filters the QEvent::Close.
Just had the same problem but I wanted to add a checkbox and it kept closing the dialog on clicked even with the ButtonRole set to QMessageBox::ActionRole (tried others too). For this scenario I just called blockSignals(true) on the QCheckBox and now it allows check/uncheck behaviour without closing the dialog. Luckily QCheckBox works fine without signals but assume you want a signal from your button.
They should likely add a new role that doesn't close the dialog as it's a pain to derive a class for simple customizations.
I looked through the addButton() functions overloads, but there is no custom behavior for the buttons you add with this method. They will behave like the standard buttons on a messagebox should.
However if you want to create a fully customizable dialog, then your best option is to extend the QDialog class and use whatever controlls you like on it.
Thanks to #Albert's Answer, I found that this also possible in python:
messagebox = QMessageBox()
button = QPushButton("This button will not close anything")
messagebox.addButton(button, QMessageBox.ButtonRole.NoRole)
button.disconnect()

QDockWidget is closed if main window is minimized

I'm using Qt 4.7 on Windows 7 Ultimate 32 bit.
The QMainWindow of my program has a QDockWidget. I've noticed that if I minimize the main window by the minimize button on the title bar, after restoring it the dock widget is closed. I didn't write any support for a feature like this!
How does this happen and how to prevent this?
Thanks.
I encountered this error when writing my own application. I have QDockWidget with options for my application. Using Qt Creator I created menu with QAction actionMenu which was checkable. Then I connected QDockWidget and QAction like this:
QObject::connect(ui->dockWidget, SIGNAL(visibilityChanged(bool)),
ui->actionMenu, SLOT(setChecked(bool)));
QObject::connect(ui->actionMenu, SIGNAL(toggled(bool)),
ui->dockWidget, SLOT(setVisible(bool)));
The order of connection is not important. And then when I minimized application with QDockWidget being visible, after I restored it QDockWidget was closed and actionMenu was unchecked.
In fact there are two solutions. First which works for me is to use SIGNAL(triggered(bool)) instead of SIGNAL(toggled(bool)):
QObject::connect(ui->dockWidget, SIGNAL(visibilityChanged(bool)),
ui->actionMenu, SLOT(setChecked(bool)));
QObject::connect(ui->actionMenu, SIGNAL(triggered(bool)),
ui->dockWidget, SLOT(setVisible(bool)));
The second solution uses action which you can obtain from QDockWidget:
// Retrieve action from QDockWidget.
QAction *action = ui->dockWidget->toggleViewAction();
// Adjust any parameter you want.
action->setText(QString("&Menu"));
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
action->setStatusTip(QString("Press to show/hide menu widget."));
action->setChecked(true);
// Install action in the menu.
ui->menuOptions->addAction(action);
I know for sure that SIGNAL(toggled(bool)) was causing in my application closure of QDockWidget.
I faced the same problem... I managed to get rid of it by using a method called StoreWindowsLayout and RestoreWindowsLayout.
StoreWindowsLayout will save the content of the ByteArray returned by the Method QMainwindow::saveState().
RestoreWindowsLayout will restore that bytearray, and therefore your windows layout, the qdockwidget visibility state and so on...
I call StoreWindowsLayout on ApplicationMainFrm::changeEvent, on ApplicationMainFrm::closeEvent (it's likely this one you'll need) and in ApplicationMainFrm::hide().
Then I use restoreWindowsLayout in ApplicationMainFrm::showEvent.
Exemple of use of restoreWindowsLayout in my MainForm :
void ApplicationMainFrm::showEvent(QShowEvent* pEvent)
{
QMainWindow::showEvent(pEvent);
restoreWindowsLayout();
}
Hope it helps !