Reputation: 1539
I am having a problem with mousePressEvent(QGraphicsSceneMouseEvent *event)
, indeed the clickable area seems small and off centre to the QGraphicsPixmapItem
it is linked to.
The red line is where the QGraphicsPixmapItem is clickable.
How would I centre it and eventually make it bigger and change it's shape ?
Here are the portions of my code that can be useful :
In player.h
class Player:public QObject, public QGraphicsPixmapItem{
Q_OBJECT
public:
Player();
void place_player(int x, int y);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
};
In player.cpp
Player::Player(): QGraphicsPixmapItem(){
}
void Player::place_player(int x,int y)
{
this->setPixmap(QPixmap("test.png"));
this->setPos(x,y);
game->scene->addItem(this);
}
void Player::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug()<< event;
};
in game.cpp
Game::Game(){
setFixedSize(1600,900);
scene = new QGraphicsScene(this);
scene->setSceneRect(0,0,1600,900);
setScene(scene);
}
void Game::start(){
player1 = new Player();
player1->place_player(300,300);
}
void Game::mousePressEvent(QMouseEvent *event)
{
QGraphicsView::mousePressEvent(event);
}
And finally the main.cpp
int main(int argc, char *argv[]){
QApplication a(argc, argv);
game = new Game();
game->show();
game->start();
return a.exec();
}
Thanks a lot for your help
Upvotes: 2
Views: 1203
Reputation: 27621
The clickable area of a QGraphicsItem is defined by its boundingRect and shape functions.
I would start by not using QGraphicsPixmapItem. You want a custom graphics item, which has the functionality of signals and slots, so derive from QGraphicsObject.
class Player : public QGraphicsObject
{
};
As we've now derived from this class, we need to override a couple of pure, virtual functions; namely boundingRect, paint
class Player : public QGraphicsObject
{
public:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
};
The boundingRect function defines the object in local coordinates. For an example, let's assume the character will have a width and height of 100. If we set the boundingRect to return (0, 0, 100, 100), this would be oriented about the top left corner. Instead, we want to centre the bounding rect on our Player:
QRectF Player::boundingRect() const
{
return QRectF(-50, -50, 100, 100); // local coordinates, centered on the Player
}
To draw our Player, store a QPixmap in the class
class Player : public QGraphicsObject
{
public:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
private:
QPixmap m_playerPixmap;
};
I'll assume you know how to load the pixmap and can do that in the constructor of the player.
All we need now is to render the player and we'll also show the clickable area, which is defined by the boundingRect() function: -
void Player::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
// draw the player
painter->drawPixmap(0, 0, m_playerPixmap);
// set the pen to draw debug rect
painter->setPen(QColor(255, 0, 0, 127));
// for debug purposes, show the bounding rect (clickable area)
painter->drawRect(boundingRect());
}
Originally I mentioned that the clickable area is defined by the boundingRect and shape functions. As the Player is of uniform shape (a rectangle), we only care about the boundingRect. In the case of an irregular shape, you would also override the shape function.
How would I centre it and eventually make it bigger and change it's shape ?
Hopefully you now know that to make the Player bigger, it's just a matter of increasing its local coordinates returned in the boundingRect function. So, if we want to double its width and height, we'd do this:
QRectF Player::boundingRect() const
{
return QRectF(-100, -100, 200, 200); // local coordinates, centered on the Player
}
To change its shape, implement the shape() function and to debug, paint the painterPath returned from that function, instead of drawing the boundingRect.
For example, let's have a circular, clickable area.
Assuming you've added the shape declaration to the Player header:
QPainterPath Player::shape() const
{
QPainterPath path;
path.addEllipse(-100, -100, 200, 200);
return path;
}
void Player::paint(QPainter * painter, const QStyleOptionGraphicsItem, QWidget*)
{
// draw the player
painter->drawPixmap(0, 0, m_playerPixmap);
// set the pen to draw debug path
painter->setPen(QColor(255, 0, 0, 127));
// for debug purposes, show the path (clickable area)
painter->drawPath(shape());
}
One final thing to note is that if you're overriding the shape function, you must still implement boundingRect.
Upvotes: 3