3. 矩形罐体图元绘制与属性配置
任务目标
在Qt图形视图框架中,实现图元(QGraphicsItem)的鼠标拖拽移动与放置。用户点击图元后按住拖动,图元跟随鼠标移动,松开后停留在新位置。通过本案例掌握QGraphicsItem的鼠标事件处理、坐标转换以及QGraphicsScene的拖拽模式设置。
环境依赖
基于Qt Widgets模块,需要Qt5或Qt6开发环境,核心依赖为QtWidgets与QtGui。在项目文件(.pro)中添加:
QT += widgets
核心实现
自定义图元类DraggableItem,重写mousePressEvent、mouseMoveEvent与mouseReleaseEvent。关键点:按下时记录鼠标与图元原点的偏移量,移动时通过setPos更新位置,释放时不做额外处理即完成放置。场景需设置为QGraphicsScene::ItemIsMovable模式以启用拖拽,但本案例通过事件处理实现更精细的控制。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QMouseEvent>
#include <QPointF>
class DraggableItem : public QGraphicsRectItem {
public:
DraggableItem(qreal x, qreal y, qreal w, qreal h)
: QGraphicsRectItem(x, y, w, h) {
setFlag(QGraphicsItem::ItemIsMovable, false); // 禁用内置移动,使用自定义事件
setFlag(QGraphicsItem::ItemIsSelectable, true);
setBrush(QBrush(QColor(100, 180, 255)));
setPen(QPen(Qt::black, 2));
}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override {
// 记录鼠标按下位置与图元位置之间的偏移
m_offset = event->scenePos() - pos();
event->accept();
}
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override {
// 根据鼠标场景坐标减去偏移量,更新图元位置
setPos(event->scenePos() - m_offset);
event->accept();
}
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override {
// 放置完成,无需额外处理
event->accept();
}
private:
QPointF m_offset;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
scene.setSceneRect(0, 0, 400, 300);
// 创建两个可拖拽图元
DraggableItem *item1 = new DraggableItem(0, 0, 80, 60);
item1->setPos(50, 50);
scene.addItem(item1);
DraggableItem *item2 = new DraggableItem(0, 0, 100, 80);
item2->setPos(200, 150);
scene.addItem(item2);
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
view.resize(420, 320);
view.show();
return app.exec();
}
运行与验证
编译运行:
qmake
make
./drag_demo
验证步骤:
- 程序启动后,场景中显示两个蓝色矩形图元。
- 鼠标左键点击任一图元并按住拖动,图元应跟随鼠标移动。
- 松开鼠标,图元停留在释放位置,不会弹回原处。
- 重复拖拽多个图元,图元之间可重叠,位置互不影响。
通过条件:图元在拖拽过程中无闪烁、无跳变,松开后位置精确对应鼠标释放点;两个图元均可独立拖拽,且拖拽时图元始终位于鼠标下方(以按下点为准)。
关键说明
本实现通过event->scenePos()获取鼠标在场景坐标系中的位置,减去按下时记录的偏移量得到图元应处的位置。若需限制图元在场景边界内,可在mouseMoveEvent中添加边界判断。若使用setFlag(ItemIsMovable)配合场景的ItemIsMovable模式,Qt会自动处理拖拽,但自定义事件方式便于后续扩展吸附、对齐等工业组态场景中的精确放置需求。