Create QAction with shortcut, without inserting in menu - c++

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <cassert>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QAction* back = new QAction(this);
back->setVisible(true);
back->setShortcut(QKeySequence("Ctrl+M"));
bool cres = connect(back, SIGNAL(triggered(bool)), this, SLOT(mySlot()));
assert(cres);
}
In this code I tried to catch Ctrl+M key event. I don't want to put the action in menu. connect returns true but mySlot is never called. When action is inserted in menu, shortcut works well. What I have done wrong?

QAction is dormant until you insert it somewhere. As vahancho has suggested, use QShortcut. You need to instantiate the shortcut for each top-level widget (window) where you want it to be active. Thus if you have 5 top-level windows, you'll need 5 shortcuts, each having one of windows as its parent.
There is no way to use QShortcut as a global shortcut without the gui. QShortcut is only active when its associated widget has focus. The widget could be a top-level window.
System-global shortcuts are the subject of this question.

Related

Qt ignore click when dismissing popup on Windows

I have an issue with Qt where the behavior on Windows is different than Mac or Linux. I discovered the issue on PySide2 but was able to reproduce it in a minimal C++ application as well (see below).
When I dismiss a Popup widget by clicking outside the click is ignored by the rest of the application. This is the desired behavior and is the way it works on Linux and Mac. However in Windows this click is registered by the widget that was clicked which in my application leads to unwanted user input on the underlying widgets.
Is there a way to will prevent the dismissal click from being passed on in Windows? I am fine with having platform dependent code for this issue.
The behavior can be reproduced with this example. When the popup is open and testButton is clicked the onTestButton method will be executed.
#include "mainwindow.h"
#include <QPushButton>
#include <QHBoxLayout>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setFixedHeight(600);
this->setFixedWidth(800);
QWidget* w = new QWidget();
QDialog* popUp = new QDialog();
popUp->setFixedHeight(200);
popUp->setFixedWidth(200);
popUp->setWindowFlag(Qt::Popup | Qt::FramelessWindowHint);
popUp->setModal(true);
popUp->setVisible(false);
QHBoxLayout *layout = new QHBoxLayout(this);
w->setLayout(layout);
QPushButton* openButton = new QPushButton("open popup");
// same behavior whether using QDialog::show or QDialog::exec
connect(openButton, &QPushButton::clicked, popUp, &QDialog::show);
QPushButton* testButton = new QPushButton("catch mouse");
connect(testButton, &QPushButton::clicked, this, &MainWindow::onTestButton);
layout->addWidget(openButton);
layout->addWidget(testButton);
this->layout()->addWidget(w);
}
void MainWindow::onTestButton()
{
qDebug() << "caught mouse";
}
QWidget is just a widget, if you want it to "hold" focus, then use QDialog instead.
Also it changes the "logic" if u use it as QDialog.show or QDialog.exec.
Can you try with QDialog?
QDialog::setModal(bool) should set the dialog to modal, thus prohibiting clicking into the mainwindow.
Your windowflag Qt::Popup blocked modality. If you want to use that approach and create Qwidget as a modal dialog (Qt::Dialog), it should be launched from another window, or have a parent and used with the QWidget::windowModality property.
Tested:
auto w = new QWidget;
QDialog* popUp = new QDialog;
popUp->setFixedHeight(200);
popUp->setFixedWidth(200);
popUp->setWindowFlags( Qt::FramelessWindowHint);
popUp->setModal(true);
QHBoxLayout *layout = new QHBoxLayout(this);
w->setLayout(layout);

Manually place a toolbar Qt c++

My QMainWindow contains three different windows.
I would like to display three different toolbars. One for each window.
For now I display a toolbar but I can not place it just above my windows.
I wanted to know if it was possible?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent) {
//here I declared a widget and my three windows.
QToolBar *toolBar= addToolBar("window");
addLine=new QAction("Add Line",this);
removeLine=new QAction("Remove line",this);
removeAll=new QAction("Remove all",this);
toolBar->addAction(addLine);
toolBar->addAction(removeLine);
toolBar->addAction(removeAll);
}

QT connect to push button does not work

I tried a very simple program in QT. I created a dialog in QT designer with one push button. I want to have program, when I click on push button, I will get message box. I debugged the program. But, signal will not come to function OnClickedPushButton(bool) after clicking on push button. Where is a mistake?
My code is looking like:
#include "qttest.h"
#include <QtGui>
#include <QMessageBox>
QTTest::QTTest(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(OnClickedPushButton()));
QPushButton *button = new QPushButton(this);
button->setText("ClcikMe");
button->setGeometry(QRect(QPoint(150, 50), QSize(85, 25)));
connect(button, SIGNAL(clicked()), this, SLOT(OnClickedPushButton()));
}
QTTest::~QTTest()
{
}
void QTTest::OnClickedPushButton()
{
QMessageBox::about(this, "Message", "You pushed button.");
}
I can build it, and I can launch it. But, debugger writes me in the constructor following messages:
QObject::connect: No such slot QTTest::OnClickedPushButton() in qttest.cpp:9
QObject::connect: (sender name: 'pushButton')
QObject::connect: (receiver name: 'QTTestClass')
QObject::connect: No such slot QTTest::OnClickedPushButton() in qttest.cpp:14
QObject::connect: (receiver name: 'QTTestClass')
I can see both buttons at the window. pushButton and button. But, if I will click on button the message will not come due to wrong slot mapping. Do you have any idea how to do it correctly?
There are two possibilities here:
You either declare OnClickedPushButton as a slot, as mentioned by Avi, or you use the new signal/slot connection syntax. With the new syntax you'd connect the signal to an arbitrary function like this:
connect(pushButton, &QPushButton::clicked, this, &QTTest::OnClickedPushButton);
The major advantage this has over the old syntax is that it is checked at compile time and you can't end up with runtime errors like the ones you currently got.
You need to declare the 'OnClickedPushButton' as SLOT in your header file.
Compiler cannot find the specified function in slots list in your code.
If you have already a mainwindow created while project creation then you do not have to create the pushbutton manually. You can open the MainWindow using the designer, drag and drop the pushbutton and then right click on the button, select "Go to slot" option, this will open the source code. The sample source is here,
#include "qttest.h"
#include "ui_qttest.h"
#include <QMessageBox>
QTTest::QTTest(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::QTTest)
{
ui->setupUi(this);
}
QTTest::~QTTest()
{
delete ui;
}
void QTTest::on_pushButton_clicked()
{
QMessageBox::about(this, "Message", "You pushed button.");
}
Also please paste your header code.
try this connect(ui.pushButton, SIGNAL(release()), this, SLOT(OnClickedPushButton(bool))); or you can use SIGNAL(clicked()) without bool. I didn't test it yet but seem work for you.

Qt C++ Creating toolbar

I am learning Qt and trying some examples in the book "Foundations of Qt Development".
In the book, there is a section teaching Single Document Interface with an example creating a simple app like a notepad.
However I am having problem with toolbar creating.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle(QString("%1[*] - %2").arg("unnamed").arg("SDI"));
connect(ui->docWidget->document(), SIGNAL(modificationChanged(bool)), this, SLOT(setWindowModified(bool)));
createActions();
createMenu();
createToolbars();
statusBar()->showMessage("Done");
}
It is the constructor of the main window.
void MainWindow::createToolbars()
{
QToolBar* toolbar;
toolbar = addToolBar(tr("File"));
toolbar->addAction(anyaction);
}
This is how the book create the toolbar.
However, when I try to run the program, there are two toolbars created.
One is the toolbar created by the code and called "File"
Another is a blank toolbar created by the ui designer ie. *ui.toolbar.
In order to get rid of two toolbars, I tried using only the *ui.toolbar.
It's working. The code is shown below.
void MainWindow::createToolbars()
{
ui->toolBar->addAction(anyaction);
}
But I tried to create the toolbar by code only, ie. not adding a toolbar in the ui designer.
So I write this:
void MainWindow::createToolbars()
{
QToolBar* FileBar = this->addToolBar(tr("File"));
FileBar->addAction(anyaction);
}
However, there is a compile error.
The compiler use this function:
void QMainWindow::addToolBar(QT::ToolBarArea area, QToolBar * toolbar)
instead of what I want:
QToolBar * QMainWindow::addToolBar(const QString & title)
http://doc.qt.io/qt-5/qmainwindow.html#addToolBar-3
What is my mistake here?
When you removed QToolBar from MainWindow QtCreator automatically removed import of QToolBar class.
Just add this to the top of mainwindow.h:
#include <QToolBar>
And it is better to define QToolBar* FileBar in private section of MainWindow in mainwindow.h. Then you will be able to access it from any method of MainWindow class.
void MainWindow::createToolbars()
{
FileBar = this->addToolBar(tr("File"));
FileBar->addAction(anyaction);
}
When you see such message:
must point to class/struct/union/generic type
First of all try to include headers for necessary class.

Qt QLabel default text

My code is very simple:
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
lineEdit = new QLineEdit();
label = new QLabel("");
connect(lineEdit, SIGNAL(textChanged(QString)), label, SLOT(setText(QString)));
ui->setupUi(this);
}
I compiled it, and no error or warning.
But When I run it, The UI like this:
Why QLabel's default text was TextLabel?
You should read some tutorials from Qt docs. You're mixing QtDesigner ui with manual widget creation. Your default text on label comes from your ui file. Also you don't need to create your labels/line edits when you use ui file. Just get them stright from ui class. So if you'll get your ui file back to normal, then you may do something like this:
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->lineEdit, SIGNAL(textChanged(QString)), ui->label, SLOT(setText(QString)));
}
Also change text in your label with Qt Designer by doubleclick on it.
That's because both your
lineEdit = new QLineEdit();
label = new QLabel("");
are different that the ones you created in your ui. You are defining two new widgets, while you should probably reference the previous ones:
ui->lineEdit->clear();
ui->label->clear();
connect(ui->line....
//etc...