如何通过编程修改QGraphicsLineItem?十字线缩放无效果
QGraphicsLineItem修改参数无效果的解决办法
我正在开发可缩放、可移动的覆盖项,当前聚焦于十字线功能。为实现缩放,我需要修改组成十字线的两个QGraphicsLineItem的参数,但调用setLength()、setP1()、setP2()或setLine()等函数均无效果。相关代码如下:
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QGraphicsRectItem> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; QGraphicsRectItem *_item; }; #endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QGraphicsScene *scene = new QGraphicsScene(this); _item = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); _item->setFlag(QGraphicsItem::ItemIsMovable); _item->setPen(QColor(102, 102, 102)); auto l1 = new QGraphicsLineItem(0, 50, 100, 50, _item); auto l2 = new QGraphicsLineItem(50, 0, 50, 100, _item); l1->setPen(QColor(10, 255, 10)); l2->setPen(QColor(10, 255, 10)); scene->addItem(_item); ui->graphicsView->setScene(scene); ui->graphicsView->setAlignment(Qt::AlignTop | Qt::AlignLeft); ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); // make lines longer by 10 on button press connect(ui->resize, &QPushButton::clicked, this, [this]() { auto childs = _item->childItems(); if (childs.size() > 0) { auto line1 = dynamic_cast<QGraphicsLineItem *>(childs.at(0)); auto line2 = dynamic_cast<QGraphicsLineItem *>(childs.at(1)); line1->line().setLine(0, 55, 110, 55); //no effect line2->line().setLine(55, 0, 55, 110); //no effect } }); } MainWindow::~MainWindow() { delete ui; }
由于需要处理mousePressEvent、mouseMoveEvent事件,未使用QGraphicsItemGroup,求解决办法。
问题原因
QGraphicsLineItem::line()函数返回的是QLineF的副本,不是原对象的引用。调用line().setLine(...)只是修改了这个临时副本,根本没作用到实际的QGraphicsLineItem上,自然看不到效果。
解决代码
把按钮点击的lambda部分改成下面这样,直接调用setLine()成员函数设置新线段:
connect(ui->resize, &QPushButton::clicked, this, [this]() { auto childs = _item->childItems(); if (childs.size() > 0) { auto line1 = dynamic_cast<QGraphicsLineItem *>(childs.at(0)); auto line2 = dynamic_cast<QGraphicsLineItem *>(childs.at(1)); // 直接调用setLine设置新线段 line1->setLine(0, 55, 110, 55); line2->setLine(55, 0, 55, 110); } });
如果需要基于原线段长度动态缩放(比如每次延长10单位),可以先获取原线段修改后再设置回去:
connect(ui->resize, &QPushButton::clicked, this, [this]() { auto childs = _item->childItems(); if (childs.size() > 0) { auto line1 = dynamic_cast<QGraphicsLineItem *>(childs.at(0)); auto line2 = dynamic_cast<QGraphicsLineItem *>(childs.at(1)); // 获取原线段并修改 QLineF l1 = line1->line(); l1.setLine(l1.x1() - 10, l1.y1(), l1.x2() + 10, l1.y2()); line1->setLine(l1); QLineF l2 = line2->line(); l2.setLine(l2.x1(), l2.y1() - 10, l2.x2(), l2.y2() + 10); line2->setLine(l2); } });
额外说明
- 若后续需要频繁修改这两条线,建议不要通过
childItems()动态获取,而是在MainWindow类中添加成员变量保存l1和l2的指针,这样更高效安全,避免dynamic_cast失败的风险。 - 不使用QGraphicsItemGroup完全可行,直接管理子item的方式符合你的需求,处理鼠标事件时在父item(
_item)的事件函数中处理即可。
内容的提问来源于stack exchange,提问作者GregPhil
相关产品推荐
相关产品推荐

