我正在用Qt-5.15.1開發。我想定制QGraphicsItem,并在這個定制的專案中添加一個矩形和一些周圍的圓圈。當滑鼠懸停在該矩形上時,這些小圓圈將顯示出來。所以我重新實作了hoverEnterEvent和hoverLeaveEvent函式來接收滑鼠懸停事件,請參考minimal example。
然后,在paint事件中,我可以根據_mouseEnter來決定是否繪制圓圈。
問題來了,我發現hoverEnterEvent將在滑鼠進入該矩形的邊界時被觸發,然而當滑鼠穿過邊界,靠近矩形的中心時,hoverLeaveEvent也很快被觸發了。似乎邊界是滑鼠懸停事件的物體,而不是填充的矩形。所以我只能在滑鼠懸停在該矩形的邊框上時顯示圓圈。
我不知道我是否錯過了什么?在我看來,shape()和boundingRect()會在事件發生時影響這些滑鼠事件?我想讓shape()回傳一個QPainterPath的填充矩形,但不知道如何做。
更新。最小的例子
customizeitem.cpp
#include "customizeitem.h"
#include <QDebug>
CustomizeItem::CustomizeItem(QGraphicsItem *parent)。
QGraphicsItem(parent),
_bbox(0,0,120, 120), _radius(7)。
_mouseEnter(false)
{
setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable) 。
setAcceptHoverEvents(true)。
_rectRect = QRect(QPoint(_radius*4, _radius*4), QPoint(_bbox. width() - _radius*4, _bbox.height() - _radius*4) )。)
QPointF upCenter(_bbox.width()/2, _radius)。
QPointF rCenter(_bbox.width() - _radius, _bbox.height() / 2)。
QPointF downCenter(_bbox.width()/2, _bbox.height() - _radius)。
QPoint lCenter(_radius, _bbox.height() / 2)。
_anchorRects.push_back(QRectF(upCenter, QSizeF(_radius, _radius)) )。
_anchorRects.push_back(QRectF(rCenter, QSizeF(_radius, _radius)) )。
_anchorRects.push_back(QRectF(downCenter, QSizeF(_radius, _radius)) )。
_anchorRects.push_back(QRectF(lCenter, QSizeF(_radius, _radius)) )。
}
void CustomizeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
qInfo() << "滑鼠進入"。
_mouseEnter = true;
update()。
QGraphicsItem::hoverEnterEvent(事件)。
}
void CustomizeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
qInfo() << "滑鼠離開"/span>。
_mouseEnter = false。
update()。
QGraphicsItem::hoverLeaveEvent(事件)。
}
QRectF CustomizeItem::boundingRect() const
{
return shape().boundingRect()。
}
void CustomizeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
painter->setRenderHint(QPainter::Antialiasing)。
drawAnchors(painter)。
painter->fillRect(_rectRect, QColor(255, 0, 0) ) 。
}
QPainterPath CustomizeItem::shape() const
{
QPainterPath路徑。
path.moveTo(_bbox.topLeft())。
path.addRect(_bbox)。
QPainterPathStroker stroker;
stroker.setWidth(10)。
return stroker.createStro(path)。
}
void CustomizeItem::drawAnchors(QPainter *painter)
{
if(_mouseEnter)
{
for(int i = 0; i < _anchorRects.size(); i )
{
QPainterPath path;
path.moveTo(_anchorRects[0].center() 。)
path.addEllipse(_anchorRects[i].center(), _radius, _radius) 。
painter->drawPath(path)。
}
}
customizeitem.h
#ifndef CUSTOMIZEITEM_H
#define CUSTOMIZEITEM_H
#include <QGraphicsItem>/span>
#include <QObject>
#include <QPainter>/span>
class CustomizeItem : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
enum { Type = UserType 1 };
explicit CustomizeItem(QGraphicsItem *parent = nullptr)。
~CustomizeItem() = default;
protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event)。
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)。
QPainterPath shape() const。
private:
void drawAnchors(QPainter *painter)。
QRect _bbox。
float _radius; 圓錨的半徑。
QVector<QRectF> _anchorRects;
QRect _rectRect;
bool _mouseEnter;
};
#endif // CUSTOMIZEITEM_H
maiwindow.cpp
#include "mainwindow.h"
#include " ./ui_mainwindow.h"
#include " customizeitem.h"
#include <QGraphicsView>/span>
#include <QVBoxLayout>/span>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this)。
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
layout->setContentsMargins(0,0,0) 。
QGraphicsView *view = new QGraphicsView(this)。
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding) 。
QGraphicsScene *scene = new QGraphicsScene;
CustomizeItem *item = new CustomizeItem;
scene->addItem(item)。
view->setScene(場景)。
layout->addWidget(view);
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
qt_begin_namespace
namespace Ui { class MainWindow; }
qt_end_namespace
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr)。
~MainWindow()。
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"/span>
#include <QApplication>
int main(int argc, char *argv[]) /span>
{
QApplication a(argc, argv)。
MainWindow w;
w.show()。
return a.exec()。
uj5u.com熱心網友回復:
QPainterPathStroker在矩形周圍生成了一個空心區域,所以只要該邊界通過,就已經脫離了形狀。解決方案是將該邊框與內部區域連接起來:
QPainterPath CustomizeItem::shape() const
{
QPainterPath路徑。
path.moveTo(_bbox.topLeft())。
path.addRect(_bbox)。
QPainterPathStroker stroker;
stroker.setWidth(10)。
QPainterPath strokerPath = stroker.createStroke(path)。
strokerPath.addPath(path); // join
return strokerPath。
}
uj5u.com熱心網友回復:
或者只是調整邊界框的矩形以適應額外的尺寸。
QPainterPath CustomizeItem::shape() const
{
QPainterPath路徑。
path.addRect(_bub. adjusted(-5, -5, -5))。
return path。
}
由于你的 "命中 "形狀是矩形的,你可能只需重新實作boundingRect(),因為默認的QGraphicsItem::shape()實際上使用了boundingRect()的結果(根據docs)。
QRectF CustomizeItem::boundingRect() const
{
return QRectF(_bub. adjusted(-5, -5, 5, 5))。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/332750.html
標籤:
上一篇:Apps腳本:將行復制到另一個沒有標題/標題的作業表
下一篇:專案不能被添加到一個陣列中
