Help on QStackedWidget - qt

I am using a QStackedWidget on my mainWindow. The firstPageWidget on stackedWidget contains 3 buttons. Now If I will press the first button on firstPage, I want the stackedWidget show the 2nd Page widget. Following are the details
I tried to connect like this in my mainwindow
connect(firstPageWidget->button1,SIGNAL(clicked()),stackWidget,SLOT(setCurrentIndex(int)));
Now I want to know how to pass the value of index number to stackWidget to set currentIndex?
If my question is not much clear please tell me I will explain more.

You probably need to use QSignalMapper class:
QSignalMapper mapper = new QSignalMapper(); // don't forget to set the proper parent
mapper->setMapping(firstPageWidget->button1, 2); // 2 can be replaced with any int value
connect(firstPageWidget->button1, SIGNAL(clicked()), mapper, SLOT(map()));
connect(mapper, SIGNAL(mapped(int)), stackWidget, SLOT(setCurrentIndex(int)));

Instead of buttons you could use a QListWidget containing selectable Icons. QListWidget has a method called QListWidget::currentItemChanged ( QListWidgetItem * current, QListWidgetItem * previous ). I used that method in a program I wrote some time ago... There I wrote a function on_change_widget( QListWidgetItem *current, QListWidgetItem *previous ) which I connected to the SIGNAL currentItemChanged:
connect( my_list_widget,
SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
this,
SLOT(on_change_widget(QListWidgetItem *, QListWidgetItem *))
);
That should do the trick.
You should have a look at the Config Dialog Example, there they use the same method to swap widgets.
Of course you can use normal buttons too, in connection with the QSignalMapper chalup mentioned.

You can also use QButtonGroup and set proper id to each button, then connect QButtonGroup signal QButtonGroup::buttonClicked(int) with stacked widget slot QStackedWidget::setCurrentIndex(int)

Related

How To Create Tri-state Actions on Menus Using Qt

I have a situation where I need a tri-state checkable action on a QMenu, and the QAction class appears to only support on or off, unless I'm overlooking something obvious. The situation I have is a context menu where multiple objects are selected, but may have different states for a given boolean condition (i.e. for a given property, some objects have a true value and some false). I can leave the action unchecked when there's a mix of values, but I feel that's misleading to the user.
I'm using Qt 5.5.1 and very experienced with Qt, but not seeing a way to achieve what I want in this instance.
There is no direct way to do it from a QAction, but it is possible to subclass the QWidgetAction and create an action that contains a QCheckBox widget.
class CheckBoxAction : public QWidgetAction {
public:
CheckBoxAction (const QString &text) : QWidgetAction(Q_NULLPTR) {
QHBoxLayout *_layout = new QHBoxLayout(Q_NULLPTR);
QWidget *_widget = new QWidget(Q_NULLPTR);
QLabel *_label = new QLabel(text);
mCheckbox = new QCheckBox(Q_NULLPTR);
_label->setAlignment(Qt::AlignLeft);
_layout->addWidget(mCheckbox);
_layout->addWidget(_label);
_layout->addStretch();
_widget->setLayout(_layout);
setDefaultWidget(_widget);
}
QCheckBox *checkbox() {
return mCheckbox;
}
private:
QCheckBox *mCheckbox;
};
Simply use the class to then add to your menu; for instance:
CheckBoxAction *checkAction = new CheckBoxAction(QStringLiteral("My Action"));
checkAction->checkbox()->setCheckState(Qt::PartiallyChecked);
menu->addAction(checkAction);
You can use the checkbox() method in order to connect to signals when it changes; or change the checkbox state. Hope this helps.

How to access a QAction using the QtTest lib?

I have a pop-up menu in a QTableWidget (resultTable). In the constructor of my class I set the context menu policy:
resultTable->setContextMenuPolicy(Qt::CustomContextMenu);
connect(resultTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(popUpMenuResultTable(QPoint)));
The popUpMenuResultTable function:
void MyClass::popUpMenuResultTable(QPoint pos)
{
QMenu menu;
QAction* actionExport = menu.addAction(QIcon(":/new/prefix1/FileIcon.png"), tr("Export"));
connect(actionExport, SIGNAL(triggered()), this, SLOT(exportResultsTable()));
menu.popup(pos);
menu.exec(QCursor::pos());
}
Now, I need to implement a function to test my GUI using the QtTest lib.
How can I produce the same result as a user by right clicking on my resultTable? Basically, I need to get access to the actionExport (QAction) and trigger it.
For example:
I already tried:
QTest::mouseClick(resultTable, Qt::RightButton, Qt::NoModifier, pos, delay);
but it does not show the QMenu.
I'm using Qt 5.3.2.
Maybe not entirely what you are after but an alternative approach that is easier to test.
Instead of creating the menu manually you register the actions with the widgets and use Qt::ActionContextMenu:
// e.g. in the widget's constructor
resultTable->setContextMenuPolicy(Qt::ActionsContextMenu);
QAction* actionExport = menu.addAction(QIcon(":/new/prefix1/FileIcon.png"), tr("Export"));
connect(actionExport, SIGNAL(triggered()), this, SLOT(exportResultsTable()));
resultTable->addAction(actionExport);
Then you either add an accessor to your widget that returns resultTable->actions() or just make actionExport a member of your class.
Once your test code has access to the action it can simply call its trigger trigger() method.

How to programmatically close QMenu

I have pretty specific situation. I want to place a QAction into QToolbar and reach following behaviour:
Checkable QAction with icon.
Classic arrow on the right side which is used for showing menu
By pressing this arrow my QDialog should appears on screen instead of QMenu-like one
Now I'm a bit confused with implementing all this things together.
For now I've created QAction added it to toolbar and also created an empty QMenubecause I didn't get the idea of how to add the "dropdown" arrow another way.
So, I also connected my slot to QMenu aboutToShow() signal and now, I can create my dialog and exec() it just before QMenu shows. But here's the main problem appears: after I did everything with my dialog an click OK button QMenu trying to appear, but as it is empty it shows nothing and further actions become available only after I left-click somwhere to "close" this menu.
Is there any way to force QMenu not to show or can inherit from QMenu and reimplemnt its behaviour (I've tried to do such trick with exec() show() popup() methods of QMenu after subclassing from it, but none of them are being called when menu appears on the screen) ?
Here's the solution, which worked for me.
class QCustomMenu : public QMenu
{
Q_OBJECT
public:
QCustomMenu(QObject *parent = 0):QMenu(parent){};
};
In code:
QAction* myActionWithMenu = new QAction ( "ActionText", toolbar);
QCustomMenu* myMenu = new QCustomMenu(toolbar);
connect(myMenu, SIGNAL(aboutToShow()), this, SLOT(execMyMenu()));
execMyMenu() implementation:
void execMyMenu(){
m_activeMenu = (QCustomMenu*)sender(); // m_activeMenu -- private member of your head class, needs to point to active custom menu
QMyDialog* dlg = new QMyDialog();
// setup your dialog with needed information
dlg->exec();
// handle return information
m_myTimer = startTimer(10); // m_myTimer -- private member of your head(MainWindow or smth like that) class
}
Now we have to handle timerEvent and close our menu:
void MyHeadClass::timerEvent(QTimerEvent *event)
{
// Check if it is our "empty"-menu timer
if ( event->timerId()==m_myTimer )
{
m_activeMenu->close(); // closing empty menu
killTimer(m_myTimer); // deactivating timer
m_myTimer = 0; // seting timer identifier to zero
m_activeMenu = NULL; // as well as active menu pointer to NULL
}
}
It works great on every platform and does what I wanted.
Hope, this would help someone. I've spent week trying to find this solution.

How to put pushbutton inside the QMenu or QAction control?

I need to put a QPushButton inside a QMenu. Is it possible and, if so, then how?
I want to achieve something like this:
QWidgetAction is what you are looking for. This is what is on qt docs
The QWidgetAction class extends QAction by an interface for inserting custom widgets into action based containers
So basically it gives a custom UI to QAction according to what QWidget you pass to it.
I have used QWidgetAction to show checkbox as QMenu items.
QCheckBox *chkBox = new QCheckBox(menu);
chkBox ->setText("MyCheckBox");
QWidgetAction *chkBoxAction= new QWidgetAction(menu);
chkBoxAction->setDefaultWidget(chkBox);
menu->addAction(chkBoxAction);
You can then handle signals from checkbox accordingly.
If you only want a menu item to have a state, you may use Checkable property of QAction:
rotateAct = new QAction(QIcon(":/images/Mouse/Rotate.png"), tr("&Rotate"), this);
rotateAct->setCheckable(true);

Can I decide where a Qaction is added to a Qmenubar

I need to add a QAction directly into a QMenuBar (not an QAction inside a QMenu but a QAction directly in the QMenuBar) I am able to do this with the following command.
ui->menuBar->addAction("VFTP",this, SLOT(VFTPmenuTrigger()) );
My only problem is that when I add it, it is appended to the end of the menu bar that I have built in Qt designer. I would like to be able to put it somewhere in the middle. Seems the only way I could do this is if I generate the menu bar by coding it only. Is there a way to build most of my menuBar in Qt Designer and then add that Qaction in the menu bar where I want? I hope I am clear and I added the QAction programmatically because it is not possible to do so with Qt (I know it sounds countintuitive to put a QAction directly in the menu bar but this is what the customer wants)
If you look at QMenuBar code you'll that it does this:
QAction *QMenuBar::addAction(const QString &text, const QObject *receiver, const char* member)
{
QAction *ret = new QAction(text, this);
QObject::connect(ret, SIGNAL(triggered(bool)), receiver, member);
addAction(ret);
return ret;
}
which basically uses QWidget::addAction(). So it stands to reason that you can use QWidget::insertAction() yourself to do the same thing. insertAction() lets you specify before what QAction you want to add.

Resources