0

I have a QT-project (using C++) where instances of a certain user-defined QGraphicsItem called Person move around the scene. Sometimes those Persons interact so that some of them change color.

Now I want to put a text field in the window and display counts of how many I have of each color. But since the change occurs within the call to the Person::advance-method I want to create a text field that can be updated from within these.

I could easily display some text by adding the following code to my main.cpp:

    QGraphicsSimpleTextItem *text1 = new QGraphicsSimpleTextItem;
    text1->setPos(-200, -150);
    text1->setText("This is an arbitrary English sentence");
    scene.addItem(text1);

but I do not know how to access and alter the text of this variable text1 from within the advance-method of the Persons in my scene. What is a good strategy for this?

Should I create a global variable keeping track of the count, and if I do, how can I then update the text field? Or should the text not even be on my QGraphicsScene, but rather be defined in some other more appropriate place where it is callable from everywhere in the program? Is there a generic way of doing this?

String
  • 207
  • 1
  • 2
  • 8
  • 1
    Seems to be a good job for qt's signal-slot system – simon May 22 '15 at 08:31
  • @thuga: OK, no problem. – String May 22 '15 at 08:35
  • @simon: Thank you! I will try to read more about it. Although my program already uses a `QTimer`, I am not that familiar with qt's signal-slot system yet, since the `QTimer`-statements was simply taken from another example, so I do not yet understand exactly how it works/how the syntax and structure is. – String May 22 '15 at 08:38
  • @thuga: OK, but does that mean that I have to pass that pointer to every single `Person`? Right now I only have a `Person`-class and not a mother class called `Persons`, so for all instances of `Person` to know the reference, I would have to pass it on each initialization of a `Person`, correct? – String May 22 '15 at 08:40
  • 1
    If you use Qt, you will definitely need signals/slots, it's better to get familiar with them as soon as possible. – simon May 22 '15 at 08:41
  • 2
    It seems my initial comment was correct. You could subclass `QGraphicsObject` instead of `QGraphicsItem`, that would allow you to use signals from within the `Person` class. Then just emit a signal to a slot that counts the items and changes the text of `text1`. – thuga May 22 '15 at 08:41
  • @simon: No doubt about that! I am new to Qt, but I will get there, eventually. The sooner the better! – String May 22 '15 at 08:42
  • @thuga: From reading the first line of the documentation of the `QGraphicsObject` class, it seems that you are absolutely correct! Would it make sense to make a mother class called `Persons` (subclass to `QGraphicsObject`) just to give it the single goal to store the reference to the text fields that display counts and then subclass it by `Person`? – String May 22 '15 at 08:46
  • @thuga: I urge both of you to turn your comments into answers. You provided exactly the information, I was looking for. – String May 22 '15 at 08:50
  • @simon: I urge both of you to turn your comments into answers. You provided exactly the information, I was looking for. – String May 22 '15 at 08:50

1 Answers1

1

You could subclass QGraphicsObject instead of QGraphicsItem, that would allow you to use signals from within the Person class. Then just emit a signal to a slot that counts the items and changes the text of text1.

What I would do is move your graphics view to a new QWidget type class (like QMainWindow). This is to make it easier to handle signals and slots, and it will also allow you to use member variables. It will also be cleaner than doing everything in main.cpp.

You could have your text1 variable as a member variable of this MainWindow class. This would make accessing it easy.

Your slot in the MainWindow class could look something like this:

MainWindow::countItems()
{
    int redcount = 0;
    int greencount = 0;
    int bluecount = 0;
    // iterate through your `Person` items and check their colors and count them
    text1->setText(QString("Red items: %1, Green items: %2, Blue items: %3").arg(redcount).arg(greencount).arg(bluecount));
}

You can improve the logic, but this is just a basic example.

thuga
  • 12,601
  • 42
  • 52
  • Thank you very much! There is a lot to learn when you are new to Qt, but this took me a step forward. – String May 22 '15 at 08:59