Qt:线连接2个单独的图

标签 qt mouseevent qgraphicsview qgraphicsscene

This is what i mean that happens, first tried a circle, then on the right a square我想画不同的任意数字。在图形 View 中单击鼠标时开始绘图,停止单击鼠标时结束。但是,当从图形 View 中的不同点开始绘制新绘图或继续上一个绘图时,将从第一个绘图的最后一个鼠标坐标到第二个绘图的第一个坐标绘制一条线。图纸不一定需要是不同的图纸,也可以只是对图纸的调整。这是我的代码。

#include "mousedraw.h"
#include <QDebug>

MouseDraw::MouseDraw()
{
    setFlag(ItemIsMovable);
}

QRectF MouseDraw::boundingRect() const
{
    return QRectF(0,0,300,300);
}

void MouseDraw::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,      QWidget *widget)
{
    QPainterPath path;
    path.addPolygon(polyPoints2);
    painter->setPen(QPen(QColor(qrand() % 256, qrand() % 256, qrand() % 256),3));
    painter->drawPath(path);
}

void MouseDraw::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QPointF point = event->pos();
    if (boundingRect().contains(point)) {
         array1 = point.x();
        array2 = point.y();
        polyPoints2 << QPoint(array1,array2);
        update();
    }
}

最佳答案

不需要从 QGraphicsItem 派生的自定义 MouseDraw 类。有一个 QGraphicsPathItem 可以为您正确处理这一切。

在正在创建的项目中处理鼠标交互在概念上是不正确的 - 您的大边界矩形是它工作所需的 hack,但这是错误的方法。您不希望 item 与鼠标交互。您希望场景 与鼠标交互并即时创建项目。仅当编辑现有项时您希望有鼠标交互,但即便如此,最好创建一个单独的编辑器项覆盖在正在编辑的项上以处理编辑交互。

用鼠标右键单击窗口可获得带有清除图片操作的上下文菜单。您还可以切换后续路径是否与前一个路径相连。此代码已在 Qt 4.8.5 和 5.2 中进行了测试。

当场景小于 View 时, View 坚持将其居中(使用 alignment 属性)。 EmptyItem 用作此“功能”的变通方法,用于在场景小于 View 时(包括场景“空”时)限制场景在 View 中的位置。

代码为每个不相交的路径创建一个单独的项目 - QGraphicsScene 通常会在多个不重叠的项目中表现最佳。您当然可以只保留一个项目,并在每次按下鼠标时继续向其添加新的片段,但这最终会对性能产生影响——尤其是当您放大场景时,您希望性能会越来越好。显示。

screenshot

// https://github.com/KubaO/stackoverflown/tree/master/questions/gscene-paint-20632209
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif

class EmptyItem : public QGraphicsItem
{
public:
    EmptyItem(QGraphicsItem * parent = nullptr) : QGraphicsItem{parent} {}
    QRectF boundingRect() const override { return {0, 0, 1, 1}; }
    void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override {}
};

class Scene : public QGraphicsScene
{
    Q_OBJECT
    Q_PROPERTY(bool joinFigures READ joinFigures WRITE setJoinFigures)
    bool m_joinFigures = false;
    QGraphicsPathItem * m_item = nullptr;
    QPainterPath m_path;

    void newItem() {
        addItem(m_item = new QGraphicsPathItem);
        m_item->setPen(QPen{{qrand() % 256, qrand() % 256, qrand() % 256}});
        m_path = QPainterPath{}; // using std::swap; swap(m_path, QPainterPath());
    }
    void newPoint(const QPointF& pt) {
        if (! m_item) {
            newItem();
            m_path.moveTo(pt);
        } else {
            m_path.lineTo(pt);
            m_item->setPath(m_path);
        }
    }
    void mousePressEvent(QGraphicsSceneMouseEvent * ev) override {
        if (ev->buttons() != Qt::LeftButton) return;
        if (! m_joinFigures) m_item = nullptr;
        newPoint(ev->scenePos());
    }
    void mouseMoveEvent(QGraphicsSceneMouseEvent *ev) override {
        if (ev->buttons() != Qt::LeftButton) return;
        newPoint(ev->scenePos());
    }
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override {
        if (! m_path.isEmpty()) return;
        delete m_item; // Empty items are useless
        m_item = nullptr;
    }
public:
    Scene(QObject *parent = nullptr) : QGraphicsScene{parent}
    {
        addItem(new EmptyItem{});
    }
    Q_SLOT void setJoinFigures(bool j) { m_joinFigures = j; }
    bool joinFigures() const { return m_joinFigures; }
};

class Window : public QWidget
{
    Q_OBJECT
    QGridLayout m_layout{this};
    QGraphicsView m_view;
    QCheckBox m_join{"Join Figures (toggle with Spacebar)"};
    QAction m_toggleJoin{this};
public:
    Window(QWidget * parent = 0) : QWidget{parent}
    {
        m_layout.addWidget(&m_view);
        m_layout.addWidget(&m_join);
        m_view.setAlignment(Qt::AlignLeft | Qt::AlignTop);

        m_toggleJoin.setShortcut(QKeySequence(Qt::Key_Space));
        connect(&m_toggleJoin, SIGNAL(triggered()), &m_join, SLOT(toggle()));
        addAction(&m_toggleJoin);

        m_view.addAction(new QAction{"Clear", this});
        m_view.setContextMenuPolicy(Qt::ActionsContextMenu);
        connect(m_view.actions().at(0), SIGNAL(triggered()), SLOT(newScene()));

        // Create a new scene instead of clear()-ing it, since scenes can only grow their
        // sceneRect().
        newScene();
    }
    Q_SLOT void newScene() {
        if (m_view.scene()) m_view.scene()->deleteLater();
        m_view.setScene(new Scene);
        m_view.scene()->connect(&m_join, SIGNAL(toggled(bool)), SLOT(setJoinFigures(bool)));
    }
};

int main(int argc, char *argv[])
{
    QApplication a{argc, argv};
    Window w;
    w.show();
    return a.exec();
}

#include "main.moc"

关于Qt:线连接2个单独的图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20632209/

相关文章:

java - 哪个鼠标按钮是中间的?

c++ - 在窗口调整大小时重新定位图形项目

c++ - QGraphicsView 周围的自定义边框

c++ - Windows 7下无法加载QtBluetooth 5.12.0

c++ - Qt/QML 从 C++ 类为 GridView 设置属性

c++ - 如何添加到 Qt 书籍示例中,例如将项目添加到列表的可能性?

python - 获取自定义 Qt QGraphicsView 以显示在使用 Qt Designer 制作的表单中

c++ - FFMPEG API - 录制视频和音频 - 同步问题

javascript - 识别圆弧上的事件

java - 使用玻璃 Pane 时,鼠标调整光标大小不起作用