connect(serialScanner->serialPort, SIGNAL(readyRead()), serialScanner,
SLOT(handleReadyRead()));
Why is it than with the respective serial port opened, my code never gets into the connected function that is handleReadyRead()?
The code below is my alternative implementation within the class constructor, so as everything has the same scope.
if (scanConnectedSerialDevices()){
serialPort = new QSerialPort();
portPath = serialPortName;
serialPort->setPortName(portPath);
qDebug()<<serialPort->portName();
serialPort->setBaudRate(this->serialPortBaudeRate);
connect(serialPort, SIGNAL(readyRead()), this, SLOT(handleReadyRead()));
connect(serialPort, SIGNAL(bytesWritten(qint64)), this, SLOT(handleBytesWritten(qint64)));
serialPort.openPort(QIODevice::ReadOnly);
edit: Changing the Device, thus the Driver due to the scanner being from a different manufacturer my code works just fine??????
Related
I have a subclass of QObject called Updater that I want to use to manage some widgets in my app. I want it to run updateDisp() every 16 ms, so I created a QTimer in the constructor and connected the timeout signal to the updateDisp() slot. However, updateDisp() never runs, and I can't for the life of me figure out why.
in updater.h:
class Updater : public QObject {
Q_OBJECT
ToUpdate* toUpdate;
QTimer* timer;
...
public slots:
void updateDisp();
};
in updater.cpp:
Updater::Updater(ToUpdate* t, QObject *parent)
: QObject(parent) {
toUpdate = t;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateDisp()));
timer->setInterval(16);
timer->start();}
I instantiate an Updater object in MainWindow.cpp. Also, I have the GUI thread separate from main() (using winapi CreateThread()); I've seen some other posts about problems with QTimers and QThreads but obviously this is a bit different.
There's some similar issues.
I'd a similar problem in the past: https://github.com/codelol/QtTimer/commit/cef130b7ad27c9ab18e03c15710ace942381c82a#commitcomment-10696869
Basically it seems that Qt5 timer doesn't work as expected while in background, it's sync with the animation timer... which doesn't run often while in background.
This guy solved a similar issue setting the timer type to Qt::PreciseTimer
https://github.com/codelol/QtTimer/commit/cef130b7ad27c9ab18e03c15710ace942381c82a#commitcomment-10696869
timer->setTimerType(Qt::PreciseTimer);
The description of the timer types: http://doc.qt.io/qt-5/qt.html#TimerType-enum
Qt::PreciseTimer 0 Precise timers try to keep millisecond accuracy
Not sure if they're the exactly same problem, but you can give a try on that.
I am able to remove this warning, please suggest on below points.
QSocketNotifier: socket notifiers cannot be enabled from another thread
Whenever new request comes to QTcpServer i create new object -- xxx . This object then create thread for this socket & send receive data in
dowork_socket() function of yyy object. Inside dowork_socket() function i emit signal signalTcpSocketWriteData() to send data from socket.
Object creating the thread for new socket - xxx (I am not pasting full code):----
yyy * ptr;
QTcpSocket *m_pTcpSocket;
public slots:
void writeDataSlot( QByteArray data )
{
m_pTcpSocket->write( data );
m_pTcpSocket->flush();
}
Object in which thread is moved -- yyy (I am not pasting full code) :----
xxx *TcpSocketWrapper_ptr;
signals:
void signalTcpSocketWriteData( QByteArray);
public slots:
void dowork_socket();
Inside above object yyy contructor I am connecting signal signalTcpSocketWriteData to slot writeDataSlot :---
connect(this, SIGNAL(signalTcpSocketWriteData( QByteArray)), TcpSocketWrapper_ptr, SLOT(writeDataSlot( QByteArray )), Qt::QueuedConnection );
dowork function of object yyy :--
void TcpSocketThreadObject::dowork_socket()
{
QByteArray block;
block.append(" \n hi again .. !!!");
emit signalTcpSocketWriteData(block);
}
I am able to send data success fully by above method & above warning is removed.
1> Now my question is suppose two threads are created & both thread simultaneously emit the signal then will there be conflict in running the slot ?
2> Will it cause some critical section problem or events are queued & will not be executed simultaneously ?
Please suggest on this two points.
that seems too complicated. You don't need to create threads to work with sockets.
Whatever, if you do this, here's two points needs to be kept in mind:
QTcpSocket is Not thread-safe itself
as long as you use Qt::QueuedConnection when connecting slot (or at least proper using of implicit connections between different threads do this) all code executing inside connected slot will be execited in object's thread loop. In other words, signals emitted from different thread(s) will be queued.
I have a following situatuion.
2 Socket objects are created in the main in a for loop (the original problem has 1000 objects). Upon creation the start() method is invoked.
start() creates a QTcpSocket which tries to connect to some host.
Socket has slots which catch the connected() signal from QTcpSocket and print some debug output
What happens is that chronologically first ALL the Socket objects are created after which the sockets are started. Here is an example output of debug options:
1. Created Socket object 1
2. Invoked Socket object 1 start()
3. Created Socket object 2
4. Invoked Socket object 2 start()
5. Socket object 1 TcpSocket Connected
6. Socket object 2 TcpSocket Connected
Code:
//main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
for (int i=0; i<10; i++)
{
Socket *socket = new Socket();
qDebug() << "Socket object created";
socket->Start();
}
return a.exec();
}
//socket.cpp
Socket::Socket(QObject *parent)
: QObject(parent)
{}
void Socket::Start()
{
qDebug()<<"Start method invoked";
socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()), this, SLOT(on_connect()), Qt::DirectConnection);
socket->connectToHost("192.168.5.5",12345);
}
void Socket::on_connect()
{
QTcpSocket* socket = qobject_cast<QTcpSocket *>(QObject::sender());
qDebug() << socket->socketDescriptor() << " Connected.";
}
This is not the behavior I expected because the documentation states:
When a signal is emitted, the slots connected to it are usually
executed immediately, just like a normal function call. When this
happens, the signals and slots mechanism is totally independent of any
GUI event loop.
Question:
How to ensure the slots are executed "immediately" (not only after the loop in the main finishes) when the signal is emitted?
The only available solution (without introducing new threads) i currently see:
Drop the use of signals and slots in this case, and implement everything in the start method. Something like this:
Socket::start(){
...
if(!tcpsocket->waitForConnected(200)) qDebug() << "Socket object X TcpSocket Connected"
...
}
Your slot is indeed triggered immediately when QTcpSocket's signal connected() is emitted.
However, connected() is not emitted the moment you try to connect that socket to somewhere.
The documentation writes:
This signal is emitted after connectToHost() has been called
and a connection has been successfully established.
The establish of a connection requires an event loop.
establishing the connection happens asynchronously (read connectToHost will return immediately before it even checks whether the connection has already been established) and will notify your code using the signals that are triggered by events
these events are handled only in the event loop or when you call WaitForConnect (which will spin up it's own even loop only handling those events)
this means that the sequence you get is perfectly normal
I don't think you can do that without introducing new threads, only solution is seems your solution.
Or using DirectConnection instead of leaving it empty (Which is AutomaticConnection and which is QueuedConnection in your case) may be a solution. But I don't think that it will work because you need to wait in order to run that slot. I'm not sure, just give it a try.
Can anyone tell me if I'm doing this right?
Using Qt I'm implementing a TCP Server by inheriting from the QTcpServer class. On an incoming connection I create a new thread, a new Worker object, and I move the object to the new thread and start the thread. From here, the server keeps listening for new clients and each thread then is in its run method for object Worker.
Now, I create a timer because I need to send updates to each client based on 1 second intervals AND when a song is playing. In the readyRead slot I read data using readAll and then perform some work and send a reply.
However, when I go back to my run method I need to just continue sending song data updates to the clients (with no response from the client). Should this all just go in a while(true) loop and then I check some boolean to start and stop the timer? The track information I need to send is the song progression time.
I guess my question is, should I be doing it this way? It seems a little complex, but then again that's concurrency for you. Basically I need the TCP server to send data to the client repeatedly when some condition is true. I feel like just an endless while loop that checks when to start and stop the timer is useless work.
Would posting code make this clearer?
This question is a very old one, but perhaps it could still help.
About threads in Qt:
Many people think about parallel processing in Qt like in .NET where you need for every operation another thread, in qt this is not necessary!
In qt you only need a thread if you have blocking code like calculating big things or waiting syncron for an answer from a SQLServer
If i have understand you correctly you don't have such a blocking operation.
So i have programmed a very small TcpServer without inheriting and without a single thread (except the main eventloop thread of course), which hopefully solves your problem and help others:
#include <QObject>
#include <QSet>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
class TcpServer : public QObject
{
Q_OBJECT
public:
TcpServer()
{
// handle new connections
this->connect(&this->serverTcp, &QTcpServer::newConnection, this, &TcpServer::handleClientConnect);
// init client refresh timer
this->timer.setInterval(1000);
this->connect(&this->timer, &QTimer::timeout, this, &TcpServer::handleClientUpdates);
this->timer.start();
}
bool startListen(qint16 port)
{
return this->serverTcp.listen(QHostAddress::Any, port);
}
private slots:
void handleClientConnect()
{
QTcpSocket* socketClient = *this->setConnectedClients.insert(this->serverTcp.nextPendingConnection());
this->connect(socketClient, &QTcpSocket::disconnected, this, &TcpServer::handleClientDisconnect);
this->connect(socketClient, &QTcpSocket::readyRead, this, &TcpServer::handleClientData);
}
void handleClientDisconnect()
{
this->setConnectedClients.remove((QTcpSocket*)this->sender());
}
void handleClientData()
{
QTcpSocket* socketSender = (QTcpSocket*)this->sender();
// handle here the data sent by the client
}
void handleClientUpdates()
{
// construct here your update data
QByteArray baUpdateResponse = "test";
// send update data to all connected clients
foreach(QTcpSocket* socketClient, this->setConnectedClients) {
socketClient->write(baUpdateResponse);
}
}
private:
QTcpServer serverTcp;
QTimer timer;
QSet<QTcpSocket*> setConnectedClients;
};
I have some constructor for the class LCDRange:
LCDRange::LCDRange(QWidget *parent)
: QWidget(parent)
{
QLCDNumber *lcd = new QLCDNumber(2);
lcd->setSegmentStyle(QLCDNumber::Filled);
slider = new QSlider(Qt::Horizontal);
slider->setRange(0, 99);
slider->setValue(0);
connect(slider, SIGNAL(valueChanged(int)),
lcd, SLOT(display(int)));
connect(slider, SIGNAL(valueChanged(int)),
this, SIGNAL(valueChanged(int)));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(lcd);
layout->addWidget(slider);
setLayout(layout);
}
but I can't understand the difference between these lines:
connect(slider, SIGNAL(valueChanged(int)),
lcd, SLOT(display(int)));
connect(slider, SIGNAL(valueChanged(int)),
this, SIGNAL(valueChanged(int)));
thanks in advance
Remember that we are in OO land, so we are operating on objects.
In order to connect a signal to something, those signal/slots have to be apart of an object.
Another way to think about it is you can't have a signal by itself, because a signal has to come from somewhere. Likewise, you can't have a slot all by itself it has to be attached to something.
Now, Qt allows you to connect a signal to a slot, but it also allows you to connect a signal to a signal, which is what is happening in the second connect line. This allows you to chain signals from one object to another, or you could think about it as passing a signal through.
Usually this happens when an Object or Widget has a private internal child that emits a signal, and the parent Object/Widget wants to emit the same signal to whoever is listening to it.
In the case of your example the LCDRange Widget contains a slider, which is an internal implementation detail. The user of LCDRange doesn't need to know about all the different components that make up the LCDRange (slider, lcdnumber, layout, etc), that's a basic requirement of encapsulation which is a huge advantage of OO.
However, the user of LCDRange will want to know when the value of LCDRange changes. And rather then creating a slot in LCDRange, that simply re-emits the signal valueChanged signal, you can forward or passthrough the valueChanged signal from the slider.
The following achieves the same effect of passing the signal through, however it requires much more code.
class LCDRange : public QWidget
{
// constructor and other methods
//...
signals:
void valueChanged(int)
private slots:
void sliderValueChanged(int);
// ...
};
// in the LCDRange constructor
connect(slider, SIGNAL(valueChanged(int)),
this, SLOT(sliderValueChanged(int)));
// elsewhere in LCDRange's definition
void LCDRange::sliderValueChanged( int value )
{
emit valueChanged( value );
}
connect(slider, SIGNAL(valueChanged(int)),
lcd, SLOT(display(int)));
tells, if the value of the slider gets changed then valueChanged signal will be emited and it will be reflected in LCD view. i.e display slots gets called, whose implementation will be present in QLCDNumber
connect(slider, SIGNAL(valueChanged(int)),
this, SIGNAL(valueChanged(int)));
Qt offers, mechanism of connecting one signal to another signal, it implies if slider valueChangedsignal is emited means present class valueChangedsignal is emited.
the connected slot for valueChanged gets called