Program crash using a while loop
-
Hello everybody. I'm doing a UART communication. I have a button that makes a program runs continuously if the button is down or checked, however, when I press the button again to change its state, the program does not respond, and after a couple of clicks more, it crashes, any help will be appreciated it. Thanks.
void MainWindow::on_pushButton_3_toggled(bool checked) { while(checked) { QByteArray datas = Serial_port.readAll(); ui->textEdit->setText((QString)datas); qDebug()<<"Im here"; msleep(100); qDebug()<<datas; qDebug()<<checked; } qDebug()<<checked; }
-
Hi, and welcome to the Qt forum. Once your program enters the while loop, it's trapped there forever. And as you're executing this infinite loop on the GUI thread, your GUI can't respond to clicks (or do anything else) anymore.
-
@Wieland said in Program crash using a while loop:
Hi, and welcome to the Qt forum. Once your program enters the while loop, it's trapped there forever. And as you're executing this infinite loop on the GUI thread, your GUI can't respond to clicks (or do anything else) anymore.
How could I solve this problem? How could I run something continuously and be able to check and get out of that loop?
-
You could call
QApplication::processEvents()
from within the loop to have events handled. But what you really want is to move your blocking code into its own thread. See How To Really, Truly Use QThreads; The Full Explanation for more info on this. -
@Wieland said in Program crash using a while loop:
Hi, and welcome to the Qt forum. Once your program enters the while loop, it's trapped there forever. And as you're executing this infinite loop on the GUI thread, your GUI can't respond to clicks (or do anything else) anymore.
How could I solve this problem? How could I run something continuously and be able to check and get out of that loop?
@anfedres As alternative to what @Wieland suggested you could do it in Qt way: use signals/slots.
This way you avoid multi-threading which is a complex and error prone topic.
Implement a slot and connect it to the http://doc.qt.io/qt-5/qiodevice.html#readyRead signal of your serial port. In that slot then call readAll.One note:
ui->textEdit->setText((QString)datas);
this will overwrite what was set before in textEdit, not sure whether it is intended behaviour. If you want to see everything you got so far do:
ui->textEdit->setText(ui->textEdit->toPlainText() + (QString)datas);
-
@anfedres As alternative to what @Wieland suggested you could do it in Qt way: use signals/slots.
This way you avoid multi-threading which is a complex and error prone topic.
Implement a slot and connect it to the http://doc.qt.io/qt-5/qiodevice.html#readyRead signal of your serial port. In that slot then call readAll.One note:
ui->textEdit->setText((QString)datas);
this will overwrite what was set before in textEdit, not sure whether it is intended behaviour. If you want to see everything you got so far do:
ui->textEdit->setText(ui->textEdit->toPlainText() + (QString)datas);
ui->textEdit->setText(ui->textEdit->toPlainText() + (QString)datas);
That line really helped me a lot. I was planning to build an array, save it and display it.
Talking about the Signals and Slots, I just started to program in qt yesterday, I'm getting familiar with it. I was trying to implement a toggle button but failed. The idea is having a button that if you press for the first time, stays down and sends data using the UART. I had problems finding the right example using "connect".
I have done the following, which it works, but the communication gets data when is available, I was looking more to get the data if I press the button.
The following line will connect the port to the signal when there is data available.
connect(&Totem_Serial,SIGNAL(readyRead()),this,SLOT(Totem_Serial_Received()));
Where Totem_Serial_Received() is defined as follow:
void MainWindow::Totem_Serial_Received() { QByteArray datas = Totem_Serial.readAll(); // ui->textEdit->setText((QString)datas); ui->textEdit->setText(ui->textEdit->toPlainText() + (QString)datas); qDebug()<<"Im here"; qDebug()<<datas; }
From here, connecting the signal of the bottom being down shouldn't be that hard. If you point me out an example, I will appreciate it.
Thank you for your help.
-
Hi
For a button that acts like a checkbox please see
http://doc.qt.io/qt-5/qabstractbutton.html#checkable-prop
and the Toggle signal
http://doc.qt.io/qt-5/qabstractbutton.html#toggleso you would enable checking
ui->TheButton->setCheckable(true);
and then use connect
QObject::connect(ui->TheButton, SIGNAL(toggled(bool)), Mainwindow, SLOT(yourslot(bool)));Remember to add "yourslot" to mainwindow
-
@mrjj I'll might need a litte bit more of help. I'm really trying, but. I'm still to new to this. I'm not quite sure what am I doing wrong here. Signals/Slots should't be that hard.
The following code should make the pushbutton checkeable, so it will remain pressed once you pressed, and it will be released once you presed it again. While the button is pressed, checked will remain with a Boolean state (I'm guessing it will be true). So, my signal will be generated by the object pusshButton, such signal will be "checked" (the stated of the button). The previous signal will activate the Totem_Serial_Received function. Am I right?
ui->pushButton->setCheckable(true); QObject::connect(ui->pushButton, SIGNAL(checked), this, SLOT(Totem_Serial_Received()));
Where Totem_Serial_Received() is as follow:
void MainWindow::Totem_Serial_Received() { QByteArray datas = Totem_Serial.readAll(); ui->textEdit->setText(ui->textEdit->toPlainText() + (QString)datas); qDebug()<<"Im here"; qDebug()<<datas; }
And the button was defined as follow:
void MainWindow::on_pushButton_toggled(bool checked) { }
I'm also getting an error: QObject::connect: Parentheses expected, signal QPushButton::checked in ..\Totem_app\mainwindow.cpp:35
I think I have all the parentheses.Thanks for your help. I'm sorry if the questions seems simply, but I just started to program in qt yesterday.
-
Hi
Np. as long as you try, its ok to ask anything you like.I think we need to talk about the logic.
The check button signal should not send to Totem_Serial_Received as that is for reading data.
so its correct to hook it up to
void MainWindow::on_pushButton_toggled(bool checked)
{
if (checked) // ok to read data
else
// not ok
}But do you want to close the serial completely or simply ignore what is sent ?
Because there are many ways to implement this so how do you really want it to work?
Update:
Higher up you write ", stays down and sends data using the UART."So maybe i misread.
This toggle buttons controls sending stuff ? ( not reading) ?
Also it wont call a function over and over while being down.
Do you need that? -
@mrjj What I want is just to read data when I press the button, and stop reading data when I press it again. Is it the connect implementation OK? But I want is to read data while the button is holding its state of pressed.
This toggle buttons controls sending stuff ? ( not reading) ?
I'm reading data using the UART
Also it wont call a function over and over while being down.
Do you need that?That's what I'm trying to implement, read data continuously while the button is down, that's why I implemented it at the beginning with the while loop.
-
@mrjj What I want is just to read data when I press the button, and stop reading data when I press it again. Is it the connect implementation OK? But I want is to read data while the button is holding its state of pressed.
This toggle buttons controls sending stuff ? ( not reading) ?
I'm reading data using the UART
Also it wont call a function over and over while being down.
Do you need that?That's what I'm trying to implement, read data continuously while the button is down, that's why I implemented it at the beginning with the while loop.
@anfedres said in Program crash using a while loop:
read data continuously while the button is down,
The QSerial is already reading by it self., if it sees data then it will call the SLOT. (Totem_Serial_Received)
So if you mean to completely stop reading, then you need to close the serial port or disconnect the data signal.
Im not sure why you need this. Maybe its just the wording.
So if Checked, then serial port will be oepn and data is being read.
If dechecked, then serial port is closed. Is that what u mean ?Else im not sure where you are going with this checkable button :)
-
@anfedres said in Program crash using a while loop:
read data continuously while the button is down,
The QSerial is already reading by it self., if it sees data then it will call the SLOT. (Totem_Serial_Received)
So if you mean to completely stop reading, then you need to close the serial port or disconnect the data signal.
Im not sure why you need this. Maybe its just the wording.
So if Checked, then serial port will be oepn and data is being read.
If dechecked, then serial port is closed. Is that what u mean ?Else im not sure where you are going with this checkable button :)
@mrjj You might be right. Yes, what about, displaying the data! I think that would be the right think to do. My guess would be, instead of calling
Totem_Serial_Received()
I should call a function that does the following while the button is down.
ui->textEdit->setText(ui->textEdit->toPlainText() + (QString)datas);
This sounds like a more adequate approach. Am I right?
-
@mrjj You might be right. Yes, what about, displaying the data! I think that would be the right think to do. My guess would be, instead of calling
Totem_Serial_Received()
I should call a function that does the following while the button is down.
ui->textEdit->setText(ui->textEdit->toPlainText() + (QString)datas);
This sounds like a more adequate approach. Am I right?