Qtimer Bloking Slots Value - qt

Hi I have a bellowing code. I want to add some delay (6second) for appering QMesaageBox. But in background reading 2 ports. I dont want to delay block port value.
motorStart();
QString msv = "msv?0;";
loadcellPort->write(msv.toStdString().c_str(),msv.length());
plotFlag = true;
newPlot = true;
ui->startButton->setEnabled(false);
ui->cancelButton->setEnabled(false);
QTimer::singleShot(5000,this,SLOT(onSerialLoadcellData()));
QMessageBox::information(this,"Bastak Test",json_map["QWater"].toString(),json_map["QFinishAccept"].toString());
I was use QThread before and this thread bloking port value ?
class Sleeper : public QThread
{
public:
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
};

Related

connect multiple signal to a slot

I've the follwoing issue.
There are two signals :
void buttonChanged(int);
void pulseWidthValue(int);
buttonChanged is emitted from a slot nextBtn:
void Program::nextBtn()
{
m_currentBtn++;
if(m_currentBtn > btnGrp->buttons().size())
{
m_currentBtn = 0;
phaseOver = true;
saveToXMLFile();
}
emit buttonChanged(m_currentBtn);
}
it's connected as follows:
connect(ui->btn_nextPhase, &QPushButton::clicked, this, &Program::nextBtn);
connect(this, &Program::buttonChanged, this, &Program::paintBtn);
the signal, buttonChanged is used in another slot to paint button:
void Program::paintBtn(int id) // how do I change the def of this function to receive to signal?
{
if(id==1)
{
ui->btn1->setStyleSheet(StyleSheetOn);
ui->btn2->setStyleSheet(StyleSheetOff);
ui->btn3->setStyleSheet(StyleSheetOff);
}
else if(id==2)
{
ui->btn1->setStyleSheet(StyleSheetOff);
ui->btn2->setStyleSheet(StyleSheetOn);
ui->btn3->setStyleSheet(StyleSheetOff);
}
else if(id==3)
{
ui->btn1->setStyleSheet(StyleSheetOff);
ui->btn2->setStyleSheet(StyleSheetOff);
ui->btn3->setStyleSheet(StyleSheetOn);
}
else
{
ui->btn1->setStyleSheet(StyleSheetOff);
ui->btn2->setStyleSheet(StyleSheetOff);
ui->btn3->setStyleSheet(StyleSheetOff);
}
ui->label_7->setText(QString::number(pw_value)); // this pw_value is from the other signal pulseWidthValue
}
the basic idea is , there are 3 phase buttons , clicking Next will switch between these buttons and change its color. Now I need to use the other signal pulseWidthValue inside paintBtn
Now I come to the question:
How do I connect two signals, buttonChanged and pulseWidthValue, (both signals are coming from different functions) to the paintBtn slot?
Qt allows you to connect multiple times even to the same slots. It even allows you to connect between signals.
Check this example, is not meant to be functional but descriptive enought to see many options and accesability.
class A:public QObject
{
Q_OBJECT
...
signals:
void signalA1();
void signalA2(const QString &);
}
class B:public QObject
{
Q_OBJECT...
signals:
void signalB();
public slots:
void slotB();
}
class C:public QObject
{
...
public:
C(QObject *parent):QObject(parent)
{
a=new A(this);
b=new B(this);
}
void connectionTest()
{
connect (a,&A::signalA1,b,&B::slotB) ; // one connection to slot B::slotB
connect (this,&C::signalC,b,&B::slotB); // another connection to B::slotB
connect (a,&A::signalA1,this,&C::slotC) ; // another connection from A::signalA, slotC is private so only I can connect
connect (b,&B::signalB,this,&C::signalC); // connection from signal to signal
connect (a,&A::signalA2,this,&C::slotC); //connection from A::signalA2 to C::slotC
//with different argument count, but compatible as slotC doesn't need an argument
connect (a,&A::signalA1,b,&B::slotB) ; // duplicate connection to slot B::slotB (signalA1 will trigger slotB two times)
}
signals:
void signalC();
private slots:
void slotC();
private:
class A *a;
class B *b;
}

QT-How to utilize QWidget with QThread?

I'm making some GUI through QT.
I almost complete my work but I have a hard time dealing with Qthread.
My goal is to measure the position of the motor (it moves) and display it on the Qtextbrowser while working another function in the main thread. When I wrote codes like below, people said I can't use QTextBrowser(Qwidget) directly in the thread, so I'm searching how to return location value to the main thread. Can you do me a favor?
MDCE is a class in another header and the codes I attach are some parts of my first code.
void MotorPort::StartThread(MDCE* com, QTextBrowser* browser)
{
thread1 = QThread::create(std::bind(&MotorPort::MeasureLocation,this,com,browser));
thread1 -> start();
}
void MotorPort::MeasureLocation(MDCE* com, QTextBrowser* browser)
{
double location;
while(1)
{
location = CurrentLocation(com); \\return current position value
browser->setText(QString::number(location));
if (QThread::currentThread()->isInterruptionRequested()) return ;
}
}
void MotorPort::stopMeasure()
{
thread1->requestInterruption();
if (!thread1->wait(3000))
{
thread1->terminate();
thread1->wait();
}
thread1 = nullptr;
}
You should use the Qt signal/slot mechanism for iter-thread notification such as this. Firstly change your MotorPort class definition to declare a signal location_changed...
class MotorPort: public QObject {
Q_OBJECT;
signals:
void location_changed(QString location);
...
}
Now, rather than MotorPort::MeasureLocation invoking QTextBrowser::setText directly it should emit the location_changed signal...
void MotorPort::MeasureLocation (MDCE *com, QTextBrowser *browser)
{
while (true) {
double location = CurrentLocation(com);
/*
* Emit signal to notify of location update.
*/
emit location_changed(QString::number(location));
if (QThread::currentThread()->isInterruptionRequested())
return ;
}
}
Finally, update MotorPort::StartThread to connect the signal to the browser's setText slot...
void MotorPort::StartThread (MDCE *com, QTextBrowser *browser)
{
connect(this, &MotorPort::location_changed, browser, &QTextBrowser::setText);
thread1 = QThread::create(std::bind(&MotorPort::MeasureLocation, this, com, browser));
thread1->start();
}

Qt add points one by one with QThread or QTimer?

I want to make a program in Qt to add points one by one, not all at once. To do that, I need to use QThread, or I can just use QTimer?
it can be done using QTimer and if it is time dependent (like every 1 second) then its the way to go. just create the timer, connect its timeout signal to your slot and it should work like a charm
You need create some class, inherited from QObject:
class QTimer;
class QList;
class Test_Timer : public QObject
{
Q_OBJECT
public:
explicit Test_Timer(QObject *parent = 0);
~Test_Timer();
private:
QList<QPoint> *lst;
QTimer *timer;
public slots:
void addPoint();
};
Ok, now we have timer variable for QTimer events, lst for store QPoint and addPoint() slot for handling your timer event.
At constructor we initialize members of class, connect timer's slot with current class slot and start timer with period 500ms:
Test_Timer::Test_Timer(QObject *parent) : QObject(parent)
{
lst = new QList<QPoint>;
timer = new QTimer;
connect(timer, SIGNAL(timeout()), this, SLOT(addPoint()));
timer->start(500);
}
Slot for adding points may look something like this:
void Test_Timer::addPoint()
{
static int number = 0;
if (lst->size() < 10) {
lst->append(QPoint(0, number++));
qDebug() << lst->size();
} else {
timer->stop();
deleteLater();
}
}
After all don't remember free resources:
Test_Timer::~Test_Timer()
{
lst->clear();
delete lst;
if (timer->isActive())
timer->stop();
delete timer;
}
I think this example will be helpful for you.

Qt signal to specific object's slot

I would like to know which of the following is the proper way of doing thing with signal/slot in Qt.
I need a way to have multiple instance of a Dialog, i.e: A and B. And I need to tell A to print "A" and B to print "B" from a different thread. So I believe I need something like either:
OPTION 1) A->print("A") and B->print("B")
or is it better to do:
OPTION 2) emit print("A") and emit print("B") and use a way that I don't know so only A catch the "A" and only B catch the "B".
I got the option 1 working like this:
class myClass : public QMainWindow
{
Q_OBJECT
public:
myClass (QWidget *parent = 0, Qt::WFlags flags = 0);
~myClass ();
void doPrint(char* text)
{
emit mySignal(text);
}
private:
Ui::myClass ui;
public slots:
void newLog(char* msg);
signals:
void mySignal(char* msg);
};
myClass::myClass(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags)
{
ui.setupUi(this);
connect(this, SIGNAL(mySignal(char*)), this, SLOT(newLog(char*)));
}
void myClass::newLog(char* msg)
{
ui.textEdit->append(msg);
}
and then all I have to do is:
myClass* instanceA = new myClass();
myClass* instanceB = new myClass();
instanceA->doPrint("A");
instanceB->doPrint("B");
is this right?
Thanks!
Since your slot is in another thread, you have to use the Meta-Object System to invoke the method asynchronously. The proper way to do this is to use QMetaObject::invokeMethod
DO NOT subclass QThread and override the run method. For details on this see: https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
void otherClass::printTo(myClass* instance, char* text)
{
QMetaObject::invokeMethod(instance, // pointer to a QObject
"doPrint", // member name (no parameters here)
Qt::QueuedConnection, // connection type
Q_ARG(char*, text)); // parameters
}
void myClass::doPrint(char* text)
{
ui.textEdit->append(text);
}
myClass* instanceA = new myClass();
myClass* instanceB = new myClass();
printTo(instanceA, "A");
printTo(instanceB, "B");
If the char* type hasn't been registered with the Meta-Object System yet, do so with
Q_DECLARE_METATYPE(char*);
then:
qRegisterMetaType<char*>("charPtr");
In this simplified example, I think you are on the correct path with option 1. However, it would be even better if you didn't need the doPrint() method, which would also eliminate the need for the mySignal signal (at least in myClass). Instead, I would suggest inheriting your threads from QThread if the aren't already, and doing something like this:
class myThread : public QThread
{
Q_OBJECT
public:
myThread (QWidget *parent = 0 ) : QThread(parent) {}
~myThread () {}
void run(char* text)
{
emit mySignal(text);
}
signals:
void mySignal(char* msg);
};
Then you need to do something like this:
myClass* instanceA = new myClass();
myThread* threadA = new myThread();
connect(threadA, SIGNAL(mySignal(char*)), instanceA, SLOT(newLog(char*)), Qt::QueuedConnection);
threadA->run( "A" );
Obviously, in most non-example code, you'd not pass the string into run, but rather generate strings to be run as threadA is running. The advantage is that this keeps the thread considerations out of myClass, and you only need to think about them where they are connected. On the flip side, you introduce fewer dependencies into the threads, since they don't need to know about myClass to be able to log.

Scientific Visualization with OpenGL and Qt

I am trying to write an OpenGL visualization program for some scientific data using Qt. I would like to be able to use my existing program unchanged and simply be able to call the glwidget and tell it to update the data at the end of each time step. However in order to run a Qt program it appears you have to use QApplication and then qt.run() which blocks the cpu.
Here is the pseudo code
main()
{
..set up stuff
myVisualizer = new myGLWidget();
for(int i=0;i<1000;i++)
{
..do calculations
myVisualizer.update(new data)
}
}
I realize that I could put all of my existing code in to a QThread and have it send a signal whenever it is done to connect to an update. It would just be easier this way. Does anybody have an idea how to solve this?
If you really don't want to investigate the threaded solution, which would be nicer all around, you can use the special-case timeout with 0. Basically, when you run a timer with a timeout of 0, it runs the appropriate code after processing the events that are currently on the event queue. So, you could set up something like this:
class MyDialog : public QDialog
{
Q_OBJECT
public:
MyDialog()
{
m_step = 0;
QTimer::singleShot( 0, this, SLOT( Process() ) );
}
public slots:
void Process()
{
// do calculations
m_step++;
QTimer::singleShot( 0, this, SLOT( Redraw() ) );
if ( m_step != 1000 )
QTimer::singleShot( 0, this, SLOT( Process() ) );
}
void Redraw() { // do redrawing code here }
private:
int m_steps;
};
And then combine it with the Qt-proper main code:
int main( int argc, char** argv )
{
QApplication app( argc, argv );
MyDialog dialog;
dialog.show();
return ( app.exec() );
}
You can use QThread in your application and do the calculations in a seperate thread.
What you have to do is to subclass the QThread and implement the run() method.
You can create a calculator class and add some signals in that class and connect the signal to your display widget's update slot (in this case QGLWidget::updateGL()).
Here is a rough example: (All you have to is to create a thread and DisplayWidget in your main() function and set the thread's DisplayWidget.)
class Calculator: public QObject
{
Q_OBJECT
public:
Calculator();
void start();
signals:
void updateDisplayWidget(/* you can put the resulting data */);
};
class DisplayWidget(): public QGLWidget
{
Q_OBJECT
// override paint methods here
public slots:
void slotUpdateDisplayWidget(/* you can receive the resulting data*/);
};
class MyThread : public QThread
{
public:
void run();
void setDisplayWidget(DisplayWidget* displayWidget);
private:
Calculator mCalculator;
};
void MyThread::run()
{
mCalculator.start();
exec();
}
MyThread::setDisplayWidget(DisplayWidget* displayWidget)
{
displayWidget->moveToThread(this);
connect(&mCalculator, SIGNAL(updateDisplayWidget()), displayWidget, SLOT(slotUpdateDisplayWidget()));
}

Resources