Creating signals and slots qt4 gui builder - c++

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.

Related

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.

hide QWidget from a different QWidget

I have a MainWindow with two widgets, buttonsWidget and infoWidget.
I'm trying to to hide infoWidget after clicking a button within buttonsWidget (and ultimately show a different widget).
I've tried:
mainwindow.h
public:
void hideInfo();
mainwindow.cpp
void MainWindow::hideInfo()
{
ui->info->hide();
}
buttonsWidget.cpp
void buttonsWidget::on_timingButton_clicked()
{
MainWindow::hideInfo();
//Then will do something to show 'timingWidget'..
}
Many thanks
You should use Signals and Slots for this.
Add a signal in the buttonsWidget.h.
signals:
void hideInfoSignal();
In the main function, connect the button signal with the mainwindow method hideInfo().
QObject::connect(this->info, SIGNAL(hideInfoSignal),this, SLOT(hideInfo));
I haven't tested this, because I dont have Qt on this machine, but that should work, with possible minor modifications. If any errors appear, let me know and I will help. Also, read the signals and slots documentation.

QT Creator Main window - how to change the interface for each element from the menu?

I am new to QT Creator. I did create a menu: Login || Open. When login is clicked I would like to see a line edit and a press button. When Open is clicked I would like to see a picture in the window. Can I change the interface of the same window depending on what I click in the menu bar? How can I do that?
I did something similar to this - an app with several major areas, toggled by an icon bar at the top.
I used a QStackWidget to stack the different application areas on top of each other, a set of QActions that I created using the designer, and a QActionGroup to implement the toggling.
When the actions are marked as "checkable" and grouped in a QActionGroup, theQToolBar only lets one be active at the time.
Here's a simplified extract of my code:
// MyApp.h
#include <QMainWindow>
class QAction;
class QActionGroup;
namespace Ui {
class MyApp;
}
class MyApp: public QMainWindow
{
Q_OBJECT
public:
explicit MyApp(QWidget *parent = 0);
~MyApp();
public slots:
void showSection(QAction* a);
private:
Ui::MyApp *ui;
QActionGroup* sections;
};
//MyApp.cpp
#include "structureapp.h"
#include "ui_structureapp.h"
#include <QActionGroup>
MyApp::MyApp(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MyApp),
sections(new QActionGroup(this)),
{
ui->setupUi(this);
/* Populate section list */
/* Page indices for the stack widget*/
ui->actionSectionOne-> setData(0);
ui->actionSectionTwo-> setData(1);
ui->actionSectionThree-> setData(2);
sections->addAction(ui->actionSectionOne);
sections->addAction(ui->actionSectionTwo);
sections->addAction(ui->actionSectionThree);
ui->mainToolBar->addSeparator();
connect(sections, SIGNAL(triggered(QAction*)), this, SLOT(showSection(QAction*)));
/* Show the default section */
ui->actionContentSection->trigger();
}
MyApp::~MyApp()
{
delete ui;
}
void MyApp::showSection(QAction *a)
{
ui->mainArea->setCurrentIndex(a->data().toInt());
}
Yes, you can. As I explained earlier, each menu entry is a signal, and that's connected to a slot. With two different menu entries, you have two signals, and you'd connect them to two different slots. So, you could name your first slot onLogin, and the second slot onOpen. (It helps to choose descriptive names, so you'll understand your program when you come back on mondays).
Now, it the slot onLogin, you put the code for login. In the slot onOpen, you put the other code. But do consider what happens if you click the two menu entries one after another. Should that even be possible? If not, you may need another solution. It's quite common to use a QDialog for a login. When a dialog is active, you can't use the menu of the main application, so you can't accidentily hit onOpen when you're busy with the login.

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.

Signals and Slots with Qtoolbutton

I have created a ToolButton with my qt designer and Im trying to connect it to a slot.
I wrote this
connect(ui->toolButton_addfiles, SIGNAL(triggered()), this, SLOT(changeDirectory()));
Im able to run the program but when I press the button I see the following log into my qt Application Output :
Object::connect: No such signal QToolButton::triggered() in ../RightDoneIt/rightdoneit.cpp:10
Object::connect: (sender name: 'toolButton_addfiles')
Object::connect: (receiver name: 'RightDoneIt')
If I change the toolButton_addfile to some action like (actionChange_addfile) it will work fine.
How can I make this connection work ?
As the error says, there's no signal triggered() but triggered(QAction*) in the QToolButton.
Edit
In the connect function you must have the signal signature like triggered(QAction*) since QToolButton class has no signal triggered() (with no parameter) declared
You could use the auto-connection process of Qt.
In the class referencing your UI, create a slot called :
on_toolButton_addfiles_clicked();
Exemple :
See : A Dialog With Auto-Connect
class ImageDialog : public QDialog, private Ui::ImageDialog
{
Q_OBJECT
public:
ImageDialog(QWidget *parent = 0);
private slots:
void on_okButton_clicked();
};
Hope this helps !
Edit : No triggered signals in qAbstractButton. See http://doc.qt.nokia.com/4.7/qabstractbutton.html
QToolButton() has the signal method triggered(QAction *), this signal is to be addressed if triggering of the related QAction connected to the QToolbutton is of interest. At the same time QToolButton is inherited from QAbstractButton(), which has the toggled(bool checked) signal. If you want to catch the signal triggered by pressing/unpressing the tool button, you may do as following:
auto toolbutton = new QToolButton(this);
connect(toolbutton , &QAbstractButton::toggled, this, []() { // your code });
Alternatively (I have not checked if this solution works), you may define explicitly, what signal to be caught
connect(toolbutton , qOverload<bool>(&QToolButton::toggled), this, [](bool val) { // your code});
I'm guessing you're creating a QAction, adding it to the QToolButton and trying to connect it to a slot in your own class?
You can connect your slot to either the QToolButton::triggered(QAction*) signal or directly to the QAction::triggered() signal. Either way, the QAction must be added to the QToolButton through QWidget::addAction(QAction*), the slot's method signature must match the signal's signature, and the connect invocation must include the signal/slot parameters, not just the names of the signal and slot.