VaComm component encapsulates communication with external devices through COM port. My program is communicating with measuring device using following code:
void Form::OnButton_Click()
{
VaComm1->PortNum = param.serialComm.port;
VaComm1->Open();
VaComm1->WriteText("bla bla\r\n");
Sleep(3000);
VaComm1->WriteText("another bla bla");
}
I have set OnRxChar event handler (through form designer) which looks like this:
void __fastcall TForm_Main::VaComm1RxChar(TObject *Sender, int Count)
{
AnsiString str = VaComm1->ReadText();
if (!str.IsEmpty())
{
// process received data
}
}
Problem is that this event is not fired even when data were received (can be checked through calling TVaComm::ReadText method in infinite loop). Also sending of two commands to connected device was successfull (can be seen on device display). What else is needed beside opening COM port to receive OnRxChar events when there are some data in input buffer? I also don't understand what is the purpose of sibling component TVaBuffer? Currently i am not using it and can receive data through method ReadText (as i have written above).
Most CommPort components I have seen depend on the calling thread having an active message loop in order to fire asynchronous events. In this case, your main thread is blocked from processing new messages until OnButon_Click() exits. Try something more like this instead:
void Form::OnButton_Click()
{
VaComm1->PortNum = param.serialComm.port;
VaComm1->Open();
VaComm1->WriteText("bla bla\r\n");
}
void __fastcall TForm_Main::VaComm1RxChar(TObject *Sender, int Count)
{
AnsiString str = VaComm1->ReadText();
if (!str.IsEmpty())
{
// process received data
if (str is a reply you are expecting)
VaComm1->WriteText("another bla bla");
}
}
Related
I found time to investigate a bit into QT, and it is very interesting for me. However, right now I am encountering a problem that I am not aware about how to solve it. My aim is actually simple. I have a QCheckBox that I want to activate. If it is activated, I am starting a process (I am opening a file, reading it, taking some values out and change different labels accordingly). This process is repeated until the user is deactivating the QCheckBox. Some small code example to get a better idea of what I am going to do.
void Analyzer::on_actualTemperature_stateChanged(int arg1)
{
// Read data and change labels
if (arg1 != 0)
{
qDebug() << "Start data analysis";
// Infinity loop to get the data and display it
while true
{
// Open file and extract data
const actualTemperature = getData();
// Change any label or do something with the data
ui->anyLabel->setText(actualTemperature);
// Some break
QThread::sleep(1);
// Leave the loop if user deactivate the QCheckBox
// Something like on_actualTemperature_stateChange == 0
}
}
// Stop reading the data
else
{
qDebug() << "Stop data analysis";
}
}
It is obvious that after activating the QCheckBox, the loop will not finish at all and the GUI will not recognize anything anymore. Hence, I guess I have to start some new thread and have to kill it. However, I have no idea how to proceed here. An idea would be:
void Analyzer::on_actualTemperature_stateChanged(int arg1)
{
// Read data and change labels
if (arg1 != 0)
{
// Start reading the file and updating the label using some other thread
startThread(XY);
}
// Stop reading the data
else
{
// Kill thread 1234
killThread(XY);
}
}
Any hint is warmly welcomed and I hope this question is not too basic for you. Thank you for reading, Tobi.
I think killing a running thread is not a decent behavior. Let's be gentle to our threads with a loop control variable. In this example it named keepLoop. Set keepLoop when checkbox checked. Then start thread if it is not running. We are using QtConcurrent::run, and monitoring it by a QFuture in this case.
connect(ui->checkBox, &QCheckBox::toggled,
[&](const bool checked) {
analyzer->keepLoop = checked;
if (checked && !future.isRunning())
future = QtConcurrent::run(analyzer, &Analyzer::on_actualTemperature_stateChanged);
}
);
Don't call user interface slots directly, instead connect them to signals. Connections will be queued connection when signals emitted from another thread. It means slots will be called in event loop of main thread and changes will be shown when the next frame painted.
connect(analyzer, &Analyzer::temperatureCalculated, ui->anyLabel, &QLabel::setText);
Our asynchronous function does not forced to die immediately when user toggle checkbox. Instead we letting it to finish the iteration it already on halfway through.
Analyzer::on_actualTemperature_stateChanged() {
while (keepLoop) {
// Open file and extract data
const QString& actualTemperature = getData();
// send data
emit temperatureCalculated(actualTemperature);
}
}
You can use atomic bool if you want a more precise loop control.
Bonus:
If you don't want to mess with threads, you can avoid GUI freezing by using QTimer to run your loop periodically in main thread.
I found an interesting article on how to impement QObject with dynamic properties (see C++ class DynamicObject). The code from the article works fine, the properties of DynamicObject are get and set successfully from both C++ and QML, but the only thing I cannot figure out is how to fire dynamic signals.
I tried to fire "nameChanged()" signal with the following code:
bool DynamicObject::emitDynamicSignal(char *signal, void **arguments)
{
QByteArray theSignal = QMetaObject::normalizedSignature(signal);
int signalId = metaObject()->indexOfSignal(theSignal);
if (signalId >= 0)
{
QMetaObject::activate(this, metaObject(), signalId, arguments);
return true;
}
return false;
}
myDynamicObject->emitDynamicSignal("nameChanged()", nullptr);
the index of the signal is found and signalId is assigned to 5, but the signal is not fired. But if I do, for example,
myDynamicObject->setProperty("name", "Botanik");
the property is changed and the signal is fired successfully.
What is wrong in my code? What should I pass as 'arguments' parameter of QMetaObject::activate ?
EDIT1:
The full source code is temporarily available here.
A signal is also a method. You can invoke it from the meta object.
So, replace your line QMetaObject::activate(...) by:
metaObject()->method(signalId).invoke(this);
And let Qt handles the call to activate().
There is also an issue in DynamicObject::qt_metacall(): you are handling only QMetaObject::ReadProperty and QMetaObject::WriteProperty calls.
You have to add QMetaObject::InvokeMetaMethod if you want to emit your signal.
As far as I understand one has two options to port a C program to Native Client:
Implement a number of initializing functions like PPP_InitializeModule and PPP_GetInterface.
Simply pass your main function to PPAPI_SIMPLE_REGISTER_MAIN.
So the question is how can I implement JS message handling (handle messages emitted by JS code in native code) in the second case?
Take a look at some of the examples in the SDK in examples/demo directory: earth, voronoi, flock, pi_generator, and life all use ppapi_simple.
Here's basically how it works:
When using ppapi_simple, all events (e.g. input events, messages from JavaScript) are added to an event queue. The following code is from the life example (though some of it is modified and untested):
PSEventSetFilter(PSE_ALL);
while (true) {
PSEvent* ps_event;
/* Process all waiting events without blocking */
while ((ps_event = PSEventTryAcquire()) != NULL) {
earth.HandleEvent(ps_event);
PSEventRelease(ps_event);
}
...
}
HandleEvent then determines what kind of event it is, and handles it in an application specific way:
void ProcessEvent(PSEvent* ps_event) {
...
if (ps_event->type == PSE_INSTANCE_HANDLEINPUT) {
...
} else if (ps_event->type == PSE_INSTANCE_HANDLEMESSAGE) {
// ps_event->as_var is a PP_Var with the value sent from JavaScript.
// See docs for it here: https://developers.google.com/native-client/dev/pepperc/struct_p_p___var
if (ps_event->as_var->type == PP_VARTYPE_STRING) {
const char* message;
uint32_t len;
message = PSInterfaceVar()->VarToUtf8(ps_event->as_var, &len);
// Do something with the message. Note that it is NOT null-terminated.
}
}
To send messages back to JavaScript, use the PostMessage function on the messaging interface:
PP_Var message;
message = PSInterfaceVar()->VarFromUtf8("Hello, World!", 13);
// Send a string message to JavaScript
PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message);
// Release the string resource
PSInterfaceVar()->Release(message);
You can send and receive other JavaScript types too: ints, floats, arrays, array buffers, and dictionaries. See also PPB_VarArray, PPB_VarArrayBuffer and PPB_VarDictionary interfaces.
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;
};
Environment: Ubuntu, Qt Creator
In my Qt app, I found that sometimes Qt doesn't respond to my key press event immediately, but if I wait a while, it eventually responds.
I think something is blocking the UI.
As I know, if a Qt's component (QWidget etc.) is being destroyed, the Qt UI will be blocked. I have checked my code, there is no component being destroyed at the time I'm pressing the up/down key.
I really want to know is there any other things can block Qt UI.
{
...
connect(webViewWidget, SIGNAL(loadfinished()), this, SLOT(addItem()));
...
}
void addItem()
{
delete webViewWidget; // will this delete block UI?
mListWidget = new ScrollWidget();
mScrollArea = new ScrollArea(this);
for(int i=0; i<Datalen; i++)
{
mListWidget->addSubItem(itemWidget);
}
}
void keyPressEvent(QKeyEvent *event)
{
switch(event->key)
{
case UP_KEY:
scroll up;
break;
case DOWN_KEY:
scroll down;
break;
default:
break;
}
}
In general, your key press event will not be processed before all other events which were put into the application's event queue before pressing your key are processed.
Therefore it could be any kind of event which has not finished processing. Maybe you can figure out if there are any events, e.g. by using QApplication::hasPendingEvents or by inheriting from QApplication and adding debug output whenever an event is added or fully processed.
Destruction of objects is usually not a concern, unless you are doing a lot of work in the destructor. Destroying a webview may take long. You probably should not be destroying it like you do. Instrument that delete (see code below) and see how long it takes.
Your own code may be calling APIs that block. Are you calling any third party libraries? Are you calling any wait... methods in Qt's own API?
If you're unsure, you can instrument every slot and every reimplemented virtual method like xxxEvent(...). You'd need to instrument only slots and reimplemented QObject/QWidget methods, not every method in your code.
You may be producing an event storm, perhaps by posting lots of events in a loop, or by sending a lot of signals that are hooked up to slots connected via a Qt::QueuedConnection. Make sure you're not calling repaint() from within paintEvent() for example.
The instrumentation example below uses RAII and is very easy to apply. Alternatively, you can use a profiler.
#include <QElapsedTimer>
#define INSTRUMENT() Instrument instr__ument(__FUNCTION__)
#define INSTRUMENTLIM(lim) Instrument instr__ument(__FUNCTION__, (lim))
class Instrument {
QElapsedTimer timer;
int limit;
const char * function;
public:
Instrument(const char * name, int timeLimitMs = 20) :
function(name), limit(timeLimitMs) { timer.start(); }
~Instrument() {
if (timer.elapsed() > limit) {
qDebug("%s was slow, took %d ms", function, timer.elapsed());
}
}
}
void slot(...)
{
INSTRUMENT();
...
}
void addItem()
{
INSTRUMENT();
delete webViewWidget; // will this delete block UI?
mListWidget = new ScrollWidget();
mScrollArea = new ScrollArea(this);
for(int i=0; i<Datalen; i++)
{
mListWidget->addSubItem(itemWidget);
}
}