gpt4 book ai didi

qt - 插槽只用一个线程互相中断?

转载 作者:行者123 更新时间:2023-12-02 04:45:17 25 4
gpt4 key购买 nike

我有一个使用由 mousemovement 和 mousewheel 调用的插槽的小示例。

现在我遇到的问题是,当我同时缩放和移动时,首先调用 onZoom-slot,然后在完成之前调用 onMouseMoved-slot。这导致第一个插槽锁定互斥锁(在我的原始程序中被另一个线程使用),第二个插槽等待它。

我怎样才能防止插槽相互中断(为什么它们首先要这样做,因为它们在同一个线程中?)。

我阅读了一些有关使用 Qt::QueuedConnection 的内容,但这会导致访问冲突异常。

主要.cpp

#include "ppi.h"
#include <QtGui/QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PPI w;
w.show();
return a.exec();
}

ppi.h

#ifndef PPI_H
#define PPI_H

#include <QtGui/QMainWindow>
#include <QGraphicsView>
#include <QDebug>
#include <QWheelEvent>
#include <QgraphicsEllipseItem>
#include <QMouseEvent>
#include <QMutex>
#include <QThread>
#include <QGraphicsSceneMouseEvent>

//#include "ui_ppi.h"

class PPIView : public QGraphicsView
{
Q_OBJECT

public:
PPIView(QWidget * parent = 0)
: QGraphicsView(parent)
{};
~PPIView(){};

private slots:
void wheelEvent(QWheelEvent *event)
{emit zoom(event);};

signals:
void zoom(QWheelEvent *event);

};

class PPIScene : public QGraphicsScene
{
Q_OBJECT

public:
PPIScene(QObject *parent)
: QGraphicsScene(parent)
{};

~PPIScene(){};

private:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{emit mouseMoved(event);};

signals:
void mouseMoved(QGraphicsSceneMouseEvent *event);
};

class PPI : public QMainWindow
{
Q_OBJECT

public:
PPI(QWidget *parent = 0, Qt::WFlags flags = 0)
: QMainWindow(parent, flags)
{
//ui.setupUi(this);
//ppiScene is inherited from QGraphicsScene, overriding mouseMoveEvent so it emits mouseMoved();
ppiScene = new PPIScene(this);
gVPPI = new PPIView(this);
gVPPI->setMinimumSize(1024,1024);
gVPPI->show();

test = new QGraphicsEllipseItem(-10, -10, 20, 20);
ppiScene->addItem(test);

gVPPI->adjustSize();

connect(ppiScene, SIGNAL(mouseMoved(QGraphicsSceneMouseEvent*)), this, SLOT(onMouseMoved(QGraphicsSceneMouseEvent*)));
connect(gVPPI, SIGNAL(zoom(QWheelEvent*)), this, SLOT(onZoom(QWheelEvent*)));

//ui.gVPPI is inherited from QGraphicsView, overriding wheelEvent, so it emits zoom()
gVPPI->setScene(ppiScene);
gVPPI->setMouseTracking(true);
};

~PPI(){};

QMutex mutex;

private:
//Ui::ppiClass ui;
PPIScene* ppiScene;
PPIView *gVPPI;

QGraphicsEllipseItem *test;

protected slots:
void onZoom(QWheelEvent *event)
{
qDebug() << "Zoom lock" << QThread::currentThreadId();
mutex.lock();
qDebug() << "Zoom locked";

if(event->delta() > 0)
gVPPI->scale(1.01, 1.01);
else
gVPPI->scale(1/1.01, 1/1.01);

qDebug() << "Zoom unlock";
mutex.unlock();
qDebug() << "Zoom unlocked";
};

void onMouseMoved(QGraphicsSceneMouseEvent *event)
{
qDebug() << "Move lock" << QThread::currentThreadId();
mutex.lock();
qDebug() << "move locked";

test->setPos(test->pos()+event->scenePos()-event->lastScenePos());

qDebug() << "Move unlock";
mutex.unlock();
qDebug() << "Move unlocked";
};
};

#endif // PPI_H

输出qDebug():

Move lock 0x1514 
move locked
Move unlock
Move unlocked
Move lock 0x1514
move locked
Move unlock
Move unlocked
Zoom lock 0x1514
Zoom locked
Move lock 0x1514

最佳答案

您可以使用QObject::blockSignals 来阻止特定对象的信号,但我认为您对代码的工作方式有错误的认识。

有一个 GUI 线程,如果 signals + slots 在同一个 GUI 线程中,就像你的情况一样,然后他们按顺序调用。如果 PPI::onZoom 将在另一个线程上下文中调用,那么您就会遇到问题,因为在非 GUI 线程中使用 ui.gVPPI->scale 之类的东西不是允许并可能导致断言崩溃,或者只是崩溃,或者随机工作,UB 原样。

当您看到 slot 1 被调用时,然后在 slot 1 slot 2 完成之前被调用的情况可能是因为您在 slot 1 中调用一些函数调用另一个函数等,在调用 signal 2 的深处调用一些函数,它发出 slot 2 的调用,只需设置调试器中的断点并找出发生了什么。

关于qt - 插槽只用一个线程互相中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33567668/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com