Кнопка QT/кнопка остановки

У меня есть кнопка, которую я хотел бы изменить на кнопку остановки при нажатии. В настоящее время текст кнопки говорит «автоматический огонь», он запускает бесконечный цикл, и при нажатии его текст меняется на «остановить автоматический огонь». Моя проблема заключается в том, чтобы разорвать бесконечный цикл, снова нажав/нажав эту кнопку после изменения текста.

Код пока:

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

Я попытался вставить другой слот в цикл выше, который запускается после нажатия кнопки (точнее, запускается, когда кнопка отпускается), но я не смог заставить его работать. Я знаю, что это можно сделать с помощью сигналов/слотов и отдельной кнопки остановки, но я не знаком с этим методом и предпочитаю метод, описанный мной.


person Duanne    schedule 22.01.2015    source источник


Ответы (2)


Проблема с вашим бесконечным циклом в том, что больше ничего не работает.

Один из подходов, который вы можете использовать, — это использовать QTimer с коротким интервалом для вызова метода on_manual_fire_clicked(), а затем использовать метод on_auto_fire_clicked(), отвечающий за изменение текста на кнопке и включение/выключение таймера.

Пользовательский интерфейс должен получить достаточно времени, чтобы реагировать на клики и т. д., если вы делаете это таким образом.

редактировать:

Для получения дополнительной информации об использовании QTimer посетите эту страницу:

Как использовать QTimer

или этот учебник:

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

Вот код:

главное окно.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

главное окно.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");
    }
}

Надеюсь, вы поняли идею и сможете преобразовать ее в свои нужды.

person Michael Vincent    schedule 22.01.2015
comment
Не могли бы вы объяснить дальше. Я никогда не использовал QTimer. Если я использую таймер, как можно отключить цикл при нажатии кнопки? - person Duanne; 22.01.2015
comment
Спасибо за вашу помощь. Я использовал радиокнопку вместо кнопки, когда она проверена, время идет, если она не отмечена, она останавливается. - person Duanne; 23.01.2015

Я полностью согласен с ответом Майкла.

  • Это также повлияет на перекраску! (Попробуйте поместить несколько окон поверх вашего приложения, находясь в бесконечном цикле: вы должны увидеть проблемы с перерисовкой).

  • Не используйте бесконечные циклы, особенно внутри слотов!

  • Попробуйте QTimer или переместите объект в QThread.

  • Находясь в таком цикле: дайте GUI-Thread некоторое время. Вы можете вызвать QCoreApplication::processEvents().. Но будьте осторожны с этим.

Простое (все еще плохое) решение с QTimer может быть следующим: (я нашел , Михаил в свой ответ ввел пример.- Используйте его.).

//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");
    }
}
person Bernhard Heinrich    schedule 22.01.2015
comment
QCoreApplication::processEvents редко бывает хорошей идеей, особенно внутри циклов. Например, объект this может быть удален после вызова QCoreApplication::processEvents. Затем, если вы попытаетесь использовать переменную-член или функцию после этого, вы обречены. - person thuga; 23.01.2015