PDA

View Full Version : Calling setPos() on custom QGraphicsPixmapItem doesn't update item in GraphicsScene



jzacks524
19th April 2020, 22:42
Hello, I'm working on a little poker game and I am having a graphical glitch I would like to understand better and fix. For my "Card" class I subclassed QGraphicsPixmap items and added a 52-card "deck" to my QGraphicsScene.

During runtime, I click on a button to deal the cards which then calls setPos() on the first three to simulate a flop.

The problem is, the cards don't appear to fully draw themselves right away (see photos). When I resize the window suddenly they pop into full view. The QGraphicsView is not being updated when a card position changes.

I tested calling setPos() on my background image which is a regular QGraphicsPixmap item and it moves properly and immediately updates the entire QGraphicsScene, so I'm thinking it has to be some error I've made while creating my "Card" class, but I'm not sure what I'm doing wrong.

pokerTable.cpp (relevant portion)

void PokerTable::dealFlop()
{
m_deck->burnCard();

m_flopCard1 = m_deck->dealCard(); // dealCard() returns a pointer to a Card, stored in these data members
m_flopCard2 = m_deck->dealCard();
m_flopCard3 = m_deck->dealCard();

m_flopCard1->setPos(m_flopCard1Position); //QPointF positions
m_flopCard2->setPos(m_flopCard2Position);
m_flopCard3->setPos(m_flopCard3Position);
}

Card.h

#ifndef CARD_H
#define CARD_H

#include <QGraphicsPixmapItem>
#include <QLabel>

class Card : public QGraphicsPixmapItem
{
public:
enum class Rank
{
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING,
ACE,
MAX_RANKS
};

enum class Suit
{
CLUBS,
DIAMONDS,
HEARTS,
SPADES,
MAX_SUITS
};

Card();

Card(const Card &card2);

Card& operator=(const Card &card);

int getCardValue();

void setRank(int rank);

void setSuit(int suit);

void setTexture(QPixmap texture);

void setSprite();

void printCard();

protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;

virtual QRectF boundingRect() const override;

private:
QPixmap m_texture;
QPointF m_sprite;

Rank m_rank;
Suit m_suit;
};

#endif // CARD_H

Card.cpp (relevant portion)

#include "Card.h"
#include <QPainter>
#include <iostream>

Card::Card()
: m_sprite{ QPointF(0, 0) }
{
setScale(0.2);
setFlag(ItemSendsGeometryChanges, true);
}

Card::Card(const Card &card2)
{
m_texture = card2.m_texture;
m_sprite = card2.m_sprite;

m_rank = card2.m_rank;
m_suit = card2.m_suit;
}

Card& Card::operator=(const Card &card)
{
m_texture = card.m_texture;
m_sprite = card.m_sprite;

m_rank = card.m_rank;
m_suit = card.m_suit;

return *this;
}

void Card::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawPixmap(x(), y(), m_texture, m_sprite.x(), m_sprite.y(), 560, 780);
}

QRectF Card::boundingRect() const
{
return QRectF(0, 0, 560, 780);
}

jzacks524
20th April 2020, 17:31
I still don't know what I'm doing wrong, but here is another clue if it helps anyone.

When I create a card, and set it to move right by 100 pixels and down by 100 pixels on a button click, a little bit of the image disappears with each click until it's gone completely (see photos). But I resize my window at any time, the card image pops back into full view, in the correct updated position. Either the QGraphicsView or QGraphicsScene is not registering changes in my card positions?

Calling "m_pokerscene.update()" (m_pokerScene is my QGraphicsView) every time after I change the position of a Card item is a crude fix that works, but is cumbersome, should be unnecessary and would just cover up whatever my real problem is.

Any thoughts? I appreciate it!

d_stranz
20th April 2020, 17:43
Set the QGraphicsItem::ItemSendsGeometryChanges flag on your card items.

jzacks524
20th April 2020, 17:59
Set the QGraphicsItem::ItemSendsGeometryChanges flag on your card items.

I did that already in the constructor, should it be somewhere else?

d_stranz
20th April 2020, 21:10
Hmmm, maybe that flag only applies when the ItemIsMovable flag is also set and the user interactively drags the item.

I don't think there is any alternative to the QGraphicsScene::update() call.