Duanne
Duanne

Reputation: 137

QT push button / stop button

I have a push button that I'd like to change to a stop button when clicked. Currently the button's text says "auto fire", it runs an endless loop and it's text changes to "stop auto fire" when clicked. My problem is breaking the endless loop by clicking/pressing this button again after the text changes.

Code so far:

void Cpp_Fire::on_auto_fire_clicked()
{
    while(true)
    {
        ui->auto_fire->setText("Stop Auto Fire");
        on_manual_fire_clicked();
    }
}

I tried inserting a different slot into the loop above that runs when after the button is pressed (it runs when the button is released to be precise) but I couldn't get it to work. I know this could be done with signals/slots and a separate stop button but I'm unfamiliar with that method and I prefer the method I described.

Upvotes: 2

Views: 3611

Answers (2)

Bernhard Heinrich
Bernhard Heinrich

Reputation: 120

I fully agree Michael's answer.

  • This will also affect the repaint! (Try to put some windows over your application, while in endless-loop: you should see repaint problems).

  • Don't use endless-loops, specially not within slots!

  • Try QTimer, or move object to a QThread.

  • While in such loop: Give GUI-Thread some time. You can call QCoreApplication::processEvents().. But be careful with this.

A simple (still poor) solution with QTimer could be: (I found, Michael entered an example in his answer. - Use it.).

//have a QTimer 'timer' in the class, and a connect signal 
//timer.timeout() to 'onSingleShotFired()'
void Cpp_Fire::on_auto_fire_clicked()
{
    if ( ui->auto_fire->text() == "Stop Auto Fire" )
    {    
        timer.stop();
        ui->auto_fire->setText("Start Auto Fire");
    } 
    else 
    {
        //MSEC_AUTOFIRE_DELAY is the delay between the autofire-shots
        timer.start( MSEC_AUTOFIRE_DELAY );
        ui->auto_fire->setText("Stop Auto Fire");
    }
}

Upvotes: 0

Michael Vincent
Michael Vincent

Reputation: 1660

The problem with your endless loop is that nothing else gets a chance to work.

One approach you could use is to use a QTimer with a short interval to call the on_manual_fire_clicked() method, then have the on_auto_fire_clicked() method be responsible for changing the text on the button and enabling / disabling the timer.

The ui should get enough time to respond to clicks etc if you do it that way.

edit:

For more info on using QTimer have a look at this page:

How to use QTimer

or this tutorial:

http://www.bogotobogo.com/Qt/Qt5_QTimer.php

Here's some code:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();
    void timerslot();

private:
    Ui::MainWindow *ui;

    QTimer* myTimer;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QTimer>
#include<QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    myTimer = new QTimer(this);
    myTimer->setInterval(500);
    myTimer->setSingleShot(false);
    connect(myTimer, SIGNAL(timeout()), this, SLOT(timerslot()));
    myTimer->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::timerslot()
{
    qDebug() << "timeslot";
}

void MainWindow::on_pushButton_clicked()
{
    if ( this->myTimer->isActive() == true ) {
        this->myTimer->stop();
        ui->pushButton->setText("Start");
    } else {
        this->myTimer->start(500);
        ui->pushButton->setText("Stop");
    }
}

I hope you get the idea and can convert it to your needs.

Upvotes: 3

Related Questions