QTimer定时器问题分析

QObject::killTimer: timers cannot be stopped from another thread

原因:出现这个错误的原因在于在次线程中执行主线程对象的一些操作引起的

使用定时器的注意事项

  1. 不能跨线程启动定时器和停止定时器。
  2. 不能跨线程启动一个定时器关联的对象,但在另一个线程释放此定时器关联的对象,即定时器相关的逻辑和对象只能用在一个线程中。

例子分析:

//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
#include "autosampleservice.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void Init();
private slots:
    void on_btnStop_clicked();
signals:
    void sigStop();
    void sigInit();
private:
    Ui::MainWindow *ui;
    AutoSampleService *pAutoSampleService=nullptr;
};
#endif // MAINWINDOW_H

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


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qDebug()<<"MainWindow----current thread id:"<<QThread::currentThreadId()<<endl;
    pAutoSampleService=new AutoSampleService();
    connect(this,SIGNAL(sigInit()),pAutoSampleService,SLOT(SlotInit()),Qt::QueuedConnection);
    connect(this,SIGNAL(sigStop()),pAutoSampleService,SLOT(Stop()),Qt::QueuedConnection);
    Init();
}
void MainWindow::Init()
{
    QThread *t=new QThread();
    pAutoSampleService->moveToThread(t);
    t->start();
    //emit sigInit();
    pAutoSampleService->SlotInit();
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::on_btnStop_clicked()
{
    emit sigStop();
}
//autosampleservice.h
#ifndef AUTOSAMPLESERVICE_H
#define AUTOSAMPLESERVICE_H
#include<QTimer>
#include<QObject>

class AutoSampleService:public QObject
{
    Q_OBJECT
public:
    AutoSampleService();
public slots:
    void SlotInit();
    void RecvTimeOut();
    void Stop();
private:
    QTimer* RecvTimer=nullptr;

};

#endif // AUTOSAMPLESERVICE_H
#include "autosampleservice.h"
#include<QThread>
#include<QDebug>

AutoSampleService::AutoSampleService()
{

}
void AutoSampleService::SlotInit()
{
    qDebug()<< "AutoSampleService Init----current thread id:"<<QThread::currentThreadId()<<endl;
    RecvTimer=new QTimer();
    RecvTimer->start(5000);
    connect(RecvTimer,SIGNAL(timeout()),this,SLOT(RecvTimeOut()));
}
void AutoSampleService::RecvTimeOut()
{
    qDebug()<< "RecvTimeOut----current thread id:"<<QThread::currentThreadId()<<endl;
}
void AutoSampleService::Stop()
{
    qDebug()<< "AutoSampleService Stop----current thread id:"<<QThread::currentThreadId()<<endl;
    RecvTimer->stop();
}

点击停止按钮后,运行结果如下:
在这里插入图片描述

原因分析

因pAutoSampleService->SlotInit() 主线程中直接调用SlotInit函数创建RecvTimer定时器,即RecvTimer定时器启动在主线程;当点击停止按钮后,在子线程进行RecvTimer定时器停止操作

解决方法:

调整上述代码

void MainWindow::Init()
{
    QThread *t=new QThread();
    pAutoSampleService->moveToThread(t);
    t->start();
    emit sigInit();
}

运行正常:

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用PyQt5可以轻松地设计动态分析数据界面。以下是一个简单的示例: ``` import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem from PyQt5.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("动态分析数据界面") self.setGeometry(100, 100, 500, 500) self.table = QTableWidget(self) self.table.setGeometry(50, 50, 400, 400) self.table.setColumnCount(3) self.table.setHorizontalHeaderLabels(["数据1", "数据2", "数据3"]) data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # 这里假设有一些数据 self.populateTable(data) self.show() def populateTable(self, data): self.table.setRowCount(len(data)) for i, row in enumerate(data): for j, item in enumerate(row): tableItem = QTableWidgetItem(str(item)) tableItem.setTextAlignment(Qt.AlignCenter) self.table.setItem(i, j, tableItem) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() sys.exit(app.exec_()) ``` 此示例创建了一个包含3列的表格,并向其中插入了一些数据。您可以根据您的需求修改表格的大小、行数和列数。populateTable方法可以根据您的数据动态填充表格。通过调整data变量的值,您可以添加、删除或更改表格中显示的数据。 这个示例只是用PyQt5设计动态分析数据界面的其中一种方法。您可以根据自己的需求进行灵活的修改和扩展。 ### 回答2: PyQt5是一个用于开发图形用户界面(GUI)的Python库,具有丰富的功能和强大的功能。在设计动态分析数据界面时,以下是一种可能的实现方式: 1. 导入所需的PyQt5模块和其他必要的Python模块。 ```python from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel from PyQt5.QtCore import Qt import matplotlib.pyplot as plt import numpy as np ``` 2. 创建一个主窗口类,并在构造函数中设置窗口的一些基本属性。 ```python class DataAnalysisWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("动态数据分析界面") self.setGeometry(100, 100, 800, 600) ``` 3. 在主窗口中添加一个标签,用于显示数据的图表。 ```python self.label = QLabel(self) self.label.setGeometry(50, 50, 700, 500) ``` 4. 创建一个用于动态更新数据的函数,并将其绑定到一个定时器事件上。 ```python def update_data(self): x = np.linspace(0, 10, 100) y = np.sin(x) plt.plot(x, y) plt.xlabel("X轴") plt.ylabel("Y轴") plt.title("动态数据分析图表") plt.grid(True) plt.savefig("temp.png") plt.clf() self.label.setPixmap(QPixmap("temp.png")) ``` 5. 在主窗口的`showEvent`事件中启动定时器,并设置定时器的时间间隔。 ```python def showEvent(self, event): self.timer = QTimer(self) self.timer.timeout.connect(self.update_data) self.timer.start(1000) # 每1秒更新一次数据 ``` 6. 在`main`函数中创建应用程序对象并显示主窗口。 ```python if __name__ == "__main__": app = QApplication([]) window = DataAnalysisWindow() window.show() app.exec_() ``` 这样,当程序运行时,会在主窗口上显示一个动态的数据分析图表,每秒钟更新一次数据。 请注意,以上代码只是一种示例实现,你可以根据自己的需求进行修改和扩展,例如添加其他的图表类型、增加更多的数据分析功能等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值