Qt : restarting thread - c++

I'm working on a GUI with Qt, I have a problem with playing with threads . I create a small GUi with two button stream and stopstream. my Problem is that I can't restart stream after stoping it:
below is a part of the code :
MainThread::MainThread(QWidget *parent):QWidget(parent){
bstream = new QPushButton("&stream");
bstopstream = new QPushButton("STOP stream");
bcapture = new QPushButton("capture a frame");
Allbox = new QVBoxLayout(this);
Allbox->addWidget(bstream);
Allbox->addWidget(bcapture);
Allbox->addWidget(bstopstream);
connect(bstream,SIGNAL(clicked()),this, SLOT(startingstream()));
connect(bcapture,SIGNAL(clicked()),this, SLOT(captureAFrame()));
connect(bstopstream,SIGNAL(clicked()),this, SLOT(stopstreaming()));
setLayout(Allbox);
}
void MainThread::stopstreaming(){
cv::destroyAllWindows();
stream.terminate();
stream.wait();
stream.~Streaming();
}
void MainThread::startingstream(){
if(stream.isRunning()) return;
stream.start();
}

stream.~Streaming();
This calls the destructor of your stream object. You should not call it manually, formally the object is dead after that and it may behave "interesting" after that.
For example, assume an object like this:
void stream::play() {
buff_->start();
}
void stream::~stream() {
delete buff_;
}
then the line buff_->start() might do funky things, essentially yielding undefined behaviour.
Or if it is written like this (though you should never need to manually set something to zero in a destructor; as said, the object is supposed to be dead after destruction):
void stream::play() {
if (buff_) buff_->start();
}
void stream::~stream() {
delete buff_;
buff_ = 0;
}
then it might do plain nothing.

Related

How do I suppose to delete dynamic object which is may be allocated in an slot method?

Either one of method the slot/method will allocate memory on heap then how do I suppose to delete it in the destructor?
Test::~Test()
{
delete frame;
delete frame_2;
delete ui;
}
void Test::on_pushButton_clicked()
{
frame = new QFrame();
frame->show();
}
void Test::on_pushButton_2_clicked()
{
frame_2 = new QFrame();
frame_2->show();
}
Actually I want to build a app that has multiple buttons, each button allocates different QFrame.
Or my coding design for situation like this is wrong?
Thank you.
The Qt way would be to pass a pointer to a parent whenever you new-up a QtObject. Qt will automatically destroy an object's children when it is destroyed. You should never have to call delete.
So, assuming Test is a QtObject subclass, you can change your code to the following:
Test::~Test() = default;
void Test::on_pushButton_clicked()
{
frame = new QFrame(this);
frame->show();
}
void Test::on_pushButton_2_clicked()
{
frame_2 = new QFrame(this);
frame_2->show();
}
Also check out this article on ownership with Qt for more deets: https://doc.qt.io/qt-5/objecttrees.html

QMessageBox open multiple times using shortcutkeys

I am putting a QMesssageBox inline with the shortcutkey of CTRL + N (it means new file will be open). When I press and hold the shortcut key when the object is animating. Is it UI problem of Linux since I am using Linux OS and then I try in other OS and it is not happening, or any codes that I forgot?
Thank you.
If your goal is to have at most one QMessageBox appear at a time, you can ensure that in your code via something like this:
static QMessageBox * openMBox = NULL;
void MyClass :: showMessageBox()
{
if (openMBox) return; // don't open a new QMessageBox if we already have one open!
openMBox = new QMessageBox(args here...);
connect(openMBox, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(userClickedButton(QAbstractButton*)));
openMBox->show();
}
void MyClass :: userClickedButton(QAbstractButton * button)
{
if (openMBox)
{
// [code to handle button-click result could go here]
openMBox->deleteLater();
openMBox = NULL;
}
}
Note that showMessageBox() will only actually create a new QMessageBox if openMBox is NULL, which is to say, only if there isn't already a message-box present.
(The code calls deleteLater() in the userClickedButton() method instead of using the delete operator because it's likely that the userClickedButton() method is itself being called from within a method of the QMessageBox object, therefore we don't want to delete the QMessageBox object until later when it's not in the middle of a method-call)

Smart pointers as an alternative to QObject::deleteLater()

So I have got a function which makes a network request:
void MyClass::makeRequest()
{
ApiRequest* apiRequest = new ApiRequest();
apiRequest->makeRequest();
connect(apiRequest, &ApiRequest::requestFinished, this, &MyClass:onApiRequestFinished);
}
Since I need the object apiRequest to survive until my request is finished I then call:
void MyClass:onApiRequestFinished()
{
// do my stuff
// now I can delete my request object ((retrieved using sender()) using deleteLater()
}
Now since I am not using Qt parent-child system in this case how can I manage the memory using C++11 smart pointers instead of calling deleteLater()?
I don't think you can solve this with C++ smart pointers without storing the apiRequest object in some container until requestFinished is triggered.
Maybe an alternative would be to create an ApiRequest::finished() method to use as the receiver of the signal, then pass this to ApiRequest's constructor so finished() can call MyClass::onApiRequestFinished(), and then have finished() call delete this after onApiRequestFinished() exits, eg:
void MyClass::makeRequest()
{
ApiRequest* apiRequest = new ApiRequest(this);
apiRequest->makeRequest();
}
void MyClass::onApiRequestFinished()
{
// do my stuff
}
...
ApiRequest::ApiRequest(MyClass *cls)
: m_cls(cls)
{
connect(this, &ApiRequest::requestFinished, this, &ApiRequest::finished);
}
void ApiRequest::finished()
{
m_cls->onApiRequestFinished();
delete this;
}
Not sure how feasible this is with Qt, but maybe worth a try.

QtConcurrent::run with MainWindow function, warning message "QObject::setParent: Cannot set parent, new parent is in a different thread"

I'm trying to use QtConcurrent::run to execute a function within my MainWindow class, so that the UI remains responsive during the calculations. Here is how I implemented it:
void MainWindow::on_calculate_pb_clicked()
{
QFuture<void> future = QtConcurrent::run(this,&MainWindow::calculation);
}
void MainWindow::calculation()
{
progressBar->show();
loadMap();
integral.clear();
positions.clear();
offset.clear();
lines = 0;
for(int i=0;i<paths.size();i++)
{
if(i ==0)
{
lines = countNumberOfLines(paths.at(i));
}
double file = i+1;
ui->statusBar->showMessage(QString("Processing file %1 of %2").arg(file).arg(paths.size()));
calculateIntegral(paths.at(i));
offset.push_back(ui->tableWidget->item(i,1)->text().toDouble());
}
makePositionVector();
plotData(ui->customPlot);
ui->export_pb->setEnabled(true);
progressBar->hide();
ui->statusBar->showMessage("Done",3000);
}
void MainWindow::calculateIntegral(QString path)
{
QVector<double> mappeddata,tempdata;
mappeddata.resize(map.size());
tempdata.resize(numberofdetectors);
double currentLine = 0;
QFile File(path);
if(File.exists()==true){
File.open(QIODevice::ReadOnly);
QTextStream in(&File);
double val;
while(!in.atEnd())
{
for(int j = 0;j<numberofdetectors;j++)
{
in >> val;
tempdata[j]+=val;
currentLine++;
double progress = currentLine/lines*100;
progressBar->setValue(progress);
}
}
for(int i =0;i<map.size();i++)
{
mappeddata[i] = tempdata.at(map.at(i));
}
for(int k = 0;k<numberofdetectors; k++)
{
integral.push_back(mappeddata.at(k));
}
}
File.close();
}
It works fine and the UI is responsive and the progress bar is updated correctly, however in the output I receive the error "QObject::setParent: Cannot set parent, new parent is in a different thread" many times, from something that is executing in a loop.
Any ideas what is causing this, or suggestions for a better implementation of QtConcurrent::run?
Thanks
You can't be touching any Qt-provided QWidget objects from the worker thread, since most of their methods are not thread-safe.
Instead, a way to tackle this is to do the computations in the worker, and then submit functors that update the state to the main thread. See this answer for details.
Your code would then become:
void MainWindow::calculation()
{
postToThread([this]{ progressBar->show(); });
loadMap();
integral.clear();
positions.clear();
offset.clear();
lines = 0;
for(int i=0;i<paths.size();i++)
{
if (i == 0)
lines = countNumberOfLines(paths.at(i));
auto file = i+1;
postToThread([this]{
ui->statusBar->showMessage(
tr("Processing file %1 of %2").arg(file).arg(paths.size()));
});
calculateIntegral(paths.at(i));
postToThread([this]{
offset.push_back(ui->tableWidget->item(i,1)->text().toDouble());
});
}
makePositionVector();
postToThread([this]{
plotData(ui->customPlot);
ui->export_pb->setEnabled(true);
progressBar->hide();
ui->statusBar->showMessage("Done",3000);
});
}
Modify the calculateIntegral in a similar fashion, but make sure that you don't emit progress updates too often.
Also make sure that the members that you update from the worker are not accessed elsewhere by the UI code. This can be hard since you mix UI and computations. Instead, abstract the worker out to a QObject that has no UI, and interface it to other code via signals that indicate progress/status. You will still use QtConcurrent::run within that object, but it becomes simpler to assure that no other threads access that object's private state.
To push finished results out of the worker functor, you can emit a signal that carries the results. The Data type should be cheap to copy, e.g. you can implement it using QSharedData/QSharedDataPointer. Or you can hold it via a QSharedPointer.
class Computation : public QObject {
Q_OBJECT
void work() {
Data data;
... // updates data
emit finished(data);
}
public:
Q_SLOT void compute() {
QtConcurrent::run(&Worker::work, this);
}
Q_SIGNAL void finished(Data data);
};
You can also store the results in the object, and pay attention that they are not accessed while the computations are active:
class Computation : public QObject {
Q_OBJECT
bool m_active { false };
Data m_data;
void work() {
... // updates m_data
m_active = false;
}
public:
Q_SLOT void compute() {
m_active = true;
QtConcurrent::run(&Worker::work, this);
}
const Data & data() const {
Q_ASSERT(! m_active);
return m_data;
}
};
Of course, if you store the reference to data() in the main thread and then call compute(), you'll have undefined behavior, so don't do that.
If any of the data types are an implicitly shared container, like QVector or QString, you should return them by value, and any access will be thread-safe:
QVector<MyData> data() const {
Q_ASSERT(! m_active);
return m_data;
}
Note that QFile is a proper C++ class. It releases any resources held when it gets destructed. Closing the file manually is unnecessary: the compiler is supposed to help you here, that's the whole point of C++'s object model as compared to e.g. Java's.

Why doesn't removing the last scene in cocosd2d-x trigger the scenes destructor?

I've added a Player* _player pointer to my HelloWorldScene scene in cocos2d-x v.2.2.2. I've defined class Player : public cocos2d::Object, so it's referenced counted. My create method for HelloWorldScene looks like this
Scene* HelloWorldScene::createScene(Player* player)
{
auto scene = Scene::create();
auto layer = HelloWorldScene::create();
layer->_player = player;
player->retain();
scene->addChild(layer);
return scene;
}
where player is instantiated in AppDelegate::applicationDidFinishLaunching(). Now, since I've retained _player (and I feel like a nice guy today), I've decided to release it as well:
HelloWorldScene::~HelloWorldScene()
{
if (_player)
{
_player->release();
}
}
So far so good. However, when HelloWorldScene is popped, the following is called
void Director::popScene(void)
{
CCASSERT(_runningScene != nullptr, "running scene should not null");
_scenesStack.popBack();
ssize_t c = _scenesStack.size();
if (c == 0)
{
end();
}
else
{
_sendCleanupToScene = true;
_nextScene = _scenesStack.at(c - 1);
}
}
So, whenever HelloWorldScene is the last scene in the stack, it won't get destroyed? (At least that's what it seems like from XCode.)
I'm not a C++ grandmaster, so forgive my ignorance. Yet, to me, this is quite unexpected behavior. Shouldn't the popped scene be cleaned up before program termination (by letting _sendCleanupToScene = true and having it run one more iteration)?
Clearly, I'm missing something ... If anyone could shed some light on this, I'd be thrilled! :)
So the premise of my question was wrong - I somehow got the idea that everything had to be released at program termination. But, as I re-learned yesterday, the OS will of course reclaim the allocated memory once the program terminates. Thus making releasing the last scene in the stack unnecessary.