I have difficulty connecting to SLOTs defined in a different class. I have 2 classes - Computations and MainWindow. MainWindow is supposed to handle the GUI part of the program only and Computations handles the calculations. I am creating a calculator.
Basically, I want to understand how I can connect to SLOTs in the Computations Class from the MainWindow Class.
I guess you already checked the Qt Signals & Slots page. To implement what you want you need to have an instance of your class in the other one.
So for example in your MainWindow class, you can include the Computations class and create a member variable of it:
#include "computations.h"
class MainWindow : public QMainWindow
{
Q_ObBJECT
public:
//..
private:
Computations *_computation;
};
and then in the constructor of MainWindow after initializing the _computation object (_computation = new Computations();) you do the connections like this (works for Qt5):
QObject::connect(_computation, &Computations::somethingHappened, this, &MainWindow::doSomeGuiStuff);
QObject::connect(this, &MainWindow::guiThingHappened, _computation, &Computations::doSomeComputation);
depending on which way it should go.
I hope this helps.
This is another version how to use, I think can be easier to understand for beginners
You need define signal and slots in your classes.
Add to header of your class, for example signals to MainWindow, slots to Computations
public slots:
void something();
signals:
void something_happend();
Then, in anywhere, where you want use it, in your example in mainwindow.cpp, you need to connect signal and slot. Do this by QObject::connect :
QObject::connect(who_emit,SIGNAL(what_signal),who_receive,SLOT(what_slot))
Example:
mainwindow.h
signals:
void something_happend();
computations.h
public slots:
void something_happend();
mainwindow.cpp
Computations *c = new Computations(this);
QObject::connect(this,SIGNAL(something_happend()),c,SLOT(something()));
If you want to pass some arguments, SIGNAL and SLOT that you want to connect need have same types of arguments:
public slots:
void something(int c);
signals:
void something_happend(int c);
QObject::connect(this,SIGNAL(something_happend(int)),c,SLOT(something(int)));
Such connections belong at a level where both the UI and the controller (computation object) are available. Thus, either in the body of main, or in a class that composes that various elements of the application at a high level (such a class usually shouldn't derive from QApplication, though).
It is almost always too tight of a coupling if the UI class knows of the existence of the computation object, or is somehow tied to its details. I usually design the UI to have an interface composed of signals and slots of as generic a nature as practicable, and then tie it to one or more controller objects via signal/slot connections. I also leverage the property system to expose UI-relevant properties in a generic manner, often using viewmodel objects to interface a UI-agnostic controller to a concrete kind of a UI.
In your case, I'd suggest that neither MainWindow know of Computations, nor vice versa:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Computations comp;
MainWindow ui;
QObject::connect(&comp, ..., &ui, ...);
/* more connections here */
ui.show();
return app.exec();
}
For more concrete examples, see answer #1 or answer #2.
you need slots and signals because those work together, like this:
your file.h
public slots:
void start();
signals:
void levelChanged(int level);
implementing:
void MainBoard::start()
{
isStarted = true;
clearBoard();
emit levelChanged(1);
}
now you need to link a button
startButton = new QPushButton(tr("&Start"));
startButton->setFocusPolicy(Qt::NoFocus);
connect(startButton, &QPushButton::clicked, board, &MainBoard::start);
Related
the runnable project is here:
enter link description here
I sincerely glad to have your detail answers to solve this, but I am still confusing on this issue:
case 1: changing socket_session as a member variable of mainwindow
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
SocketThread* socket_session;
private:
...
But this is not the solution to access setFlag, even after I change the `Form1::on_qpushButton__set_white_level_0_clicked()' function like this:
void Form1::on_qpushButton__set_white_level_0_clicked() {
qDebug() <<"clicked()";
socket_session->setThreadFlag(true);
}
Still it doesn't make sense because form1 instance doesn't have "the" instance of socket_thread which has been instantiated from mainwindow.
There's a solution I think is making another class that includes all instances that I want to use from inside of mainwindow but I don't think that is a good one because I am using thread and accessing a global big instance class that includes all of them to be "shared" is not a good idea for someone like me.
#include <form1.h>
#include <ui_form1.h>
#include "socketthread.h"
Form1::Form1(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form1) {
ui->setupUi(this);
}
Form1::~Form1() {
delete ui;
}
void Form1::on_qpushButton__set_white_level_0_clicked() {
qDebug() <<"clicked()";
socket_session->setThreadFlag(true);
}
enter image description here
I know I am lack of understanding about this but, do I wanna make something nobody does...? I think everyone wants to separate all objects and their methods clearly and communicate via signals or calling functions from delivered object instances...
case 2: ... let me try how you suggested make possible first...
I can read C++ code and overall structure, but I don't know why I have to struggle with this, so please help me, dear Guru.
On socketthread.h :
class SocketThread : public QThread {
Q_OBJECT
public:
QTcpSocket *socket_session;
SocketThread();
~SocketThread(){}
bool connectToServer(QString, int);
void sendData(const char*, int, int);
void run(void);
private:
QString message;
volatile bool threadFlag;
signals:
void changedThreadFlag(void);
void changedMessageStr(void);
void setThreadFlag(bool);
void setMessageStr(QString);
private slots:
void setStr(QString);
void setFlag(bool);
void socketError(QAbstractSocket::SocketError);
};
And its implementation is...
SocketThread::SocketThread() {
socket_session = NULL;
threadFlag = false;
message = "NULL";
connect(this, SIGNAL(setThreadFlag(bool)), this, SLOT(setFlag(bool)));
}
...
void SocketThread::setStr(QString str) {
message = str;
}
void SocketThread::setFlag(bool flag) {
threadFlag = flag;
}
void SocketThread::run() {
while(true) {
if(threadFlag) {
QThread::msleep(100);
qDebug() << message;
} else
break;
}
qDebug() << "loop ended";
}
And I have one form which has a button, and I put a clicked() slot of it like this...
void Form1::on_qpushButton__set_white_level_0_clicked() {
qDebug() <<"clicked()";
--how can I emit the signal of the one of socketthread from here??
}
Now, the mainwindow is like this:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
QString addr_server = "223.194.32.106";
int port = 11000;
SocketThread* socket_session = new SocketThread();
socket_session->connectToServer(addr_server, port);
ui->setupUi(this);
Form1* form1;
form1 = new Form1();
ui->stackedWidget_mainwindow->addWidget(form1);
ui->stackedWidget_mainwindow->setCurrentWidget(form1);
socket_session->run();
...
I just simply want to emit the signal setThreadFlag of the socketthread from inside of QPushbutton_clicked() slot.
Once the socket_session->run() started, I need to change the threadFlag by clicking the button by emitting setThreadFlag() of one's from the running thread. And I just stuck in here.
Does it possible even?
Or am I doing this all wrong from the beginning?
As mentioned in this post:
"Emitting a signal" == "calling a function"
So all you really have to do is call the signal function, and all connected slots should be called.
This of course means that the Form1 object needs a pointer to the thread object, i.e. it needs a copy of socket_session. Then you can simply call the signal on the object
socket_session->setThreadFlag(your_flag);
Of course, if the Form1 have a copy of the socket_session pointer, it might as well call setFlag directly, if it was public.
I just simply want to emit the signal setThreadFlag of the socketthread from inside of QPushbutton_clicked() slot.
No signal is needed – just call the function.
void Form1::on_qpushButton__set_white_level_0_clicked() {
qDebug() <<"clicked()";
// --how can I emit the signal of the one of socketthread from here??
// E.g. this way:
socket_session->setThreadFlag(true);
}
To make this possible, another fix is needed:
socket_session is a local variable in OP's exposed code.
To make it "persistent", it has to become e.g. a member variable.
So, the constructor MainWindow::MainWindow() has to be changed:
// Nope: SocketThread* socket_session = new SocketThread();
// Instead:
socket_session = new SocketThread();
and SocketThread* socket_session; has to be added to member variables of class MainWindow.
To make it accessible in Form1, it has to be passed to Form1 as well.
This could be done e.g. by making it a member variable in Form1 also which is initialized with a constructor argument (or set from MainWindow afterwards).
(I must admit that I never have used the Qt UI builder QtDesigner but build all my UIs by C++ code exclusively.)
But, now, another fix is necessary:
volatile doesn't make a variable suitable for interthread communication.
(This was used in ancient times before multi-threading started to be supported by C++11.)
However, this is wrong: Is volatile useful with threads?
An appropriate fix would be to use std::atomic instead:
// Wrong for interthread-com.
//volatile bool threadFlag;
// Correct:
std::atomic<bool> threadFlag; // #include <atomic> needed
FYI: SO: Multithreading program stuck in optimized mode but runs normally in -O0
And, finally, in SocketThread::SocketThread():
connect(this, SIGNAL(setThreadFlag(bool)), this, SLOT(setFlag(bool)));
is not necessary in this case.
SocketThread::setThreadFlag() could call SocketThread::setFlag() directly, or even write threadFlag itself:
void setThreadFlag(bool flag) { threadFlag = flag; }
As I (recommended to) make threadFlag atomic, it can be accessed from any thread without causing a data race.
Update:
After OP has updated the question:
I just simply want to emit the signal setThreadFlag of the socketthread from inside of QPushbutton_clicked() slot.
The button (created from UI Form1) can be connected in the MainWindow as well (without using any method of Form1):
QObject::connect(form1->button1, &QPushButton::clicked,
socket_session, &SocketThread::setThreadFlag,
Qt::QueuedConnection);
Notes:
About form1->button1, I'm not quite sure.
I noticed that widgets in UI generated forms can be accessed this way but I don't know the exact details (as I never used the Qt UI builder on my own).
I used the Qt5 style of QObject::connect().
This is what I would recommend in any case.
The Qt5 style is verified at compile time. –
Wrong connections are detected by the C++ type checking.
Additionally, any function with matching signature can be used – no explicit exposure of slots is anymore necessary.
Even conversion of non-matching signature or adding additional parameters becomes possible by using C++ lambdas which are supported as well.
Qt: Differences between String-Based and Functor-Based Connections
It is possible to connect signals and slots of distinct threads.
I used Qt::QueuedConnection to remark this as interthread communication.
(However, I roughly remember that Qt might be able to detect it itself.
See the doc. for Qt::AutoConnection which is the default.
Further reading: Qt: Signals & Slots
Btw. using the Qt signals for inter-thread communication would exclude the necissity to make SocketThread::threadFlag() atomic. It could become a simple plain bool threadFlag; instead. The slot SocketThread::setThreadFlag() is called in the Qt event loop of QThread, in this case.
So i am looking to make our own generic inherited checkbox class that will be able to take in some values in its constructor and pop out a widget that is fully connected to our model in the manner we need.
Currently we do something like this within our view
connect(checkboxWidget, &QCheckbox::Clicked, this, &VMyView::Signal);
Which emits the Signal from VMyView when the checkbox is clicked.
If i wanted to pass that signal as a parameter into my new inherited class to be hooked up in its own connect statement, how would I do so?
Research has shown me i can pass a const char* but i get compilation errors that the signal/slot do not match.
Example
CheckBox(View myView, const char* signal)
{
connect(this, &QCheckBox::Clicked, myView, signal);
}
Returns an error that Signal and slot arguments are not compatible. Ive also tried SIGNAL(signal) with the same result.
The solution ended up being fairly simple in the end
Instead of using this from within my View
connect(pCheckbox, &QCheckBox::clicked, this, &MyView::Signal);
I use
connect(this, &QCheckBox::clicked, View, signal);
Where signal and comes into my function via a function pointer
MyCheckBox::MyCheckBox(QWidget* parent, MyView* View, void(MyView::*signal)(bool))
The key takeaway is
void(MyView::*signal)(bool)
is equal too
&MyView::Signal
I think the major issue here is that signals are not static member functions. Thus they require a pointer to an instance of the class to be called correctly. So you cannot just pass in things like &VMyView::Signal, as there's no corresponding this pointer attached to the function. (This is why most of the QObject::connect() overloads require an instance to the sender/receiver objects.)
One way to solve this is to create a function object, which contains both the member function pointer and the pointer to the object on which to call it. This can be passed to the QObject::connect() function just fine.
Here's an example:
// objects.h
#include <QtCore>
class Receiver : public QObject
{
Q_OBJECT
public:
Receiver( QObject *parent = nullptr)
: QObject(parent)
{
}
~Receiver() { }
signals:
void sig(void);
};
class Sender : public QObject
{
Q_OBJECT
public:
Sender(std::function<void(void)> &bound_signal, QObject *parent = nullptr)
: QObject(parent)
{
// automatically emit `Sender::sig` on a timer, for testing.
timer = new QTimer(this);
timer->setInterval(1000);
QObject::connect(timer, &QTimer::timeout, this, &Sender::sig);
QObject::connect(this, &Sender::sig, bound_signal);
timer->start();
}
~Sender() { }
signals:
void sig(void);
private:
QTimer *timer;
};
And then a main function:
// main.cc
#include <QtCore>
#include "objects.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Receiver receiver; // object to receive the signal
// Bind the receiver's signal to the instance of the class
std::function<void(void)> signal = std::bind(&Receiver::sig, &receiver);
// Create a Sender, which will connect its own signal to the
// given bound signal
Sender sender(signal);
QObject::connect(&receiver, &Receiver::sig,
[]() -> void { qDebug() << "received"; });
return app.exec();
}
So, in your case, the Receiver and its signal would be replaced by VMyView and the signals you want to chain, and Sender would be the custom checkbox class you've implemented. Then in the constructor of the checkbox class, connect whatever signals you want to the given bound signals. You can also pass in a list of bound signals, e.g., std::list<std::function<void(void)>> &bound_signals.
I have to say, though, I'm not sure what this buys you. You'll need to write the connection logic somewhere, and I don't see why it needs to be in the constructor of the checkbox class. Wherever the checkbox and the VMyView class are created and used, that seems like a better place to put the connection code. It's more obvious, less convoluted, and there's better separation of concerns. The checkbox class shouldn't have to know or care what signals/slots its connected to. The application logic (i.e., where the objects are used) should define how the objects interact with one another.
What is the difference between a slot (a method declared in slots section) and a method in Qt (a method declared with Q_INVOKABLE keyword)? They both can be invoked using QMetaObject::invokeMethod, they are both accepted when connecting to a slot using SLOT macro, however when getting type of metamethod it can be returned either QMetaMethod::Method or QMetaMethod::Slot, so it seems that there is some difference for Qt?
The only difference is whether the method is listed as a slot or as not-a-slot in the class's metadata. In both Qt 4 and Qt 5, connection to either a slot or an invokable succeeds:
#include <QObject>
struct Test : public QObject {
Q_SLOT void slot() {}
Q_INVOKABLE void invokable() {}
Q_OBJECT
};
int main() {
Test test;
auto c1 = QObject::connect(&test, SIGNAL(destroyed(QObject*)), &test, SLOT(slot()));
auto c2 = QObject::connect(&test, SIGNAL(destroyed(QObject*)), &test, SLOT(invokable()));
Q_ASSERT(c1);
Q_ASSERT(c2);
}
#include "main.moc"
It's up to the user to decide how the difference between a slot and an invokable is interpreted. E.g. if you're exposing the slot list to the user in some way, you won't be exposing the invokable method list unless you choose to do so.
The practical differences I know of:
Q_INVOKABLE can have a return value, slot cannot.
Q_INVOKABLE is called on the GUI thread, and blocks the GUI thread. slot's thread depends on which thread the QObject was created on, and therefore can be non-blocking.
So my rule of thumb is, use slot if there are no return values, otherwise use Q_INVOKABLE.
I have a small problem. I want run function in MainWindow from AnotherWindow. I can't set connect() for it.
Main class: MainWindow
Other form: AnotherWindow
Function in main class: setVariable(QString)
Function in other form: btnClicked()
I have now connected button signal clicked():
// In AnotherWindow.cpp
connect(ui->btnOK, SIGNAL(clicked()), this, SLOT(btnOkClicked()));
// Function in same file
void interfaceWindow::btnOkClicked() {
/* Some actions - emit signal? */
this->close();
}
btnOkClicked() are declared as private slot.
// In MainWindow.cpp
void MainWindow::setVariable(QString _var) {
this->var = _var;
}
setVariable(QString) are declared as public slot.
How I can send variable from AnotherForm (from btnOkClicked() function) to MainWindow (setVariable(QString) function) ? How and where I must send signal and make connection?
I readed about signals and slots, but my code don't work - I don't paste it here because it's terrible :)
Any help for Qt newbie?
You need to have an reference of AnotherWindow in MainWindow OR vice versa. Then you need the following things:
// AnotherWindow.h
signals:
void buttonOkClickedSignal(QString var);
// AnotherWindow.cpp
void interfaceWindow::btnOkClicked() {
emit buttonOkClickedSignal("The button got clicked!");
this->close();
}
Next step varies based on whether MainWindow has reference to AnotherWindow or vice versa. You can either:
// AnotherWindow.cpp
connect(this, SIGNAL(buttonOkClickedSignal(QString), &mainWindow, SLOT(setVariable(QString)));
or:
// MainWindow.cpp
connect(&anotherWindow, SIGNAL(buttonOkClickedSignal(QString), this, (SLOT(setVariable(QString)));
If you are invoking the slot through signal it shouldn't matter whether it's private or public (see Qt Documentation).
Hope this helps.
I'm not entirely sure I understand your question, but let me try.
You want to be able to fire a slot in another class. There are a few ways you can do that.
Declare one as a friend class to the other. Then they can see the protected and private variables/memebers
It is possible to make slots static so you can call them without a class object.
For example,
class MainWindow {
private slot:
void setVariable(QString);
}
class AnotherWindow {
friend class MainWindow;
MainWindow *window;
public:
AnotherWindow() {
connect(this, SIGNAL(fire(QString)), window, SLOT(setVariable(QString)));
}
signals:
void fire(QString);
public slots:
void onButtonClicked() {
emit fire(QString);
}
}
The previous is pseudocode so don't expect it to compile. I think this is what you want. Basically since your slot is private on MainWindow you need to make it a friend. To connect, it needs to be a member. Then when the onButtonClicked slot is evoked, then it fire()s the setVarialbe() slot.
Here is a simple code for your another window:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget * parent = 0)
{
okBtn = new QPushButton ("I am Ok!");
MyData = "";
connect(okBtn ,SIGNAL(clicked()),this,SLOT(OnOk()));
}
~MyWidget();
private:
QString MyData;
QPushButton * okBtn;
//something that modify string MyData
signals:
void MyDataSignal(QString);
//Internal slot that emits signal with proper data
private slots:
void OnOk()
{
if(MyData!="")
{
emit MyDataSignal(MyData);
}
}
};
Now in MainWindow create an object of MyWidget (suppose myWid)and connect it to slot
connect(myWid, SIGNAL(MyDataSignal(QString)),this,SLOT(OnMyWidOkClicked(QString)));
the signal will pass string to slot.
While making signals and slots keep in mind following points:
To connect a signal to a slot (or to another signal), they must have the same parameter
Parameters should be in the same order in both signal and slot.
if a signal has more parameters than the slot it is connected to, the additional parameters are simply ignored but opposite is not possible.
If you will connect a signal that have unmatched parameters to slot then no compile time error will occur but at run time command window will show a warning that signal/slot/connection does not exist.
I'm relatively new to Qt; I'm writing a small program and I don't want to get into making my own classes for each widget and such. So far I haven't had many difficulties, but I'm slightly confused about signals and slots. I want to make a signal that triggers when a user types into a text box (QLineEdit) and presses enter. I would prefer the slot to be a function that accepts the text inputted by the user.
So far I've come up with this:
textBox.connect(&textBox,SIGNAL(textBox.returnPressed()),/*What to put here?*/,processText(/*Here?*/))
I apologize if this piece of code is terribly wrong; as I said I'm relatively new to Qt.
Help would be very much appreciated.
Signals and slots must be methods of a QObject (/QObject subclass). You can't use free functions as slots. "Minimal OOP" here probably would mean QObject singleton(s) containing the slots.
Also a signal with signature (A, B, C) can only be connected to slots with signatures (), (A), (A, B), (A, B, C), i.e. one can discard/ignore trailing arguments. A slot cannot have more/other arguments than the signal, nor can you bind slot arguments to a certain value when connecting (Where QSignalMapper covers the most common use case I think).
Sadly, I don't think there is a way to achieve this without inheritance - if you want the text to go with the signal or some custom handling to be done in the slot that is called.
If not, you can just use the "returnPressed" signal emitted from the QLineEdit and some pre-existing slot I couldn't possibly know.
Here's my solution using inheritance.
To make your own slot, you need to make an inherited class. Inherit it from Qobject, directly or indirectly.
//myClass.h
#ifndef myclass_h_
#define myclass_h_
#include <QObject>
class myClass: public QObject
{
// important
Q_OBJECT;
....
public slots:
void takeText(QString p_value);
};
#endif
And to get a signal like that from a QLineEdit, you need something custom as well
//myLineEdit.h
#ifndef mylineedit_h_
#define mylineedit_h_
#include <QLineEdit>
class myLineEdit: public QLineEdit
{
// important
Q_OBJECT;
....
public slots:
void handleReturnPressed();
signals:
void newText(QString p_value);
};
#endif
And then do these
myLineEdit::myLineEdit()
{
connect(this, returnPressed(),
this, handleReturnPressed());
}
void myLineEdit::handleReturnPressed()
{
emit(newText(text());
}
After this, create a myClass object, and connect the signal to it.
myClass * thing = new myClass();
myLineEdit* lineEdit = new myLineEdit();
connect(lineEdit, SIGNAL(newText(QString),
things, SLOT(takeText(QString));