QStateMachine 如何在不同的 QState 中显示和隐藏 QGraphicsView 和 QObject

Posted

技术标签:

【中文标题】QStateMachine 如何在不同的 QState 中显示和隐藏 QGraphicsView 和 QObject【英文标题】:QStateMachine how to show and hide QGraphicsView and QObject in different QState 【发布时间】:2016-06-07 16:10:23 【问题描述】:

这是我的简单代码:

我创建了一个新的sceneviewQPixmapItem

QGraphicsScene *scena = new QGraphicsScene();
QGraphicsPixmapItem *object1= new QGraphicsPixmapItem();
object1->setPixmap(QPixmap(":/prova/prova.png"));

QGraphicsView *view = new QGraphicsView();

view->setScene(scena);
scena->addItem(object1);

view->show();

接下来我创建了一个新的QStateMachine 和两个QState

QStateMachine *machine = new QStateMachine();
QState *s1 = new QState();
QState *s2 = new QState();

machine -> addState(s1);
machine -> addState(s2);

//mouse click in a void mousePressEvent
s1 -> addTransition(this,SIGNAL(mouseclick()),s2);

machine -> start();

    我想在s1 中显示view 并设置object1 可见。

    通过在场景上单击鼠标,我添加了到 s2 的过渡。

    s2 我只想隐藏object1

我该怎么做?有人可以帮我做一个小教程吗?

我正在使用带有 MinGW 4.9.2 32 位的 Qt 5.6.0。

【问题讨论】:

你读过this answer吗?看起来你一遍又一遍地问非常相似的问题...... 是的,我已经阅读了答案,我意识到我不能将view 分配给QState。我的问题是我有一个scene,在那个scene 里面我有QGraphicsPixmapObject。这是一个纸牌游戏,所以我必须隐藏和显示该对象 20 次,而我不能用 for 来做到这一点,所以你告诉我使用 QStateMachine。现在我创建了QStateQStateMachine,但我无法使用它。我使用signals 添加了从s1s2 的转换,现在我要指定要在每个QState 中显示的对象。有可能吗? "我必须隐藏和显示该对象 20 次" 同一个?你的意思是你希望它闪烁 20 次?或者您希望按顺序显示 20 个不同的对象? 这是一款纸牌游戏,所以我在场景中有 10 个QGraphicsPixmapItem。要玩我想展示牌的游戏,等待玩家选择,然后将那张牌移到场景中心。之后我想重新加载以前的情况并重复同样的事情20次 您可能并不关心鼠标点击。你关心一张卡片被选中,然后你移动它。图形视图框架已经将鼠标单击项目解释为项目选择。你真的对如此低级的细节很感兴趣,但从不解释你希望你的游戏如何工作。当鼠标在场景中按下时,你永远不想切换状态。您想使用鼠标选择一张卡片,然后对该选择做出反应,或者至少您想对鼠标单击项目做出反应,而不是场景/视图!这是一个很大的不同! 【参考方案1】:

每个QState 都有enteredexited 信号,您可以将函子连接到它们。这是现代 Qt 5 代码中的常见习语。可以使用 lambda 表达式简洁地给出函子,您可以在其中对非对象调用任意操作,例如在 QPixmapItem 上。如果QPixmapItem 派生自QGraphicsObject,您可以使用QState::assignProperty 来分配所需的可见性状态,而不是调用show()hide()

下面是一个完整的例子。

// https://github.com/KubaO/***n/tree/master/questions/scenestate-37684315
#include <QtWidgets>

void addTransition(QState * src, QObject * eventSource, QEvent::Type type, QAbstractState * dst)

   auto transition = new QEventTransition(eventSource, type);
   transition->setTargetState(dst);
   src->addTransition(transition);


struct Window : public QWidget 
   QHBoxLayout m_layoutthis;
   QGraphicsScene m_scene;
   QGraphicsPixmapItem m_item;
   QGraphicsView m_view&m_scene;

   QStateMachine m_mach;
   QState s1&m_mach;
   QState s2&m_mach;
   Window() 
      m_layout.addWidget(&m_view);
      QPixmap pix128, 128;
      QPainter p&pix;
      p.setBrush(Qt::white);
      p.drawRect(pix.rect().adjusted(0,0,-1,-1));
      p.drawText(pix.rect(), "Hello");
      m_item.setPixmap(pix);
      m_scene.addItem(&m_item);

      // I want to show the view in s1...
      s1.assignProperty(&m_view, "visible", true);
      // and set object1 visible.
      s1.connect(&s1, &QState::entered, [&] m_item.show(); );
      // With a mouse click on the scene I've added a transition to s2.
      addTransition(&s1, &m_view, QEvent::MouseButtonPress, &s2);
      // In s2 I want to hide only object1.
      s2.connect(&s2, &QState::entered, [&] m_item.hide(); );
      m_mach.setInitialState(&s1);
      m_mach.start();
   
;

int main(int argc, char ** argv) 
   QApplication appargc, argv;
   Window w;
   w.show();
   return app.exec();

【讨论】:

以上是关于QStateMachine 如何在不同的 QState 中显示和隐藏 QGraphicsView 和 QObject的主要内容,如果未能解决你的问题,请参考以下文章

使用 QStateMachine 在菜单屏幕之间切换

QStateMachine 中的事件是如何管理的?

同步 QStateMachine

QT动画介绍(有例子可以下载)

如何与复选框操作进行交互? (带有 QStandardItemModel 的 QTableView)

QTreeWidget:如何动态更改 sizeHint?