You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过编程修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:50:17