gpt4 book ai didi

c++ - 在 Qt 中运行函数时如何断开所有信号?

转载 作者:行者123 更新时间:2023-11-28 00:10:05 24 4
gpt4 key购买 nike

我已经搜索了两天,但没有任何帮助。我想在功能运行时断开所有信号。主要技巧是发出信号的类和接收信号的类都是不同的类。我在类中有一个发射信号的 QPushButton 和接收信号的自定义类 Screen,它们都已连接。

管理事件的类(class sender)

    Game::Game(QWidget *parent)
: QGraphicsView(parent)
{
//.................................//some declaration

//add the main screen
Screen * screen = new Screen();
screen->SetImageOnTheScreen();
scene->addItem(screen);

//make the lunch work
QPushButton * GO = new QPushButton;
GO->setText("GO!!!");
GO->setGeometry(134,-98,134,99);
scene->addWidget(GO);
QObject::connect(GO, SIGNAL(clicked(bool)), screen, SLOT(generate()));
//want to disconnect this connection while generate() doing its job

//.................................//some declaration

}

类接收器

void Screen::SetImageOnTheScreen()
{
//.................................//some declaration
}

void Screen::setWinningIcon()
{
//.................................//some declaration
}

void Screen::generate()
{
line = 0;

std::random_shuffle(mas, mas + 27);

SetImageOnTheScreen();

if(mas[0] == mas[1] || mas[0] == mas[2] || mas[1] == mas[2])
{
line = 1;

delay();
setWinningIcon();

delay();
SetImageOnTheScreen();
}

if(mas[3] == mas[4] || mas[3] == mas[5] || mas[4] == mas[5])
{
line = 2;

delay();
setWinningIcon();

delay();
SetImageOnTheScreen();
}

if(mas[6] == mas[7] || mas[6] == mas[8] || mas[7] == mas[8])
{
line = 3;

delay();
setWinningIcon();

delay();
SetImageOnTheScreen();
}
}

我尝试使用disconnect,但什么也没有。正在尝试使用QObject::blockSignals() 同样的故事。

请提供任何帮助!

更新

game.h

#ifndef GAME_H
#define GAME_H

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPushButton>
#include "screen.h"

class Game : public QGraphicsView
{
private:
QGraphicsScene * scene;
QPushButton * GO;
Screen * screen;

protected:
virtual void wheelEvent (QWheelEvent * event);

public:
Game(QWidget *parent = 0);
~Game();

};

#endif // GAME_H

游戏.cpp

#include "game.h"
#include <QGraphicsGridLayout>
#include <QDebug>
#include <QPushButton>
#include "screen.h"
#include <QStyle>

Game::Game(QWidget *parent)
: QGraphicsView(parent)
{
scene = new QGraphicsScene(this);
scene->setSceneRect(0,0,400,200);

screen = new Screen;
screen->SetImageOnTheScreen();
scene->addItem(screen);

GO = new QPushButton;
GO->setGeometry(0,0,100,50);
GO->setText("GO");

QObject::connect(GO, SIGNAL(clicked(bool)), screen, SLOT(generate()));
//when generate is processing i want to disconnect the button "GO" and the "screen"

scene->addWidget(GO);
setScene(scene);
show();
}

void Game::wheelEvent(QWheelEvent * event)
{
if (event->type() == QEvent::Wheel)
return;
return;
}

Game::~Game()
{

}

screen.h

#ifndef SCREEN_H
#define SCREEN_H

#include <QGraphicsPixmapItem>
#include <QGraphicsTextItem>

class Screen : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT

private:
int mas[27];
int line;

QGraphicsTextItem * text;

public:
Screen(QGraphicsPixmapItem * parent = 0);
void delay(int msecs);
void setWinningIcon();
void SetImageOnTheScreen();

public slots:
void generate();
};

#endif // SCREEN_H

屏幕.cpp

#include "screen.h"
#include <QDebug>
#include <QTime>
#include <QCoreApplication>
#include "game.h"

Screen::Screen(QGraphicsPixmapItem * parent)
: QObject(), QGraphicsPixmapItem(parent)
{
for(int i = 0, j =1; i < 27; i++, j++)
{
if(j == 10)
j = 1;

mas[i] = j;
}

line = 0;
text = new QGraphicsTextItem(this);
}

void Screen::delay(int msecs)
{
QTime dieTime= QTime::currentTime().addMSecs(msecs);
while (QTime::currentTime() < dieTime)
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

void Screen::setWinningIcon()
{
switch(line)
{
case 1:
text->setPlainText("TEST_#2 I'm NOT allowed to press /GO/ \nfor 3 seconds but i can");
text->setDefaultTextColor(Qt::red);
break;
case 2:
text->setPlainText("TEST_#3 I'm NOT allowed to press /GO/ \nfor 3 seconds but i can");
text->setDefaultTextColor(Qt::red);
break;
case 3:
text->setPlainText("TEST_#4 I'm NOT allowed to press /GO/ \nfor 3 seconds but i can");
text->setDefaultTextColor(Qt::red);
break;
}
}

void Screen::SetImageOnTheScreen()
{
text->setPlainText("TEST_#1 I'm ALLOWED to press /GO/");
text->setPos(0,50);
text->setDefaultTextColor(Qt::green);
}

void Screen::generate()
{
//In here i want to prevent to press "GO" while "generate()" is processing

//Screen::grabMouse(); //here it is my solution

std::random_shuffle(mas, mas + 27);

SetImageOnTheScreen();

if(mas[0] == mas[1] || mas[0] == mas[2] || mas[1] == mas[2])
{
line = 1;

delay(500);
setWinningIcon();

delay(3000);
SetImageOnTheScreen();
}

if(mas[3] == mas[4] || mas[3] == mas[5] || mas[4] == mas[5])
{
line = 2;

delay(500);
setWinningIcon();

delay(3000);
SetImageOnTheScreen();
}

if(mas[6] == mas[7] || mas[6] == mas[8] || mas[7] == mas[8])
{
line = 3;

delay(500);
setWinningIcon();

delay(3000);
SetImageOnTheScreen();
}

//Screen::ungrabMouse(); //here it is my solution
}

main.cpp

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

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

return a.exec();
}

最佳答案

更新

我已经获取了您发布的最新代码并对其进行了一些更改。

总结

让我们从您的评论开始:

i can't reach "GO" button from the screen.cpp unless it is global. And i do not want to use any globals.

您在尝试避免全局变量方面走在正确的轨道上。但是,我认为您的 Screen 类真的需要了解您的 GO 按钮。相反,您可以按照我在 our discussion 中的建议进行操作,也就是说,不是connect将您的GO按钮直接连接到您的Screengenerate()插槽,您应该将按钮 connectGame 类中的单独 on_button_clicked 事件处理程序,它将:

  1. 禁用或断开 GO 按钮,
  2. 调用您的screengenerate() 方法,并且
  3. generate() 返回后重新启用或重新连接按钮。

这也意味着 generate() 可能不再需要是一个插槽,但这取决于您。

您的代码 - 包含我建议的更新

我做了以下更改:

game.h 中,我向 Game 类添加了一个插槽:

private slots:
void on_go_clicked();

game.cpp中,我添加了如下实现:

void Game::on_go_clicked()
{
GO->setEnabled(false); // or QObject::disconnect(....)
screen->generate();
GO->setEnabled(true); // or QObject::connect(....)
}

并且也替换您的构造函数的QObject::connect调用为下面的调用:

QObject::connect(GO, SIGNAL(clicked(bool)), this, SLOT(on_go_clicked()));

现在,您可以让您的 Screen 类不知道您的 GO 按钮的存在,这意味着更少的耦合和复杂性,但仍然可以阻止用户使用同时你的按钮,这就是你想要的。

原始回复

基本上,您需要按如下方式使用QObject::disconnect:

QObject::disconnect(emitter, SIGNAL(signalName()), receiver, SLOT(slotName()));

您可以在事件得到处理后在插槽中执行此操作。

断开感兴趣对象之间的信号/槽是一种比尝试断开整个应用程序全局所有信号更好的方法,原因有多种,包括可能导致错误的意外副作用或其他意外行为。

在您的特定示例中,您有:

QObject::connect(GO, SIGNAL(clicked(bool)), screen, SLOT(generate()));

所以要断开连接,你可能只需要在开始处理的时候这样写:

QObject::disconnect(GO, SIGNAL(clicked(bool)), screen, SLOT(generate()));

然后在完成处理后重新连接。

或者,正如@Matt 在评论中所说,您可以简单地禁用 用户界面中的按钮小部件,而不是弄乱信号。如果用户无法点击按钮,则用户无法发出信号。

这可能是一个更简单、更可靠的解决方案。

信号阻塞更新

如果您仍想连接/断开连接并且您使用的是 Qt 5.3+,那么您应该使用 QSignalBlocker ,它还负责将事物保存和恢复到以前的状态。引用他们的文档:

{
const QSignalBlocker blocker(someQObject);
// no signals here
}

is thus equivalent to

const bool wasBlocked = someQObject->blockSignals(true);
// no signals here
someQObject->blockSignals(wasBlocked);

工作示例代码

下面是一个简短的示例应用程序,其中包含一个带有 QPushButtonQMainWindow 中的 QListWidget 的窗口。

主窗口.cpp

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

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

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

void MainWindow::on_button_clicked()
{
ui->listWidget->addItem(QString("Clicked"));

// this is the important line :o
QObject::disconnect(ui->button, SIGNAL(clicked(bool)), this, SLOT(on_button_clicked()));
}

主窗口.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:
// this naming convention allows Qt to
// create connections automatically
void on_button_clicked();

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

main.cpp

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

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

return a.exec();
}

主窗口.ui

如果需要,您可以复制粘贴 .ui 文件的内容以重现简单布局。它在下面:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="button">
<property name="text">
<string>Click Me</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

关于c++ - 在 Qt 中运行函数时如何断开所有信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33594360/

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