对象之间的Qt信号导致锁定

时间:2019-02-04 12:58:19

标签: qt5

如果有人能指出我正确的方向,我会非常感激,因为我有点卡住了。我试图编写一个简单的小部件计数器程序,其中按下QPushButton(startButton)会启动一个计数器,该计数器每秒增加一个加号,并在QTextBrowser(outputBox)中显示该计数器的值。我的第一堂课主窗口包含startButton和ouputBox。我有第二类chronoClass,它从开始按钮槽中接收信号,等待一秒钟,然后递增计数器,并通过信号将值发送回显示计数器值的主窗口槽,直到这一点工作正常为止。如果我不这样做(对应于下面的代码中的注释emit countResume();),那么我得到一个计数器,该计数器递增,并在每次按下按钮后显示一秒钟的时间延迟。理想情况下,我想将信号countResume()从主窗口显示槽发送回chronos类槽以迭代计数过程,但是它不起作用。我已经阅读了在线文档和示例,但无法深入了解它。

我尝试的实现如下:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTextBrowser>
#include <QPushButton>

class QTextBrowser;
class QPushButton;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    public slots:
        void countRead(int counter);
        void on_startButton_clicked();


    private:
        Ui::MainWindow *ui;
        QTextBrowser *ui_outputBox;
        QPushButton *ui_startButton;

    signals:
        void countResume();
        void startbutton();

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <unistd.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui_outputBox = findChild<QTextBrowser*>("outputBox");
    ui_startButton = findChild<QPushButton*>("startButton");
}

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

void MainWindow::countRead(int counter)
{
    ui_outputBox -> setText(QString::number(counter));

    emit countResume();
}

void MainWindow::on_startButton_clicked()
{
    emit startbutton();
}

chronoClass.h

#ifndef CHRONOCLASS_H
#define CHRONOCLASS_H
#include<QWidget>
#include<unistd.h>



class chronoClass : public QWidget
{

    Q_OBJECT
    public:
        chronoClass();
        int counter{0};
    public slots:
        void chronoCount();

    signals:
        void countChrInc(int counter);

};

#endif // CHRONO_CLASS_H

chronoClass.cpp

#include "chronoClass.h"

chronoClass::chronoClass()
{}

void chronoClass::chronoCount()
{
    sleep(1);

    counter++;
    emit countChrInc(counter);
}

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include "philTimer.h"
#include "chronoClass.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    chronoClass c;

    QObject::connect(&w, &MainWindow::countResume,
                     &c, &chronoClass::chronoCount);
    QObject::connect(&c, &chronoClass::countChrInc,
                    &w, &MainWindow::countRead);
    QObject::connect(&w, &MainWindow::startbutton,
                   &c, &chronoClass::chronoCount);

    w.show();

    return a.exec();
}

1 个答案:

答案 0 :(得分:0)

我想您的信号问题来自chrono类中的sleep(1)函数。它将等待1s,运行1个Qt事件循环再次等待1s。与GUI的所有交互都必须在两次睡眠调用之间发生,换句话说:从不。

是否有特定的原因让您的chrono类而不是QTimer?

因为使用QTimer变得非常容易。这是一个例子,只有3个文件

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTextBrowser>
#include <QPushButton>

// That will replace your chrono class
#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    public slots:
        void timeout(); // This is connected to the timer
        void on_startButton_clicked();


    private:
        Ui::MainWindow *ui;
        QTextBrowser *ui_outputBox;
        QPushButton *ui_startButton;


        QTimer timer; // The timer object

        int counter; // Hold your counter here

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    counter(0)
{
    ui->setupUi(this);
    ui_outputBox = findChild<QTextBrowser*>("outputBox");
    ui_startButton = findChild<QPushButton*>("startButton");

    timer.setInterval(1000); // 1000ms => 1s

    //That signal is emitted every interval of the timer
    connect(&timer, &QTimer::timeout, this, &MainWindow::timeout);
}

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

void MainWindow::timeout()
{
    counter++;
    ui_outputBox -> setText(QString::number(counter));
}

void MainWindow::on_startButton_clicked()
{
    counter = 0;

    ui_outputBox -> setText("0");

    timer.start();
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    w.show();

    return a.exec();
}

无论如何,尽量避免使用睡眠功能,使用Qt之类的框架时会很痛苦,因为它会阻止主事件循环运行。尝试找到Timers类,每个现代框架都有类似的东西。

希望这会有所帮助!