1

this is my simple code:

I've created a new scene, view and QPixmapItem

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();

and next I've created a new QStateMachine with two 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();
  1. I want to show the view in s1 and set object1 visible.

  2. With a mouse click on the scene I've added a transition to s2.

  3. In s2 I want to hide only object1.

How can I do this? Someone can help me with a small tutorial?

I'm using Qt 5.6.0 with MinGW 4.9.2 32bit.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Have you read [this answer](http://stackoverflow.com/a/37667951/1329652)? It seems like you're asking very similar questions over and over again... – Kuba hasn't forgotten Monica Jun 07 '16 at 16:44
  • Yes, I 've read the answer and I realized that I can not assign a `view` to a `QState`. My problem is I have a `scene` and inside that `scene` I've `QGraphicsPixmapObject`. It's a card game so I have to hide and show that object 20 times and I can't do it with a `for` so you have told me to use `QStateMachine`. Now I've created `QState` and `QStateMachine` but I'm not able to use it. I'added transition from `s1` to `s2` with `signals`, and now I wat to specify what object I want to show in each `QState`. Is it possible to do ? – Davide Ferrari Jun 07 '16 at 16:57
  • "I have to hide and show that object 20 times" Same one? Do you mean that you wish to blink it 20 times? Or do you wish to show 20 different objects in sequence? – Kuba hasn't forgotten Monica Jun 07 '16 at 17:17
  • it's a card game so I have 10 `QGraphicsPixmapItem` in the scene. To play the game I want to show the cards, wait for the player chose, and move that card in center of the scene. After that I want to reload the previous situation and repeat the same thing for 20 times – Davide Ferrari Jun 07 '16 at 17:23
  • You don't care about mouse clicks perhaps. You care that a card is *selected*, and then you move it. The interpretation of a mouse click on an item as item selection is already done by the graphics view framework. You're really hung up about such low level details but never explain how exactly you want your game to work. You never wanted to switch states when the mouse is merely pressed on the scene. You wanted to use mouse to select a card, and then react to that selection, or at least you wanted to react to a mouse being clicked on an item, not scene/view! That's a big difference! – Kuba hasn't forgotten Monica Jun 07 '16 at 17:26
  • Yes I want to do that. As I said I've never worked with qt and so many things are new and often I do conceptual and logical errors. To help you figure out what I want to do I'll put a link to a similar game to the one that I want to develop: http://qt-apps.org/content/show.php/QBriscola?content=83155 – Davide Ferrari Jun 07 '16 at 17:32
  • I'll have something for you later :) – Kuba hasn't forgotten Monica Jun 07 '16 at 17:33
  • thanks for all the help :) – Davide Ferrari Jun 07 '16 at 17:35

1 Answers1

1

Each QState has entered and exited signals that you can connect functors to. This is a common idiom in modern Qt 5 code. The functors can be concisely given using lambda expressions, where you can invoke arbitrary operations on non-objects, such as on the QPixmapItem. If QPixmapItem derived from QGraphicsObject, you could use QState::assignProperty to assign the desired visibility state instead of calling show() and hide().

Below is a complete example.

// https://github.com/KubaO/stackoverflown/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_layout{this};
   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 pix{128, 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 app{argc, argv};
   Window w;
   w.show();
   return app.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313