How to use QGroupBox and QCheckBoxes to one check another? - c++

I'm trying to understand how to use signals to when one QCheckBox be checked it uncheck all other checkboxes present in the same QGroupBox
class GroupBox : public QGroupBox
{
public:
GroupBox(QWidget *parent = nullptr) : QGroupBox(parent)
{
}
public slots:
void uncheck();
};
class CheckBox : public QCheckBox
{
public:
CheckBox(QWidget *parent = nullptr) : QCheckBox(parent)
{
connect(this, SIGNAL(checked()), this, SLOT(checked()));
}
public slots:
void checked()
{
qDebug() << "checked";
}
};
When I click on one of the checkboxes it didn't go to the function checked().

QCheckBox inherits from QAbstractButton
You should use clicked or stateChanged signal instead of checked.
e.q.
connect(this, SIGNAL(stateChanged(int)), this, SLOT(checked(int)));
Btw; if using a modern Qt version, you should ditch the SIGNAL and SLOTS macros and instead use the new connect() syntax that's checked at compile time.
Refer: New Signal Slot Syntax
e.p.
connect(this, &QCheckBox::clicked, this, &CheckBox::checked);

Related

How to detect that the close button of QWidget is pressed?

I create a new QWidget object and I want to know when the close button is pressed.
I have tried the following code:
pWindow = new QWidget();
connect(pWindow , SIGNAL(triggered()), this, SLOT(processCloseButtonWindowsClicked()));
but it give an error:
no signal triggered of pWindow
How to achieve this?
Cause
QWidget does not have a triggered signal.
Solution
I would suggest you to:
Subclass QWidget and reimplement QWidget::closeEvent
Check QEvent::spontaneous to differentiate between a click of the close button and the call to QWidget::close
According to your app's logic either call QWidget::closeEvent(event); to close the widget, or QEvent::ignore to leave it open
Example
I have prepared an example for you of how to implement the proposed solution:
#include <QMainWindow>
#include <QCloseEvent>
#include <QPushButton>
class FooWidget : public QWidget
{
Q_OBJECT
public:
explicit FooWidget(QWidget *parent = nullptr) :
QWidget(parent) {
auto *button = new QPushButton(tr("Close"), this);
connect(button, &QPushButton::clicked, this, &FooWidget::close);
resize(300, 200);
setWindowTitle("Foo");
}
protected:
void closeEvent(QCloseEvent *event) override {
if (event->spontaneous()) {
qDebug("The close button was clicked");
// do event->ignore();
// or QWidget::closeEvent(event);
} else {
QWidget::closeEvent(event);
}
}
};
class MainWindow : public QMainWindow
{
Q_OBJECT
FooWidget *pWindow;
public:
explicit MainWindow(QWidget *parent = nullptr) :
QMainWindow(parent),
pWindow(new FooWidget()) {
pWindow->show();
}
};
void QWidget::closeEvent(QCloseEvent *event) will be the possible way I would go with.
You can read the documentation here.
Before, check if Qt has a class for what you want to do. Maybe you want to use QDialog instead of QWidget for what you want to achieve.
The following code: suppose you want to delete the widget when the X is clicked and you just want to know when to do something.
Try connecting the signal from the base class QObject of your widget when it is Destroyed:
-Your Widget
-attribute setted to destroy your widget after X(closebotton is clicked) or the close() handler is triggered
-connect the destroyed() signal to whatever slot you want to do something before it is destroyed
pWindow = new QWidget();
pWindow->setAttribute(Qt::WA_DeleteOnClose,true);
connect(pWindow , SIGNAL(destroyed()), this,SLOT(processCloseButtonWindowsClicked()));
for more info:
https://doc.qt.io/qt-5/qwidget.html#close
https://doc.qt.io/qt-5/qobject.html#destroyed

Signal to it's own instance doesn't work

I connected the clicked(bool) event from QPushButton to a private slot mySlot() of my own Widget. But the slot is never called (I placed a breakpoint in mySlot()). I'm using c++ and Qt5.
I wrote a minimal version of my code:
MyLayout.h
class MyLayout : public QWidget
{
Q_OBJECT
public:
MyLayout(QWidget* parent = NULL);
private:
QPushButton *next;
private slots:
void mySlot();
}
MyLayout.cpp
MyLayout::MyLayout(QWidget* parent) : QWidget(parent)
{
next = new QPushButton("Next Step");
QObject::connect(next, SIGNAL(clicked(bool)), this, SLOT(mySlot()));
}
void MyLayout::mySlot() { /* do something */ }
Any ideas?
You created a parentless button and never showed it. Start by giving it parent (this), so it gets shown together with your widget:
next = new QPushButton("Next Step", this);
Then learn how to use layouts.

connect signals on a child widget slot

I have some problems with inheritance in widgets and connecting slots. I have created an abstract Widget which inherits from QWidget. Here is the prototype :
class WidgetParams : public QWidget
{
Q_OBJECT
public:
explicit WidgetParams(QWidget *parent = 0) : QWidget(parent){}
virtual bool paramChanged() = 0;
protected:
bool paramsChanged;
};
Then I created derivated class from WidgetParams, for example WidgetParamsWindows:
class WidgetParamsWindows : public WidgetParams
{
public:
explicit WidgetParamsWindows(QWidget *parent = 0);
virtual bool paramChanged(){return paramsChanged;}
private:
QFormLayout *layout;
QSpinBox *svertical;
QSpinBox *shorizontal;
signals:
public slots:
void changeSomeParam(int value);
};
In WidgetParamsWindows, I have some QSpinBox, QPushButton etc. to adjust the params.
I connect the QSpinBox in WidetParamsWindows like this :
connect(spinbox,SIGNAL(valueChanged(int)),this,SLOT(changeSomeParam(int));
After that, I created a WidgetParamsWindows and put It in a list of WidgetParams, in order to show the correct WidgetParams when the user clicks on it.
But when I tried to change the value in the QSpinBox, nothing change and I have the following message in the console :
QObject::connect: No such slot WidgetParams::changeSomeParam(int)
I don't know why the parent Widget takes the slot, instead of WidgetParamsWindows, do you have any ideas?
There is no Q_OBJECT macro in WidgetParamsWindow, so moc doesn't resolve slot macros, try to add Q_OBJECT in WidgetParamsWindow

How to connect a signal from a thread to a slot?

What I simply want to do is connect a signal inside a thread to a slot in the main thread to handle UI changes.
This is basically the current state of my thread, nothing fancy but it's just for testing purposes atm:
// synchronizer.h
class Synchronizer : public QObject
{
Q_OBJECT
public:
Synchronizer();
signals:
void newConnection(std::wstring id);
private:
QTimer timer;
private slots:
void synchronize();
}
// synchronizer.cpp
Synchronizer::Synchronizer()
{
connect(&timer, SIGNAL(timeout()), this, SLOT(synchronize()));
timer.start();
}
void Synchronizer::synchronize()
{
emit newConnection(L"test");
}
And here's how my MainWindow looks:
// mainwindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
Synchronizer synchronizer;
private slots:
void addConnection(std::wstring id);
}
// mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(&synchronizer, SIGNAL(newConnection(std::wstring)),
this, SLOT(addConnection(std::wstring)));
QThread *thread = new QThread;
// The problems starts here?
synchronizer.moveToThread(thread);
thread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::addConnection(std::wstring id)
{
// Add a new connection to QListWidget
ui->connectionList(QString::fromStdWString(id));
}
If I remove there lines:
synchronizer.moveToThread(thread);
thread->start();
everything seems to work as expected, that is a new item is added every second to a QListWidget but as soon as I move the synchronizer object to thread it simply stops working. I'd presume it has something to do with the connect context but I'm not really sure how something like this should be achieved as I'm quite new to Qt.
It seems that the in this case was simply the fact that I am using std::wstring as an argument in the signal without registering the type first and after adding the following line qRegisterMetaType<std::wstring>("std::wstring"); to the code, everything worked as expected.
If I would have read the output console more carefully I would have solved the problem without too much hassle as it was clearly stated that:
QObject::connect: Cannot queue arguments of type 'std::wstring'
So simply speaking, read the compiler output and don't be stupid like me :)

Qt slot connection not working under child Dialog

I have a text editor like program which is a QMainWindow inherited class. There, when I click Find, the connection,
connect(actionFind,SIGNAL(triggered()),this,SLOT(actionFindTriggered()));
Activates. And the defination of that function is
void MainWindow::actionFindTriggered() {
new Find(this);
}
My Find class is
class Find : public QDialog, public Ui::Dialog
{
public:
Find(QWidget *parent=0);
private:
Ui::Dialog *ui;
public slots:
void buttonFindTriggered();
};
And the definition is
Find::Find(QWidget *parent)
: QDialog(parent)
{
ui = new Ui::Dialog;
ui->setupUi(this);
show();
this->
connect(ui->buttonClose, SIGNAL(clicked()), this, SLOT(close()));
connect(ui->buttonFind, SIGNAL(clicked()), this, SLOT(buttonFindTrigddgered()));
}
void Find::buttonFindTriggered() {
qDebug() << "FIND ACTIVATED";
}
What is the problem
When I clicked find from the main window, find window works successfully but could not make the connection. And I get the following msg on console,
Object::connect: No such slot QDialog::buttonFindTriggered() // Edited
Object::connect: (sender name: 'buttonFind')
Object::connect: (receiver name: 'Dialog')
Edited due to a typo...!
You forgot the Q_OBJECT macro.
Also - consider using this notation for getting slot auto-connection (setupUI will automatically connect these slot for you).
void on_buttonFind_clicked();
void on_buttonClose_clicked();
As the error message states, it can't find the slot:
buttonFindTrigddgered()
because it should be:
buttonFindTriggered()