Qt Graphics View

news2024/11/16 23:29:28

Graphics View框架

在 Qt 中,Graphics View Framework(场景视图框架)是用于创建和管理可交互的 2D 图形界面的强大工具。它提供了以下主要的类和概念:

  1. QGraphicsScene(场景):QGraphicsScene 是一个 2D 场景,作为图形项的容器。你可以将图形项添加到场景中,并通过场景来管理这些图形项。场景提供了对图形项的布局、定位和变换等操作。它还负责事件派发和碰撞检测等功能。

  2. QGraphicsView(视图):QGraphicsView 是用于显示 QGraphicsScene 的视图。它提供了一个可滚动的窗口,可以在其中显示场景中的图形项。通过 QGraphicsView,你可以控制视图的缩放、平移和旋转等操作。它还支持鼠标和键盘事件处理。

  3. QGraphicsItem(图形项):QGraphicsItem 是场景中的可绘制对象。可以将其理解为场景中的图形元素或对象。QGraphicsItem 可以是简单的图形元素,例如线条、矩形和椭圆,也可以是复杂的自定义图形。它们可以添加到场景中,并通过 QGraphicsScene 来管理和操作。

  4. QGraphicsWidget(图形部件):QGraphicsWidget 是 QGraphicsItem 的子类,它提供了一种与 QWidget 类似的部件风格的接口。它可以包含其他图形项,并且支持布局和大小调整等功能。

通过使用 Graphics View Framework,你可以创建具有丰富交互性和定制性的 2D 图形界面。你可以在场景中添加、移动和删除图形项,并通过视图来查看和操作场景。Graphics View Framework 还提供了方便的方法来处理事件、选择图形项、执行动画、导出图形为图片等功能。你可以根据需要继承 QGraphicsItem 或 QGraphicsWidget 类来创建自定义的图形项。

总而言之,Graphics View Framework 提供了一个强大且灵活的工具集,用于创建可交互的 2D 图形界面,并且支持丰富的图形操作和事件处理。无论是创建游戏、数据可视化还是绘制图表,Graphics View Framework 都能够满足各种需求。

坐标系统及坐标映射

Graphics View Framework 中的三种坐标系统是:

  1. 物件坐标(Item Coordinates):物件坐标系统是指每个图形项(Item)自身的局部坐标系统。每个图形项都有自己的物件坐标,坐标原点通常位于图形项的左上角。物件坐标用于描述图形项自身的位置和几何属性。

  2. 场景坐标(Scene Coordinates):场景坐标系统是整个 QGraphicsScene 的坐标系统。它是一个无限大的平面,与物理设备的像素大小无关。场景坐标用于描述图形项在场景中的相对位置。

  3. 视图坐标(View Coordinates):视图坐标系统是指用于显示场景的 QGraphicsView 的坐标系统。视图坐标与物理设备的像素大小一致,即一个单位的视图坐标对应于一个像素。视图坐标用于描述图形项在视图中的位置和大小。

坐标映射(Coordinate Mapping)是 Graphics View Framework 提供的一组便捷函数,用于在物件坐标、场景坐标和视图坐标之间进行转换。这些函数包括:

  • mapToScene():将物件坐标或视图坐标转换为场景坐标。
  • mapFromScene():将场景坐标转换为物件坐标或视图坐标。
  • mapToItem():将物件坐标转换为另一个图形项的物件坐标。
  • mapFromItem():将另一个图形项的物件坐标转换为物件自身的物件坐标。

通过使用这些坐标映射函数,你可以方便地在不同的坐标系统之间进行转换操作,从而实现图形项的位置定位、交互以及坐标系之间的精确对齐。

事件处理

在 Qt 场景视图中,事件传递的顺序如下:

  1. 事件发生在 QGraphicsView 上。例如,鼠标按下或释放、鼠标滚轮旋转等事件首先在 QGraphicsView 上触发。

  2. QGraphicsView 将事件传递给当前活动的 QGraphicsScene。

  3. 如果 QGraphicsScene 没有处理事件,它将把事件传递给位于事件发生位置下方的最上层可接收事件的 QGraphicsItem。

  4. QGraphicsItem 依次接收事件,传递给具体的 QGraphicsItem 类型处理。

  5. 如果 QGraphicsItem 没有处理事件,事件将根据 QGraphicsItem 的父项关系传递给更高级别的 QGraphicsItem,直到事件被处理为止。

  6. 如果事件最终没有被任何 QGraphicsItem 处理,它将被丢弃。

总结起来,Qt 场景视图中的事件传递顺序是从 QGraphicsView 开始,然后传递给 QGraphicsScene,再传递给特定的 QGraphicsItem,直到事件被处理,或者如果没有任何 QGraphicsItem 处理事件,则事件被丢弃。通过重写 QGraphicsView、QGraphicsScene 和 QGraphicsItem 中的事件处理函数,你可以控制和自定义事件的处理过程。

QGraphicsView介绍

QGraphicsView类是Qt图形框架中的一个重要类,用于在应用程序中显示和呈现QGraphicsScene中的2D图形场景。它提供了一个可视化窗口或部件,用于将场景中的图形项显示到屏幕上,并负责处理与图形的交互操作和事件。

QGraphicsView类的主要作用如下:

  1. 提供图形场景的可视化窗口: QGraphicsView提供了一个可视化的窗口或部件,用于将QGraphicsScene中的图形项显示到屏幕上。开发人员可以将QGraphicsScene与QGraphicsView关联,通过设置QGraphicsView的参数和属性,来实现图形的显示效果、布局和交互方式。

  2. 实现图形的渲染和绘制: QGraphicsView负责将QGraphicsScene中的图形项渲染和绘制到窗口上。它使用与底层图形系统相关的绘图API,将图形项的形状、颜色、边框等绘制到屏幕上。通过控制QGraphicsView的绘制参数和视图的缩放、平移等操作,可以实现不同的图形展示效果。

  3. 处理图形的交互操作和事件: QGraphicsView负责捕获和处理与图形相关的用户交互操作和事件。例如,鼠标点击、拖拽、滚动、缩放等操作可以通过QGraphicsView进行处理。开发人员可以重写QGraphicsView的事件处理方法,以实现自定义的交互行为和相应逻辑。

  4. 支持视图的变换和坐标转换: QGraphicsView支持视图的变换,包括平移、缩放、旋转等操作,使开发人员能够灵活地控制图形的显示方式。它提供了一些方法用于坐标转换,可以将视图坐标与场景坐标进行相互转换,并实现鼠标点击位置到场景中图形项的映射。

  5. 实现多视图显示和布局: QGraphicsView支持多视图显示,同一个QGraphicsScene可以关联到多个QGraphicsView上进行显示。这样的设计模式使得开发人员能够更灵活地实现图形的布局和显示效果,例如在不同的窗口或部件中同时显示同一个场景。

总之,QGraphicsView类在Qt图形框架中扮演着一个图形场景的呈现器和交互控制器的角色。借助QGraphicsView类,开发人员可以将QGraphicsScene中的图形项显示到屏幕上,并通过设置参数和属性来实现图形的渲染、交互和显示效果。通过视图的变换和坐标转换功能,可以实现图形的平移、缩放和旋转等操作,以及在多视图之间的布局和交互操作。

QGraphicsView接口

QGraphicsView类提供了一系列的接口,用于设置和控制视图的外观、行为和交互操作。以下是QGraphicsView类的一些重要接口:

  1. 构造函数

    • QGraphicsView(QGraphicsScene* scene = nullptr, QWidget* parent = nullptr):构造一个QGraphicsView对象,并关联到指定的场景scene,并设置父级窗口为parent。
  2. 场景和视图

    • setScene(QGraphicsScene* scene):设置要显示的场景。
    • scene() const:返回当前关联的场景对象。
    • setRenderHint(QPainter::RenderHint hint, bool enabled = true):设置渲染提示,用于控制渲染的质量和性能。
    • setRenderHints(QPainter::RenderHints hints):设置一组渲染提示。
    • renderHints() const:返回当前的渲染提示。
  3. 视图行为

    • setDragMode(QGraphicsView::DragMode mode):设置拖拽模式,用于控制图形项的拖拽行为。
    • dragMode() const:返回当前的拖拽模式。
    • setInteractive(bool enabled):启用或禁用交互操作,默认为启用。
    • setRubberBandSelectionMode(Qt::ItemSelectionMode mode):设置矩形选取框的选择模式。
    • centerOn(const QPointF& pos):将视图中心移动到指定的场景坐标pos。
    • fitInView(const QRectF& rect, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio):将指定的矩形区域适应到视图中。
  4. 坐标转换

    • mapToScene(const QPoint& point) const:将视图坐标点point转换为场景坐标。
    • mapFromScene(const QPointF& point) const:将场景坐标点point转换为视图坐标。
    • mapToItem(const QGraphicsItem* item, const QPointF& point) const:将物件坐标点point转换为另一个图形项item的物件坐标。
    • mapFromItem(const QGraphicsItem* item, const QPointF& point) const:将另一个图形项item的物件坐标点point转换为物件自身的物件坐标。
  5. 视图控制

    • scale(qreal sx, qreal sy):在当前缩放基础上,按比例扩大或缩小视图。
    • translate(qreal dx, qreal dy):在当前的平移基础上,将视图平移dx个单位水平方向和dy个单位垂直方向。
    • rotate(qreal angle):在当前的旋转基础上,将视图旋转angle度。
    • resetTransform():重置视图的变换矩阵为单位矩阵,即恢复视图的原始状态。
    • setTransformationAnchor(QGraphicsView::ViewportAnchor anchor):设置视图的变换锚点,用于控制变换的中心位置。
    • setViewportUpdateMode(ViewportUpdateMode mode):设置视图更新模式,用于控制何时更新视图内容。
  6. 其他

    • setViewport(QWidget* widget):在视图中设置一个QWidget对象作为视窗。
    • viewport() const:返回当前视图的视窗对象。
    • setOptimizationFlag(QGraphicsView::OptimizationFlag flag, bool enabled = true):启用或禁用指定的优化标志,用于提高性能。
    • optimizationFlag(QGraphicsView::OptimizationFlag flag) const:返回指定优化标志的状态。

这些接口提供了控制和定制QGraphicsView的各个方面的方法,包括场景、视图行为、坐标转换、视图控制和其他选项。开发人员可以利用这些接口来创建自定义的交互式图形应用程序,并根据需要对视图进行操作和显示。

QGraphicsScene介绍

QGraphicsScene类是Qt图形框架中的一个重要类,用于创建和管理2D图形场景。它作为一个可视化的容器,可以包含和管理多个图形项(QGraphicsItem),并提供了一些方法和功能来处理场景的布局、渲染和交互。

QGraphicsScene类的主要作用如下:

  1. 提供一个场景容器: QGraphicsScene提供了一个场景容器,用于存储和管理多个图形项。开发人员可以通过添加和移除图形项的方式来编辑场景。场景可以看作是一个虚拟的二维空间,图形项可以在其中自由布局,并可以根据需要进行组合和分组。

  2. 实现图形的显示和渲染: QGraphicsScene负责将场景中的图形项渲染到视图中。它根据图形项的位置、形状和外观信息,将它们绘制到场景内部的画布上,并通过视图将画布内容显示到屏幕上。开发人员可以通过设置图形项的属性和调用相关方法,来控制图形的显示效果。

  3. 处理交互操作和事件: QGraphicsScene负责处理和转发与场景相关的用户交互操作和事件。例如,鼠标点击、拖拽、键盘操作等事件可以通过场景进行捕获和处理。开发人员可以重写场景的事件处理方法,以实现自定义的交互行为和响应逻辑。

  4. 提供坐标转换和定位功能: QGraphicsScene支持坐标转换和定位功能,使得开发人员可以在场景中方便地进行坐标的转换和定位。它提供了一些方法来将视图坐标与场景坐标进行相互转换,以及查找特定位置的图形项或特定图形项的位置信息。

  5. 支持场景与视图的分离和多视图显示: QGraphicsScene与视图(QGraphicsView)是分离的,同一个场景可以关联到多个视图上进行显示。这种设计模式使得开发人员可以实现多视图的布局和显示效果,而无需重复创建和管理场景。通过设置不同的视图参数和布局方式,可以在不同的窗口或部件中显示同一个场景。

总之,QGraphicsScene类为开发者提供了一个灵活且强大的图形场景管理器,可用于创建各种2D图形应用程序。它将图形项组织到一个可视化的场景中,并提供了多种功能和方法,以实现图形的布局、显示、交互和事件处理。通过场景与视图的关联,可以实现多视图显示和交互操作,为用户带来更好的图形体验。

QGraphicsScene接口

QGraphicsScene类是Qt图形框架中的一个重要类,用于创建和管理2D图形场景。以下是QGraphicsScene类的一些常见接口:

  1. 构造函数:

    • QGraphicsScene():默认构造函数,创建一个空的场景。
    • QGraphicsScene(const QRectF &sceneRect):使用指定的矩形范围作为场景的初始化边界框。
  2. 添加和移除图形项:

    • addItem(QGraphicsItem *item):将指定的图形项添加到场景中。
    • addRect(const QRectF &rect, const QPen &pen = QPen(), const QBrush &brush = QBrush()):添加一个矩形图形项到场景中。
    • removeItem(QGraphicsItem *item):从场景中移除指定的图形项。
  3. 场景参数和属性:

    • setSceneRect(const QRectF &rect):设置场景的边界框。
    • setBackgroundBrush(const QBrush &brush):设置场景的背景画刷。
    • setItemIndexMethod(QGraphicsScene::ItemIndexMethod method):设置图形项的索引方法。
  4. 图形项遍历和查询:

    • items():返回场景中所有的图形项。
    • items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape):返回与指定矩形相交的图形项。
    • itemAt(const QPointF &pos):返回指定位置处的图形项。
  5. 绘制和渲染:

    • render(QPainter *painter, const QRectF &target = QRectF(), const QRectF &source = QRectF(), Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio):将场景渲染到指定的绘图设备上。
    • renderToImage():将场景渲染为QImage对象。
  6. 事件和交互操作:

    • mousePressEvent(QGraphicsSceneMouseEvent *event):处理鼠标按下事件。
    • mouseMoveEvent(QGraphicsSceneMouseEvent *event):处理鼠标移动事件。
    • keyPressEvent(QKeyEvent *event):处理键盘按下事件。
  7. 场景信号:

    • changed(const QList<QRectF> &region):当场景的内容发生变化时发出信号。
  8. 坐标转换和定位:

    • sceneRect():返回场景的边界框。
    • views():返回与场景关联的所有视图。

以上仅列举了QGraphicsScene类的一部分接口,还有其他更多用于布局、编辑、选择和控制图形项的接口。开发人员可以根据具体需求使用这些接口来创建自定义的图形场景,并实现各种图形应用程序的功能。

QGraphicsItem介绍

QGraphicsItem类是Qt图形框架中的一个基类,用于在QGraphicsScene中表示可视化的2D图形项。它是所有可在场景中显示和交互的图形项的基础类。QGraphicsItem类的作用如下:

  1. 提供基本的图形项功能: QGraphicsItem提供了一些基本的功能,例如图形项的位置、旋转、缩放、边界框计算等操作。可以使用这些功能对图形项进行定位、变换以及与其他图形项的关系计算。

  2. 实现图形项的绘制和渲染: QGraphicsItem负责将自身的图形形状以及其他可视化属性绘制到场景中。通过重写QGraphicsItem的paint()方法,可以自定义图形项的绘制方式,包括填充颜色、边框样式、渐变效果等。

  3. 处理图形项的事件和交互操作: QGraphicsItem负责处理与图形项相关的事件和交互操作。例如,鼠标点击、移动、键盘事件等都可以通过重写QGraphicsItem的event()方法来实现相应的响应行为。可以根据需要捕捉和处理各种用户交互操作以及自定义的事件。

  4. 支持图形项的布局和变换: QGraphicsItem提供了一些方法和属性用于支持图形项的布局和变换。可以通过设置图形项的位置、旋转角度、缩放因子等来实现布局和变换效果。还可以设置图形项的锚点、对齐方式以及Z轴顺序等属性,以影响图形项在场景中的显示顺序和位置。

  5. 实现图形项的选择和编辑: QGraphicsItem支持图形项的选择和编辑功能。可以通过设置图形项的选择模式和编辑标志,来控制图形项是否可选中、可编辑。此外,还可以通过重写相关方法来实现自定义的选择和编辑行为。

  6. 提供图形项之间的父子关系: QGraphicsItem允许将图形项进行组合并形成父子关系。通过设置图形项的父对象,可以将多个图形项组织成一个复杂的图形结构。这种层级关系可以用于实现分组、布局和层次管理等功能。

总之,QGraphicsItem类是Qt图形框架中的基础类,提供了实现在QGraphicsScene中可视化的2D图形项所需的基本功能。它包括图形项的绘制、事件处理、交互操作、布局和变换等功能,为开发人员提供了强大的工具来创建各种图形应用程序。

QGraphicsItem子类介绍

QGraphicsItem类的子类有很多,下面列举一些常用的:

  1. QGraphicsPixmapItem 用于在场景中显示像素图(QPixmap)。

  2. QGraphicsTextItem 用于在场景中显示文本(QTextDocument),支持多种字体、颜色和对齐方式等。

  3. QGraphicsLineItem 用于在场景中显示线条。

  4. QGraphicsRectItem 用于在场景中显示矩形。

  5. QGraphicsEllipseItem 用于在场景中显示椭圆。

  6. QGraphicsPathItem 用于在场景中显示任意形状的路径(QPainterPath),支持填充、轮廓和渐变等效果。

  7. QGraphicsPolygonItem 用于在场景中显示多边形(Polygon)。

  8. QGraphicsSimpleTextItem 和QGraphicsTextItem类似,但只支持单行文本。

  9. QGraphicsWidget 基于QWidget实现的图形项,可以将QWidget作为子控件添加到场景中,并支持鼠标、键盘事件等交互操作。

  10. QGraphicsProxyWidget 类似于QGraphicsWidget,但是使用QGraphicsObject作为父类。

总之,QGraphicsItem的子类可以用于在场景中显示各种不同的2D图形项,例如图片、文本、线条、矩形、椭圆、多边形等,还可以自定义各种图形项。这些子类都继承了QGraphicsItem类的基本功能,如位置、变换、事件处理等,并且各自提供不同的可视化效果和交互特性,为开发人员提供了更多的工具来创建各种2D图形应用程序。

QGraphicsItem接口

QGraphicsItem类是Qt图形框架中的基类,提供了许多接口(方法和属性)来管理和操作可视化的2D图形项。下面介绍一些常用的接口:

  1. 位置和变换相关接口:

    • setPos(x, y):设置图形项在场景中的位置。
    • pos():获取图形项在场景中的位置。
    • setTransform(transform):设置图形项的变换矩阵,包括旋转、缩放和平移等变换。
    • transform():获取图形项的变换矩阵。
  2. 绘制和渲染相关接口:

    • paint(painter, option, widget):在给定的painter上绘制图形项的内容,可以自定义绘制逻辑。
    • boundingRect():获取图形项的边界框,用于优化绘制和碰撞检测。
    • shape():获取图形项的形状,用于做精确的碰撞检测。
  3. 事件处理和交互相关接口:

    • sceneEvent(event):处理与图形项相关的事件,如鼠标点击、移动、键盘事件等。
    • mousePressEvent(event):处理鼠标按下事件。
    • mouseMoveEvent(event):处理鼠标移动事件。
    • mouseReleaseEvent(event):处理鼠标释放事件。
    • keyPressEvent(event):处理键盘按键事件。
    • hoverEnterEvent(event):处理光标进入图形项事件。
    • hoverLeaveEvent(event):处理光标离开图形项事件。
  4. 选择和编辑相关接口:

    • setFlag(flag, enabled):设置图形项的标志,用于控制选择和编辑行为。
    • isSelected():检查图形项是否被选中。
    • setZValue(z):设置图形项的Z轴顺序,用于控制绘制顺序和层叠关系。
  5. 父子关系相关接口:

    • setParentItem(parent):设置图形项的父对象,用于创建图形项之间的层级关系。
    • parentItem():获取图形项的父对象。
    • childItems():获取图形项的所有子对象。
  6. 属性和数据相关接口:

    • setData(key, value):在图形项中存储自定义的键值对数据。
    • data(key):获取指定键的数据值。

这些接口只是QGraphicsItem类提供的部分常用接口,还有其他许多接口可以用于更精确地控制图形项的外观、行为和交互。开发人员可以根据具体需求使用这些接口来创建和管理不同类型的图形项,并实现丰富的2D图形应用程序。

代码演示

该示例基于Qt的图形视图框架实现了两列矩形框的显示,开启修改功能后,可先点击第一列的矩形框再点击第二列的矩形框,会将两个矩形框连接起来,点击取消,则删除所有的连接线。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsRectItem>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_btnChange_clicked();
    void on_focusItemChanged(QGraphicsItem *newFocusItem, QGraphicsItem *oldFocusItem, Qt::FocusReason reason);

private:
    Ui::MainWindow *ui;
    const int rowKey = 1;
    const int colKey = 2;

    int itemWidth = 100;
    int itemHeight = 50;

    QGraphicsScene *scene = nullptr;
    void init();
    int rowNum = 8;
    int colNum = 2;

    bool isDrawing = false;

};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtMath>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setFixedSize(1200,1000);
    init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::init()
{
    scene = new QGraphicsScene;
    for(int col=0;col<colNum;col++)
    {
        int x = col*200+itemWidth;
        for(int row=0;row<rowNum;row++)
        {
            //添加一个矩形
            QGraphicsRectItem   *item=new QGraphicsRectItem(-0.25*itemWidth,-0.25*itemHeight,itemWidth,itemHeight);//x,y 为左上角的图元局部坐标,图元中心点为0,0
            item->setFlags(QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            item->setBrush(QBrush(Qt::yellow));
            item->setPos(x,row*(itemHeight+20));

            item->setData(rowKey,row+1);
            item->setData(colKey,col+1);
            scene->addItem(item);

            // 创建文字项
            QString text = QString("col%1,row%2").arg(col+1).arg(row+1);
            QGraphicsTextItem* textItem = new QGraphicsTextItem(text);
            textItem->setPos(item->sceneBoundingRect().center() - textItem->sceneBoundingRect().center());
            scene->addItem(textItem);

            scene->clearSelection();
        }
    }
    connect(scene,&QGraphicsScene::focusItemChanged,this,&MainWindow::on_focusItemChanged);

    ui->graphicsView->setScene(scene);
}

void MainWindow::on_btnChange_clicked()
{
    QString text = ui->btnChange->text();
    if(text=="修改")
    {
        ui->btnChange->setText("取消");
        ui->btnSet->setEnabled(true);
        isDrawing = true;
    }
    else if(text=="取消")
    {
        ui->btnChange->setText("修改");
        ui->btnSet->setEnabled(false);
        isDrawing = false;

        // 获取场景中的所有图形项
        QList<QGraphicsItem*> items = scene->items();
        // 遍历图形项列表,筛选出 QGraphicsLineItem
        foreach (QGraphicsItem* item, items) {
            if (item->type() == QGraphicsLineItem::Type
                    || item->type() == QGraphicsPolygonItem::Type) {
                //QGraphicsLineItem* line = qgraphicsitem_cast<QGraphicsLineItem*>(item);
                // 执行操作或获取所需的 QGraphicsLineItem
                // ...
                scene->removeItem(item);
            }
        }
    }
}

void MainWindow::on_focusItemChanged(QGraphicsItem *newFocusItem, QGraphicsItem *oldFocusItem, Qt::FocusReason reason)
{
    if(reason != Qt::FocusReason::MouseFocusReason)
    {
        return;
    }

    if(newFocusItem==nullptr || oldFocusItem==nullptr)
    {
        return;
    }

    if(oldFocusItem->data(colKey)!=1 || newFocusItem->data(colKey)!=2)
    {
        return;
    }

    if(!isDrawing)
    {
        return;
    }


    QGraphicsLineItem   *item=new QGraphicsLineItem(-100,0,100,0);//x,y 为左上角的图元局部坐标,图元中心点为0,0
    item->setFlags(QGraphicsItem::ItemIsSelectable
                   | QGraphicsItem::ItemIsFocusable);

    QPen    pen(Qt::green);
    pen.setWidth(3);
    item->setPen(pen);

    QPointF startPoint = QPointF(oldFocusItem->sceneBoundingRect().right(),oldFocusItem->sceneBoundingRect().center().y());
    QPointF endPoint = QPointF(newFocusItem->sceneBoundingRect().left(),newFocusItem->sceneBoundingRect().center().y());

    item->setLine(QLineF(startPoint,
                         endPoint));

    scene->addItem(item);

    // 计算箭头的位置和方向
    QPointF direction = endPoint - startPoint;
    direction = direction / qSqrt(direction.x() * direction.x() + direction.y() * direction.y());  // 单位向量
    QPointF arrowP1 = endPoint - direction * 10 + QPointF(direction.y(), -direction.x()) * 5;
    QPointF arrowP2 = endPoint - direction * 10 + QPointF(-direction.y(), direction.x()) * 5;

    // 创建箭头形状
    QPolygonF arrowHead;
    arrowHead << endPoint << arrowP1 << arrowP2;
    QGraphicsPolygonItem* arrowItem = new QGraphicsPolygonItem(arrowHead);
    arrowItem->setBrush(Qt::green);
    scene->addItem(arrowItem);


    scene->clearSelection();
    item->setSelected(true);
}

完整工程下载:https://download.csdn.net/download/zw_ggr_2017/88280186

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/957815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【lucky-canvas插件】在Vue3实现大转盘九宫格老虎机抽奖

目录 前言 一、lucky-canvas介绍 二、lucky-canvas使用&#xff08;Vue3&#xff09; 1. 安装 2. 注册 3. 使用 三、九宫格为例的具体使用 1. 组件使用 2. 常用配置 ① blocks 背景 ② prizes 奖品 ③ buttons 抽奖按钮 3. 回调函数 ① start 开始抽奖前 ② end …

【Flask】from flask_sqlalchemy import SQLAlchemy报错

【可能出现的情况】 1、未安装 Flask-SQLAlchemy&#xff1a; 在使用 flask_sqlalchemy 之前&#xff0c;你需要确保已经通过 pip 安装了 Flask-SQLAlchemy。可以通过以下命令安装它&#xff1a; pip install Flask-SQLAlchemy 2、包名大小写问题&#xff1a; Python 是区分大…

css让多个盒子强制自动等宽

1.width: calc( 100 / n% ) 2.display:flex; flex:1;width:100px; 3.display:grid;grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); 但是其中某一个内容较长的时候 会破坏1:1:1的平衡 这个时候发现附件名字过长导致不等比例&#xff0c;通过查看阮一峰flex文…

《人生苦短,我学Python》——布尔类型 比较运算 逻辑运算

&#x1f448;前三天&#xff0c;我们学了字符串、整型、浮点型这三种数据类型。今天我们将学习最后一种数据类型&#xff1a;布尔型。简单来说&#xff0c;布尔型就是“真”&#xff08;True&#xff09;和“假”&#xff08;False&#xff09;。下面就让我们来详细看看吧&…

13.动态渲染侧边栏

为什么要动态渲染&#xff1f; 比如我们现在需要以下侧边栏的数据&#xff1a; 如果一个个的去写标签会很麻烦&#xff0c;发现导航栏中的数据分为两类&#xff0c;一类是一级导航&#xff0c;另一位是二级导航&#xff08;有子页&#xff09;&#xff0c;因此直接写两个函数判…

Docker从认识到实践再到底层原理(二-1)|容器技术发展史+虚拟化容器概念和简介

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

20230831工作心得:SQL这块花了挺多时间

1、SQL语句的问题 1、SQL这块花了挺多时间 1、理解业务 要之前自己要查什么数据&#xff0c;再去写SQL&#xff0c;这句话看起来像一句废话&#xff0c;但是很多时候&#xff0c;不知道自己在干嘛。 2、时间 1、需要查询哪个时间字段 表里有很多time有create_time&#…

【2】openGL shader着色器分析三角形填色

源代码在下面。文档查询 > docs.gl 结果展示&#xff1a;使用自己的shader和打印错误描述 该篇主要在上一部分代码的基础上添加了自己写的shader&#xff0c;即着色器。最常用的两个着色器 vertex shader 和 fragment shader&#xff0c;即顶点着色器和片段着色器。 大概…

嵌入式行业——选择比努力重要

嵌入式开发可以说是一个较大的类别&#xff0c;也可以看作是应用技术的一种广义称谓。它在不同的工业和行业场景中应用不同的业务模式和领域。 举个例子&#xff0c;嵌入式技术结合基站通信技术&#xff0c;就构成了华为基站&#xff1b;嵌入式技术结合视频处理/图像处理技术&a…

如何使用CSS实现一个响应式图片幻灯片(Responsive Image Slider)效果?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 响应式图片幻灯片⭐ HTML结构⭐ CSS样式⭐ JavaScript交互⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个…

快速排序(Quit Sort)

C自学精简教程 目录(必读) 快速排序 每次都把数据分成左右两部分&#xff0c;左边的小于某个数&#xff0c;右边的大于某个数。 递归操作左侧和右侧&#xff0c;最终完成所有数据的排序。 输入数据 72 6 57 88 60 42 83 73 48 85 执行过程 快速排序&#xff0c;选取位于…

【100天精通python】Day50:python web编程_web框架,Flask的使用

目录 1 Web 框架 2 python 中常用的web框架 3 Flask 框架的使用 3.1 Flask框架安装 3.2 第一个Flask程序 3.3 路由 3.3.1 基本路由 3.3.2 动态路由 3.3.3 HTTP 方法 3.3.4 多个路由绑定到一个视图函数 3.3.5 访问URL 参数的路由 3.3.6 带默认值的动态路由 3.3.7 带…

成都智慧企业发展研究院总经理郑小华:践行双轮驱动,为能源电力数智化注入新活力丨数据猿专访...

大数据产业创新服务媒体 ——聚焦数据 改变商业 随着全球经济走向数字化&#xff0c;中国正处于这一浪潮的前沿&#xff0c;进行前所未有的技术与产业深度融合。政府在2023年2月印发的《数字中国建设整体布局规划》等政策下&#xff0c;明确展示了对数字经济的支持与鼓励&…

虚拟机Ubuntu20.04 网络连接器图标开机不显示怎么办

执行以下指令&#xff1a; sudo service network-manager stop sudo rm /var/lib/NetworkManager/NetworkManager.state sudo service network-manager start

SPSS统计作图教程:频率多边形

SPSS统计作图教程&#xff1a;频率多边形 1、问题与数据 某研究者想了解某数据集中最大携氧能力&#xff08;VO2max&#xff09;是否服从正态分布&#xff0c;部分数据如图1。研究者应如何绘图查看呢&#xff1f; 图1 部分数据 2、对问题的分析 研究者想绘图展示最大携氧能…

Collections.singletonList、Arrays.asList与ImmutableList.of

文章目录 ListArrayListLinkedListArrayList与LinkedList的区别快速构建list集合Collections.singletonListArrays.asListImmutableList.of Java集合类型有三种&#xff1a;set(集)、list(列表)和map(映射)&#xff0c;而List集合是很常用的一种集合类型&#xff0c; List 我…

【算法训练-模拟 一】模拟设计LRU缓存结构

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是LRU缓存结构设计&#xff0c;这类题目出现频率还是很高的&#xff0c;几乎所有大厂都常考。 当然面对这道题&#xff0c;首先要讲清楚LRU是干什么…

使用环境中的视觉地标和扩展卡尔曼滤波器定位移动机器人研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

go学习part19(3)协程求素数

1.代码 intChan存放原始数据 primeChan存放检验之后的素数 exitChan存放几个协程的状态 package mainimport ("fmt""time" )/* 求素数 */ //放入1-8000个数 func putNum(intChan chan int) {for i : 2; i < 8000; i {intChan <- i}//关闭intChanc…

Java 设计模式实战系列—单例模式

本文首发公众号&#xff1a;小码A梦 单例模式是设计模式中最简单一个设计模式&#xff0c;该模式属于创建型模式&#xff0c;它提供了一种创建实例的最佳方式。 单例模式的定义也比较简单&#xff1a;一个类只能允许创建一个对象或者实例&#xff0c;那么这个类就是单例类&…