Change text in a QAction that's inside of a QMenu - c++

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.

Related

Implementing a QAction in the menu bar

I am trying to implement something like the below in Qt:
Basically the user can click on the empty box (to the left of "Average") to spawn a new dialog box. And also the user can click on "Average" to perform another function.
I understand that QWidgetAction can achieve this, but I was wondering if there is any simpler way to achieve this; or does QAction itself already has such a functionality.

Reusing a QMenu within multiple Qmenu

Hi all,
I have some code generating a dynamically filled QMenu depending on some data (I will call it thisMenu). The QMenu thisMenu is created, taking some "main" QWidget as parent and is added to a QMenuBar within this QWidget (menuBar.addMenu(&thisMenu). Latter on, I want the user to be able of accessing thisMenu from a context menu (the user right click on some portion of the QWidget, which pops a QMenu (called contextMenu) with some actions, and the previous QMenu as a sub-menu).
If I reuse the QMenu that I first created with contextMenu.addMenu(&thisMenu) I find out that, even if contextMenu pops at the right global position, thisMenu is always translated to some other position and appearing sometimes above, sometimes under contextMenu.
I can test that this is linked to the parenting chain : thisMenu is not a child of contextMenu, if I create it a child of contextMenu, everything is fine. Is there a way of cleanly handling this case without recreating a QMenu similar to thisMenu, or changing the parent of thisMenu; i.e. reusing thisMenu in both QMenuBar and in some context menu/QMenu? In other what is the proper way of handling parenting chain for QMenu and sharing QMenu?
Thank you,
In other what is the proper way of handling parenting chain for QMenu and sharing QMenu?
You cannot share a QMenu across multiple places -- each QMenu can only exist in one place at a time. You should create separate QMenus: One for your menu bar and one for your context menu.
A simple way is to put your menu-generating code in a for-loop, to create multiple identical menus.
May I ask why you want to reuse your QMenu?
I can test that this is linked to the parenting chain : thisMenu is not a child of contextMenu
Yes, that is described in the documentation. When you add one QMenu to another, the parent doesn't change: http://qt-project.org/doc/qt-5/QMenu.html#addMenu
if I create it a child of contextMenu, everything is fine.
The position of a widget is always painted in a position relative to its parent. (Remember: A QMenu is a QWidget)
Following JKSH's answer, I decided to use a function to duplicate QMenu, without duplicating the QAction in it (they are not inheriting QWidget), hence conserving all established connections :
void duplicateMenu(QMenu* dst, QMenu& origin)
{
QMenu* sub = dst->addMenu(origin.title());
QList<QAction*> actions=origin.actions();
for(QList<QAction*>::iterator it=actions.begin(); it!=actions.end(); it++)
{
QMenu* itMenu = (*it)->menu();
if(itMenu!=NULL)
duplicateMenu(sub, *itMenu);
else
sub->addAction(*it);
}
}

How to use the same QAction in two QMenus with different text?

So I have an action I want to expose in multiple menus (one of the main menus, and some context menus). I'd like the menu item text to differ slightly from menu to menu (to make the mnemonic unique, and to be more or less verbose as necessary in each context).
In MFC (which I have the pleasure of migrating away from at the moment) this was easy, as each menu's items were defined separately, and could map to the same ID, which would be linked to the handler. In Qt though, the QAction encapsulates the behaviour as well as the text/icon/etc. So I don't suppose there's straightforward support for it to return a different text dependent on where it's being used.
My thought about how to handle this is, for each location, to create a "proxy" QAction, which has the text specific to that context and simply has its triggered() signal connected to the original QAction's one. But I thought I should check first about whether there's an easier way to approach this.
I don't know about MFC, but in Qt - QAction is just an interface. One QAction object can have only one text to display. But the real action QAction does, you will implement in what Qt calls SLOT. Then you can have as much interfaces(or QActions objects) pointing to the same slot - just connect all QAction objects, that you want to do the same thing, to the same slot.
Hope this helps.
Your suggested solution is the simplest, I think. You can change the text of an action dynamically, when a menu is activated, but this looks more complicated to me.

Problem with event handling on QToolButton in Linux

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

Hiding a QWidget on a QToolbar?

I have directly added some QWidgets to a QToolbar but simply going widget->setVisible(false) did not work. Can someone please give me an example of how to show and hide a widget that is on a QToolbar?
Thanks!
You need to call setVisible() on the appropriate QAction instead. For example, addWidget() returns a QAction*:
QAction* widgetAction = toolBar->addWidget(someWidget);
widgetAction->setVisible(false);