QT connect to push button does not work - c++

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.

Related

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.

Show QWidget or QWindow near QSystemTrayIcon in QT C++

I have managed to get the QSystemTrayIcon visible similar to this:
using the following line of code (with the signal slots working):
#include "dialog.h"
#include "ui_dialog.h"
#include <QMessageBox>
#include <form.h>
Dialog::Dialog(QWidget *parent)
: QDialog(parent), ui(new Ui::Dialog)
{
ui->setupUi(this);
QIcon icon("/Users/JohnnyAppleseed/IMAGE.png");
m_ptrTrayIcon = new QSystemTrayIcon(icon );
m_ptrTrayIcon->setToolTip( tr( "Bubble Message" ) );
// m_ptrTrayIcon->setContextMenu(m_trayIconMenu);
connect(m_ptrTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
}
Dialog::~Dialog()
{
delete ui;
}
However, when I try to implement code to show the QWidget/QWindow near the QSystemTrayIcon that I have created, it fails to show up near it. It also shows up and disappears quickly as well (even if I didn't want it near the QSystemTrayIcon) using this code:
void Dialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
form fr;
fr.setWindowFlags(Qt::Popup);
fr.show();
}
For the sake of being clear, I would like to show my QWidget/QWindow just like VMWare Fusion's approach (or the clock that is found on Microsoft Windows Vista or later...)
Mac OS X / Linux
Microsoft Windows
Can some one please point out what am I doing wrong? Thanks!
To make things much simpler, download the project: http://zipshare.net/sv
UPDATE #1
Regarding the QWidget/QWindow flicking issue, vahancho advised me to move the form fr; from the void Dialog::iconActivated(QSystemTrayIcon::ActivationReason reason) function to the header of the working window. And it worked successfully all thanks to vahancho. The window now shows up, but its not near the QSystemTrayIcon yet :(
The problem is that you create you form object in the stack and it gets deleted as soon as the execution goes out of you iconActivated() slot. That is why it disappears as soon as you see it. To solve the problem you need to create your pop up in the heap.
UPDATE
In order to place you dialog near the tray icon you have to determine the tray icon position. To do that you can use QSystemTrayIcon::geometry() function. You code will look like (adjust the coordinates according to your needs):
QRect rect = m_ptrTrayIcon->geometry();
fr.move(rect.x(), rect.y());
fr.show();

Create QAction with shortcut, without inserting in menu

#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.

Creating signals and slots qt4 gui builder

Hi im brand new to c++ and trying to get my head around the concepts.
I am creating a very simple app to get going with the help of the tutorials, so im trying to do my own first try.
I'm having problems with the file.h and file.cpp the one besides main.cpp
I would like to click the button in the button box "ok" and have text come up in the text box.
Here is MainWindow.h first
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "ui_MainWindow.h"
class MainWindow: public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
public:
MainWindow(QMainWindow *parent = 0);
private slots:
//here is where im tyring to add a slot.
void on_buttonbox_buttonClicked ( QAbstractButton * );
// void on_inputSpinBox2_valueChanged(int value);
private:
Ui::MainWindow ui;
};
#endif
Next is the MainWindow.cpp
#include <QtGui>
#include "MainWindow.h"
MainWindow::MainWindow(QMainWindow *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
//This is where i would like to catch the clicked signal from the ok button and add the text to the text box.
void MainWindow::on_buttonbox_buttonClicked ( QAbstractButton * ){
ui.textEdit->setText(QString::number(16));
}
Im trying to be as simple as posible to just to get it going, it will compile but i can't get the signals and slots to talk, where am i going wrong.... remember brand new.
You have to connect your Slots to the Signals, add this into your constructor:
this->connect(this->ui.yourButton, SIGNAL(clicked()), this, SLOT(on_buttonbox_buttonClicked(QAbstractButton*)));
// ^
// |
// The name of your Button here ...
Also please see here: http://qt-project.org/doc/qt-4.8/signalsandslots.html
Edit:
MainWindow.cpp
MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent)
{
ui.setupUi(this);
// Connect Signals-Slots
this->connect(this->ui.yourButton, SIGNAL(clicked()), this, SLOT(on_buttonbox_buttonClicked(QAbstractButton*)));
}
// ...
But don't forget to change yourButton to whatever you've named yours.
Alright, you have to connect the signal to the slot somewhere. You should do this on the constructor,
connect(button, SIGNAL(clicked()), this, SLOT(on_buttonbox_buttonClicked(QAbstractButton *)));
Just remember that the slot only will be called if there is a signal connect to it. Otherwise your button won´t be able to know where to go.
The mechanism of SIGNAL and SLOT is very simple and is used to register a widget(buttons, spinbox etc..) to an event. For example "when I click that button a new window will show up."
That being said, let's see how can we register our SLOT(what to do after receiving the signal) to his SIGNAL(an event: a click, a selection, an edit of a form etc..)
QObject::connect( button , SIGNAL( click()), this , SLOT( openWindow() ))
button is the widget that will throw the signal.
SIGNAL( click()) you are telling that clicking(press and release) button an action will be performed
this is the object that declare the slot
SLOT( openWindow() ) is the method(slot) will be called clicking button
Signals and slots must have same parameters!!
So to answer your question you have to declare a slot with same parameters as the signal. click() has no parameter so you have to declare your slot as:
void on_buttonbox_buttonClicked ()
PS: as I remember there is an issue naming a slot with the prefix on. But I have to do a little search because I don't remember very well.
update: I made a little test and naming the slot with the prefix on_ gives an error message at run time QMetaObject::connectSlotsByName: No matching signal for on_ClickChangeBack() but the slot execute.

Why is the signal for the QCheckBox not emitted?

I am trying to insert in my UI a check box which can set a boolean variable from another class true or false according to its checked status. The problem is that the signal is not emitted.
The variable is defined in the header file of my 1st class (renderarea.h) as public:
bool selectionMode;
The slot is defined in the 2nd class' header file as void
protected slots:
void setSelectionMode(bool mode);
And the signal is connected to the slot in my 2nd class source file in the constructor as:
PaintWidget::PaintWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PaintWidget)
{
connect(ui->selectionModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(setSelectionMode(bool)));
}
void PaintWidget::setSelectionMode(bool mode)
{
ui->displayWidget->selectionMode = mode;
QMessageBox msgbox;
if (ui->displayWidget->selectionMode == true)
msgbox.setText("selection mode is true");
else
msgbox.setText("selection mode is false");
}
I am using the QMessageBox here only for testing reasons. But when debugging I saw that the signal is not emitted. What am I doing wrong?
You'll want to make sure a number of things are in place:
setupUi
connect succeeded
checkbox value really changed
First, I don't see where you called setupUi. You'll want to do this in the constructor:
PaintWidget::PaintWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PaintWidget)
{
ui->setupUi(this);
connect(ui->selectionModeCheckBox,
SIGNAL(toggled(bool)), this, SLOT(setSelectionMode(bool)));
}
Second, make sure that the return value of connect indicates it succeeded.
Third, I presume you're manually clicking the checkbox, but for sake of testing you could do that after the connect in your constructor:
ui->selectionModeCheckBox->setChecked(true);
Just to clarify, when you say the slot is in the header file, you do mean after the slots: label, right?
You should rather use the stateChanged() signal, emitted by the checkbox when its status changes. It gives you an integer, because checkboxes can also be tristate (but you can just use that int value as a boolean, in your case).
well,I often use the checkbox in the Dialog(settingDialog, selectionDialog,etc), so signal-slot is not need in this situation,just check the checkbox state when the "OK" button is clicked, and deal with it in the accept function.In your situation, I don't think checkbox is a good choice.