How do I assign a shortcut to a QPushButton? - c++

The documentation on assigning a shortcut to a QPushButton is as follows:
A shortcut key can be specified by preceding the preferred character with an ampersand in the text. For example:
QPushButton *button = new QPushButton("&Download", this);
In this example the shortcut is Alt+D.
What do I do if I don't want an Alt+[A-Z] shortcut? For example, in my case I want my button to be fired when the TAB button is pressed. How can I achieve this effect?

You can use setShortcut method, eg:
pushButton->setShortcut(QKeySequence(Qt::Key_Tab));
It will fire then slots assigned to the clicked() signal

You can use a QShortcut. Another tip: Qt signal / slots mechanism allows you to connect a signal to a signal.

You can overload QWidget::keyPressEvent and trigger your button click directly or through previously specially connected signal
void MainWindow::keyPressEvent(QKeyEvent * pEvent)
{
if (Qt::Key_Tab == pEvent->key())
{
ui->button->click();
}
QMainWindow::keyPressEvent(pEvent);
}

You can define the key, the target object and it's relevant slot in the constructor of QShortcut :
QShortcut * shortcut = new QShortcut(QKeySequence(Qt::Key_Tab),button,SLOT(click()));
shortcut->setAutoRepeat(false);

Related

Adding event to the context menu in QPlainTextEdit

This is my Context Menu after right click on QPlainTextEdit. I want to add function to load data from file in Context Menu. Can I? How?
Method 1: QPlainTextEdit::contextMenuEvent
You should override the QPlainTextEdit::contextMenuEvent as mentioned in the Qt documentation:
void MyQPlainTextEdit::contextMenuEvent(QContextMenuEvent *event)
{
QMenu *menu = createStandardContextMenu();
menu->addAction(tr("My Menu Item"));
//...
menu->exec(event->globalPos());
delete menu;
}
You can connect the QAction::triggered signal to your method (slot) to load the data or you can use one of the QMenu::addAction overloads, which allows you to specify a slot directly.
If you do not want to subclass QPlainTextEdit (to override contextMenuEvent), you can use event filtering in Qt.
Note that contextMenuEvent() is only called when contextMenuPolicy is not set (or set to its default value Qt::DefaultContextMenu)
Method 2: QWidget::customContextMenuRequested
As an alternative, you can use Qt's signal and slot mechanism to create the context menu when requested by the user.
The contextMenuPolicy property should be set to Qt::CustomContextMenu, in which case the QWidget::customContextMenuRequested signal is invoked whenever a context menu is requested by the user. This signal should be connected to your own slot, which should create the context menu as shown in the code above (Method 1).
Using MyQPlainTextEdit in Qt Designer
To use your MyQPlainTextEdit in a .ui file, you should implement it as a promoted QPlainTextEdit and use it in your .ui file instead of a regular QPlainTextEdit. See the Qt documentation for more information.
To be able to use your class in the Qt Designer, you should not forget to implement a constructor accepting a parent QWidget as is done in the AnalogClock example. Note that implementing such a constructor is always a good idea, because Qt typically manages ownership through a child-parent relationship.
Building on #m7913d answer.
The downside to the techniques is you must derive from the QPlainTextEdit class for a very minor extension. My preferred method, especially when using designer based widgets, is to add an eventFilter, and filter out the mouse event that is a mousebutton press
MyWidget::MyWidget(...)
{
...
ui->plainTextEdit->installEventFiler( this )
}
MyWidget::eventFilter( QObject * obj, QEvent * event )
{
if ( ( obj == ui->plainTextEdit )
&& ( event->type() = QEvent::MouseButtonPress )
&& ( dynamic_cast< QMouseEvent * >( event )->buttons() & Qt::MouseButton::RightButton )
{
// create menu
auto menu = ui->plainTextEdit->createStandardContextMenu();
// modify menu
menu->exec( mouseEvent->globalPos() );
delete menu;
return true;
}
return false;
}

Qt custom QPushButton clicked signal

I want to send two integers, string and fret, to a SLOT that will process the location of the button that was pressed. The SIGNAL and SLOT argument have to match so I am thinking I need to reimplement the QPushButton::clicked event method. Problem is I am new to Qt and could use some direction.
connect(&fretBoardButton[string][fret], SIGNAL(clicked()), this, SLOT (testSlot()));
If you use the C++11 connection syntax you can use a lambda with calls testSlot with your string and fret arguments:
connect(&fretBoard[string][fret], &QPushButton::clicked, [this, string, fret]() {
testSlot(string, fret);
});
This code creates a lambda using the [captures, ...](arguments, ...) { code } syntax. When you make the connection it captures the string and fret variable values, and will then pass them on to testSlot when the button is clicked.
There are Two approaches you could use to add the string and fret information. one is to use the sender() function to get the button which emitted the signal. you can the access fret and string if they are members of your button class so in the SLOT you would have.
MyPushButton *button = (MyPushButton *)sender();
button.getFret();
button.getString();
However since you are already subClassing QPushButton you could use a private SLOT to catch the buttonClicked signal and re-emit a signal with the right values.
In the constructor
connect(this, SIGNAL(clicked()), this, SLOT(reemitClicked()));
and then the reemit SLOT
void MyPushButton::reemitClicked()
{
emit clicked(m_fret, m_string);
}
be sure to add the appropriate private slot and public signal to you class
https://doc.qt.io/archives/qq/qq10-signalmapper.html see this artical for a good discussion on various ways to add an argument to signal.

How to catch information for Qt designer

I have created a Qdialog box using the Qt creator designer as shown below:
When I need to display it, I'm instantiate the class dialogoverwrite (.cpp, .h and .ui)
DialogOverwrite *OverwriteDialog = new DialogOverwrite;
OverwriteDialog->exec();
OverwriteOption = OverwriteDialog->result()
My issue is that I want to get the QDialogButtonBox result but I do not know how. the current code, returning the result of the OverwriteDialog but it's not returning any QDialogButtonBox::Yes, QDialogButtonBox::YesToAll ...
How to catch the QButtonGroup result and not the QDialog result.
In the same way, If I want to change the label value from "File(s) and/or Folder(s)" to another label, how to access to this QLabel ?
Thanks for your help
When you pressed QDialogButton it was emit signal clicked(QAbstractButton*) by catching this signal you can identify which action button pressed.
Please go through following link it would be help you.
Qt: How to implement QDialogButtonBox with QSignalMapper for non-standard button ??
Well the standard way to do this is to handle the result by connecting it. So you could do:
connect(this, SIGNAL(clickedDialogButton(QAbstractButton*)),
SLOT(dialogButton(QAbstractButton* aButton)));
Next you would create a function in your class called dialogButton (for example) and have that handle the result:
void MyUI::dialogButton(QAbstractButton* aButton) {
// Obtain the standard button
StandardButton button = buttonBox−>standardButton(button);
// Switch on the type of button
switch (button) {
case QDialogButtonBox::YesToAll:
// Do the thing you would like to do here
break;
// add some more cases?
}
}
You could also check for the signal given by the QButtonGroup. Something like: void QGroupButton::buttonClicked(QAbstractButton* button) would work in the same way.

How to override default shortcuts in Qt

I have a widget which can contain one or more QTableView child widgets. By default, when I select a range in one of QTableViews and hit crtl+c only the leftmost uppermost cell gets copied to the clipboard. I would like to copy the entire range, so I implemented a copy() slot which does the job. I would like the copy slot to be accessible both from a context menu (when the user makes a selection and right clics the corresponding QTableView) and by the ctrl+c shortcut.
class Widget
{
Q_OBJECT
public:
void setupContextMenu();
private:
QMenu* contextMenu_;
QAction* copyAction_;
QTableView* tableView_;
private slots:
void copy();
}
void Widget::setupContextMenu()
{
contextMenu_ = new QMenu(this);
copyAction_ = contextMenu_->addAction("&Copy");
copyAction_->setShortcut(QKeySequence::Copy);
connect(copyAction_, SIGNAL(triggered()),
this, SLOT(copy()));
}
When I select a range and right click, the appropriate context menu pops up and it even contains the name of the shortcut. When I click the "Copy" action in the context menu, the copy() slot gets executed. However the ctrl+c shortcut just copies only the leftmost uppermost cell in the selection as before. Also, the copy() slot does not get executed.
How can I repair this?
I am not sure but maybe shortcut key doesn't work with contextual menus in Qt?
The handling of copy shortcut happens in QAbstractItemView::keyPressEvent(). You can install an event filter to your QTableView watching for KeyPress event and handle your copy there.

QAction shortcut doesnt always work

I have a Qaction on a menu item for deleting selected items in one of my views. Here is how i create the action:
deleteAct = new QAction( tr("Delete Selected"), this);
deleteAct->setShortcut(QKeySequence::Delete);
connect(deleteAct, SIGNAL(triggered()), this, SLOT(deleteSelected()));
I setup a keyboard shortcut (Delete Key) which should trigger the delectAct action. It works most of the time but at some points it stops working... Does anyone know why the shortcut would stop working?
Note: the action still works if i trigger it from the menu item. Its just the shortcut that doesn't...
You need to add the action to a widget, since it's the widget that will be listening for key events.
Assuming "this" is a mainwindow, simply do
addAction(deleteAct);
Note that you can add the same action to multiple widgets (that's the whole point of the separated action concept). So it's fine to add it to the mainwindow and to a menu.
Try changing the shortcut context of the action, for example:
deleteAct->setShortcutContext(Qt::ApplicationShortcut);
The shortcut works depending on the focus of the application views.
I wanted to have shortcuts working on buttons.
In my application I changed the shortcut context of the action,
added the action to the widget
and finally to the subviews of the application.
Then the necessary signals and slots of widget an action must be connected.
const QAbstractButton*button = dynamic_cast<QAbstractButton*>(widget);
action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
widget->addAction(action);
ui->textBrowser->addAction(action);
ui->treeSource->addAction(action);
if (button)
{
if (button->isCheckable())
{
action->setCheckable(true);
if (button->isChecked()) action->setChecked(true);
connect(action, SIGNAL(triggered(bool)), button, SLOT(setChecked(bool)));
connect(button, SIGNAL(clicked(bool)), action, SLOT(setChecked(bool)));
}
else
{
connect(action, SIGNAL(triggered()), button, SLOT(click()));
}
}
Without seeing the complete code, I'd hazard a guess that somewhere it gets enabled/disabled. Make sure that the shortcut is getting hit in the constructor and not 'disabled' somewhere else because of a setting perhaps.
You can use http://doc.qt.io/qt-5/qaction.html#shortcutVisibleInContextMenu-prop property since QT 5.10 for this:
deleteAct->setShortcutVisibleInContextMenu(true);