Я создал объект:
class Button : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
public:
Button();
virtual QRectF boundingRect() const override;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
// QGraphicsItem interface
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
signals:
void clicked();
private:
bool m_pressed;
QPixmap m_buttonPixmap, m_pressedButtonPixmap;
};
затем я реализовал несколько функций:
Button::Button()
: m_pressed(false)
{
m_buttonPixmap = PixmapManager::Instance()->getPixmap(PixmapManager::Button);
m_pressedButtonPixmap = PixmapManager::Instance()->getPixmap(PixmapManager::PressedButton);
setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
}
QRectF Button::boundingRect() const
{
return QRectF(-m_buttonPixmap.width() / 2.0f,
-m_buttonPixmap.height() / 2.0f,
m_buttonPixmap.width(),
m_buttonPixmap.height());
}
void Button::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
if (m_pressed) {
//painter->drawPixmap(0,0, m_pressedButtonPixmap);
}
else {
painter->setBrush(Qt::red);
painter->drawRect(boundingRect());
//painter->drawPixmap(0,0, m_buttonPixmap);
}
}
void Button::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "pressed ";
m_pressed = true;
update();
QGraphicsPixmapItem::mousePressEvent(event);
}
void Button::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "released ";
m_pressed = false;
update();
QGraphicsPixmapItem::mouseReleaseEvent(event);
}
Я также создал QGraphicsScene с элементом Button:
MenuScene::MenuScene(QObject *parent)
: QGraphicsScene(parent)
{
setSceneRect(0,0, SCREEN::PHYSICAL_SIZE.width(), SCREEN::PHYSICAL_SIZE.height());
addItem(&m_startButton);
}
void MenuScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "Scene pressed";
QGraphicsScene::mousePressEvent(event);
}
void MenuScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "Scene released";
QGraphicsScene::mouseReleaseEvent(event);
}
Если я нажму на кнопку, я получу только информацию из MenuScene, например «Сцена нажата» / «Сцена выпущена».
В main.cpp я использовал:
MenuScene* ms = new MenuScene();
QGraphicsView gv;
gc.show();
Я пробовал использовать: m_startButton.setAcceptedMouseButtons(Qt::AllButtons); m_startButton.setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable); но без результата.
Хорошо, я сделал минимальный воспроизводимый пример.





Обнаружение столкновений мыши всегда использует функцию items() представления с флагом Qt::IntersectsItemShape, чтобы проверить, на какие элементы может повлиять событие мыши, а это означает, что результат всегда основан на shape() элемента.
Хотя поведение QGraphicsItem по умолчанию заключается в возврате QPainterPath на основе boundingRect(), это не относится ко всем подклассам, включая QGraphicsPixmapItem, который создает путь на основе своего растрового изображения (и, возможно, с учетом его маски).
Поскольку вы никогда не вызываете setPixmap() для элемента, результирующий путь от shape() пуст, поэтому он всегда будет прозрачен для событий мыши (и для обнаружения столкновений других элементов, чего бы это ни стоило).
Таким образом, самое простое решение — вызвать setPixmap(m_buttonPixmap) в конструкторе, а затем снова вызвать setPixmap() с любыми растровыми изображениями в соответствующем обработчике событий мыши.
В качестве альтернативы вы можете переопределить shape(), создать QPainterPath, использовать addRect(boundingRect()) и вернуть его (вам также следует рассмотреть возможность кэширования как ограничивающего прямоугольника, так и пути, чтобы избежать ненужных накладных расходов).
Однако обратите внимание, что вы практически не пользуетесь преимуществами каких-либо функций QGraphicsPixmapItem: вы не только не используете его возможности смещения, режима преобразования или маскировки, но также в конечном итоге рисуете растровые изображения самостоятельно.
Учитывая это, на самом деле нет смысла создавать из него подкласс с самого начала, и вы, вероятно, могли бы просто наследовать от QGraphicsObject, который уже наследуется как от QObject, так и от QGraphicsItem.
Оно работает. Большое спасибо! Решением является метод shape(). Я использовал: QPainterPath Button::shape() const {QPainterPath path; path.addRect(boundingRect()); Обратный путь; } Я также заменил QGraphicsPixmapItem на QGraphicsObject.
@Bondrusiek Хорошо, пожалуйста. Обратите внимание: если вы просто создаете подкласс QGraphicsObject, вам больше не нужно переопределять shape(), поскольку оно следует поведению QGraphicsItem по умолчанию, которое уже возвращает QPainterPath на основе boundingRect(), как объяснено в ответе.
Да, я сделал. Я использовал класс Button: public QObject, public QGraphicsPixmapItem и переопределения для событий мыши: // Интерфейс QGraphicsItem protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override; виртуальная пустота mouseReleaseEvent (QGraphicsSceneMouseEvent *event) переопределение;