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.
Related
I need to know when a QGraphicItem is selected from my Scene. I'm using the signal from the method selectionChange() but this does nothing. This my code:
scene.h
class Scene : public QGraphicsScene{
public:
Scene(QGraphicsScene *scene = 0);
~Scene();
private slots:
void test();
};
scene.cpp
Scene::Scene(QGraphicsScene* scene):QGraphicsScene(scene)
{
connect(this, SIGNAL(QGraphicsScene::selectionChanged()), this, SLOT(test()));
}
void Scene::test() {
qDebug() << "I'm here ";
}
I suppose that the problem is that my scene inherits from QGraphicScene, or that it's a bad idea define the connection in the constructor.
SIGNAL and SLOT are macros and thus text-based processing, which makes them quite picky. It's generally a good idea to assert that all your connections succeed. In your case, the problem is the extraneous qualification. Drop it:
connect(this, SIGNAL(selectionChanged()), this, SLOT(test()));
As mentioned by #Angew, the problem is in the text passed to the SIGNAL macro.
If you're using Qt 5, the preferred method would be to use the newer connection syntax, which benefits from compile time error checking
connect(this, &GraphicsScene::SelectionChanged, this, &Scene::Test);
This connection method uses addresses of functions, which has the additional benefit of being able to connect to functions that haven't been declared as a SLOT. However, it may be desirable to still define slots, as discussed here.
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.
I have two classes A and B, here is a snippet in B.h:
#include "A.h"
class B : public QDialog
{
Q_OBJECT
public:
void do_something();
private:
A *a;
}
and in B.cpp:
B::B(QWidget *parent) :
QDialog(parent),
ui(new Ui::B)
{
a = new A();
a.show();
}
So what should I do if I want to call do_something() when the ui of A is closed (by pressing Alt-F4, for example) ? Seems the way of signal-slot cannot apply here.
Thanks a lot !
Modify class A to emit signal when closed
If modifying the A widget is option, add a signal to it and override closeEvent or hideEvent and emit the new signal there. This is robust and you have complete control on what happens. However, rest of the answer is for case where, for whaever reason, you are unable or unwilling to mess with A and want a solution in class B.
Use the Qt signal for QObject deletion
If you can set Qt::WA_DeleteOnClose attribute on A, then simple way is to make B::doSomething() (note the common Qt method naming convention) a slot and connect destroyed signal of A instance to that.
B::B(QWidget *parent) : QDialog(parent), ui(new Ui::B)
{
a = new A();
a->setAttribute(Qt::WA_DeleteOnClose);
connect(a, SIGNAL(destroyed(QObject*)), SLOT(doSomething()));
a.show();
}
Of course this works even if you delete a; explicitly, and not automatically with the attribute.
Note: In this case, when the object may get deleted whenever, you should really use QPointer for the a pointer, to avoid accidentally referencing a dangling pointer.
Use Qt event filter
If you don't want to have the A instance deleted when it is closed (and re-created if it is needed again), then other way is to install event filter on the A instance, and detect the closeEvent. This has the potential problem, that the widget can reject the close event, and in any case doSomething is called before the closing. If this is a problem, it can be solved by using QMetaObject::invokeMethod static method to delay the doSomething (it must be slot or invokable method for this!) call to happen after close event is over and program returns to event loop. Then in doSomething check if a is really hidden. Instead of QEvent::Close, detecting QEvent::Hide might work well, too.
To implement this, override the virtual eventFilter method in B, something like this:
bool B::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::Close) { //or QEvent::Hide maybe
qDebug("QCloseEvent!");
// check that object is indeed this->a before calling this->doSomething()
if (qobject_cast<QObject *>(a) == obj) {
doSomething();
//alternative, make doSomething to be called later from event loop:
//QMetaObject::invokeMethod(this, "doSomething", Qt::QueuedConnection);
} else {
qDebug("...but the object is not what is expected, a bug?");
}
// do not block the event, just detect it
}
// proceed with standard event processing
return QObject::eventFilter(obj, event);
}
Then start listening events of an A instance with installEventFilter, something like:
B::B(QWidget *parent) : QDialog(parent), ui(new Ui::B)
{
a = new A();
installEventFilter(a);
a.show();
}
If you can't use a modal window (or dialog) than you have a little more work, you'll need to subclass QWidget (or QDialog or other QWidget derived class, whatever you need) and override QWidget::closeEvent (for class A) and from here call a method of the parent (i suppose a will be a child of this in your code: a = new A(this);) or code your own signal/slot.
And if you decide to use a modal dialog, the code becomes simpler, see example code in the QDialog's documentation.
I'm trying to find out why my app crashes for the whole day. A picture worth thousands of words, so take a look at this code. Header:
class SandboxedAppStat : public QObject
{
Q_OBJECT
private slots:
void pidsTimerTimeout();
public:
QTimer m_PidsTimer;
SandboxedAppStat(QObject *parent = NULL);
};
class SandboxedApp : public QObject
{
Q_OBJECT
private:
static SandboxedAppStat SandboxedAppStat1;
};
Implementation:
void SandboxedAppStat::pidsTimerTimeout()
{
qDebug() << "whatever";
}
SandboxedAppStat::SandboxedAppStat(QObject *parent)
: QObject(parent)
{
bool b = QObject::connect(&m_PidsTimer, SIGNAL(timeout()),
this, SLOT(pidsTimerTimeout()));
m_PidsTimer.start(500);
}
SandboxedAppStat SandboxedApp::SandboxedAppStat1;
Actually what I'm trying to do, is to simulate static constructor behavior in C++. I want
QObject::connect(&m_PidsTimer, SIGNAL(timeout()),
this, SLOT(pidsTimerTimeout()));
m_PidsTimer.start(500);
to be called as soon as the static member SandboxedAppStat1 initializes. That's why the code shown above is in the constructor of SandboxedAppStat.
However, my problem is that when I run the program, it crashes as soon as it reaches the line connect(&m_PidsTimer, SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));
with error code c0000005 (access violation I guess).
here's the screenshot http://dl.dropbox.com/u/3055964/Untitled.gif
If I declare SandboxedAppStat as a non static variable, then there is no crash and no errors. everything works fine.
First I thought that crash reason could be the fact that, static members are initialized too early for QObject::connect to be able to be called, that's why I updated SandboxedAppStat constructor with the following code:
auto *t = this;
QtConcurrent::run([&] () {
Sleep(3000);
bool b = QObject::connect(&(t->m_PidsTimer),
SIGNAL(timeout()), t, SLOT(pidsTimerTimeout()));
t->m_PidsTimer.start(500);
});
As you can see, QObject::connect executes after 3 seconds when static SanboxedAppStat is initialized, but this didn't help either, the program crashes after 3 seconds.
I'm really confused, I don't understand what can be the cause of this problem. Can't we use signal/slots in a static object instances?
I'm using Qt 4.8.0 with MSVC 2010. Thanks
UPDATE
Here's a simple project, consisting of only one header and one source file (as HostileFork suggested) to reproduce the crash. http://dl.dropbox.com/u/3055964/untitled1.zip
Are you looking for periodic calling of your pidsTimerTimeout slot or just once during construction?
If you're looking to just receive a signal once your class has been constructed try using QTimer::singleShot or QMetaObject::invokeMethod if you don't require continuous time outs. Like all signals the single shot will only be acted upon once the window system's event queue have been processed which can have a small delay on the execution of your slot.
MyClass::MyClass()
{
// Using a zero singles shot.
QTimer::singleShot( 0, this, SLOT( initialized() ) );
// or using invoke method.
QMetaObject::invokeMethod( this, "initialized", Qt::QueuedConnection );
}
Pretty sure we use this code in the office and we have success with static objects.
Boost.Signals allows various strategies of using the return values of slots to form the return value of the signal. E.g. adding them, forming a vector out of them, or returning the last one.
The common wisdom (expressed in the Qt documentation [EDIT: as well as some answers to this question ]) is that no such thing is possible with Qt signals.
However, when I run the moc on the following class definition:
class Object : public QObject {
Q_OBJECT
public:
explicit Object( QObject * parent=0 )
: QObject( parent ) {}
public Q_SLOTS:
void voidSlot();
int intSlot();
Q_SIGNALS:
void voidSignal();
int intSignal();
};
Not only doesn't moc complain about the signal with the non-void return type, it seems to actively implement it in such a way as to allow a return value to pass:
// SIGNAL 1
int Object::intSignal()
{
int _t0;
void *_a[] = { const_cast<void*>(reinterpret_cast<const void*>(&_t0)) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
return _t0;
}
So: according to the docs, this thing isn't possible. Then what is moc doing here?
Slots can have return values, so can we connect a slot with a return value to a signal with a return value now? May that be possible, after all? If so, is it useful?
EDIT: I'm not asking for workarounds, so please don't provide any.
EDIT: It obviously isn't useful in Qt::QueuedConnection mode (neither is the QPrintPreviewWidget API, though, and still it exists and is useful). But what about Qt::DirectConnection and Qt::BlockingQueuedConnection (or Qt::AutoConnection, when it resolves to Qt::DirectConnection).
OK. So, I did a little more investigating. Seems this is possible. I was able to emit a signal, and receive value from the slot the signal was connected to. But, the problem was that it only returned the last return value from the multiple connected slots:
Here's a simple class definition (main.cpp):
#include <QObject>
#include <QDebug>
class TestClass : public QObject
{
Q_OBJECT
public:
TestClass();
Q_SIGNALS:
QString testSignal();
public Q_SLOTS:
QString testSlot1() {
return QLatin1String("testSlot1");
}
QString testSlot2() {
return QLatin1String("testSlot2");
}
};
TestClass::TestClass() {
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot1()));
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot2()));
QString a = emit testSignal();
qDebug() << a;
}
int main() {
TestClass a;
}
#include "main.moc"
When main runs, it constructs one of the test classes. The constructor wires up two slots to the testSignal signal, and then emits the signal. It captures the return value from the slot(s) invoked.
Unfortunately, you only get the last return value. If you evaluate the code above, you'll get: "testSlot2", the last return value from the connected slots of the signal.
Here's why. Qt Signals are a syntax sugared interface to the signaling pattern. Slots are the recipients of a signal. In a direct connected signal-slot relationship, you could think of it similar to (pseudo-code):
foreach slot in connectedSlotsForSignal(signal):
value = invoke slot with parameters from signal
return value
Obviously the moc does a little more to help in this process (rudimentary type checking, etc), but this helps paint the picture.
No, they can't.
Boost::signals are quite different from those in Qt. The former provide an advanced callback mechanism, whereas the latter implement the signaling idiom. In the context of multithreading, Qt's (cross-threaded) signals depend on message queues, so they are called asynchronously at some (unknown to the emitter's thread) point in time.
Qt's qt_metacall function returns an integer status code. Because of this, I believe this makes an actual return value impossible (unless you fudge around with the meta object system and moc files after precompilation).
You do, however, have normal function parameters at your disposal. It should be possible to modify your code in such a way to use "out" parameters that act as your "return".
void ClassObj::method(return_type * return_)
{
...
if(return_) *return_ = ...;
}
// somewhere else in the code...
return_type ret;
emit this->method(&ret);
You may get a return value from Qt signal with the following code:
My example shows how to use a Qt signal to read the text of a QLineEdit.
I'm just extending what #jordan has proposed:
It should be possible to modify your code in such a way to use "out" parameters that act as your "return".
#include <QtCore>
#include <QtGui>
class SignalsRet : public QObject
{
Q_OBJECT
public:
SignalsRet()
{
connect(this, SIGNAL(Get(QString*)), SLOT(GetCurrentThread(QString*)), Qt::DirectConnection);
connect(this, SIGNAL(GetFromAnotherThread(QString*)), SLOT(ReadObject(QString*)), Qt::BlockingQueuedConnection);
edit.setText("This is a test");
}
public slots:
QString call()
{
QString text;
emit Get(&text);
return text;
}
signals:
void Get(QString *value);
void GetFromAnotherThread(QString *value);
private slots:
void GetCurrentThread(QString *value)
{
QThread *thread = QThread::currentThread();
QThread *mainthread = this->thread();
if(thread == mainthread) //Signal called from the same thread that SignalsRet class was living
ReadObject(value);
else //Signal called from another thread
emit GetFromAnotherThread(value);
}
void ReadObject(QString *value)
{
QString text = edit.text();
*value = text;
}
private:
QLineEdit edit;
};
To use this, just request call();.
You can try to workaround this with following:
All your connected slots must save their results in some place (container) accessible from signaling object
The last connected slot should somehow (select max or last value) process collected values and expose the only one
The emitting object can try to access this result
Just as an idea.