Qt:线连接2个单独的工程图 [英] Qt: Line connects 2 separate drawings

查看:132
本文介绍了Qt:线连接2个单独的工程图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

得出不同的任意数字.在图形视图中单击鼠标时开始绘制,而在停止单击鼠标时结束.但是,当从图形视图中的不同点开始以制作新图形或在上一个图形上继续时,会从第一个图形的最后一个鼠标坐标到第二个图形的第一个坐标绘制一条线.这些图不必一定是不同的图,而也可以只是对图的调整.这是我的代码.

i want to draw different arbitrary figures. Drawing starts when the mouse is clicked in the graphicsview and ends when stop clicking the mouse. However, when starting at a different point in the graphics view to make a new drawing, or to continue on the previous drawing, a line is drawn from the last mouse coordinate of the first drawing, to the first coordinate of the second drawing. The drawings do not necessarily need to be different drawings, but can also just be adjustments to the drawing. This is my code.

#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可以正确地为您处理所有问题.

Having a custom MouseDraw class derived from QGraphicsItem is unnecessary. There is a QGraphicsPathItem that handles it all for you, correctly.

在正在创建的项目中处理鼠标交互在概念上是不正确的-大的矩形边框是使其工作所需的技巧,但这是错误的方法.您不希望 item 与鼠标进行交互.您希望 scene 与鼠标交互并动态创建一个项目.仅当编辑一个现有项目时,您才需要进行鼠标交互,但是即使这样,还是最好在要编辑的项目上创建一个单独的编辑器项目,以处理编辑交互.

It is conceptually incorrect to process the mouse interaction within the item being created - your large bounding rectangle is a hack that's needed for it to work, but it's the wrong approach. You don't want the item to interact with the mouse. You want the scene to interact with the mouse and create an item on the fly. Only when editing an existing item you'd want to have mouse interaction, but even then it's better to create a separate editor item overlaid on the item being edited to handle the editing interaction.

使用鼠标右键单击窗口以获取上下文菜单,并带有清除图片的操作.您还可以切换是否将后续路径连接到前一个路径.此代码已通过Qt 4.8.5和5.2进行了测试.

Click on the window with right mouse button to get a context menu with the action to clear the picture. You can also toggle whether the subsequent path is joined to the previous one. This code is tested with both Qt 4.8.5 and 5.2.

当场景小于视图时,视图会坚持将其居中(使用 alignment 属性). EmptyItem用作此功能"的解决方法,以在场景小于视图时(包括场景为空"时)限制场景在视图内的位置.

When the scene is smaller than the view, the view insists on centering it (using the alignment property). An EmptyItem is used as a workaround to this "feature", to constrain the location of the scene within the view when the scene is smaller than the view (including when the scene is "empty").

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

The code creates a separate item for each disjoint path - QGraphicsScene generally will perform the best with multiple non-overlapping items. You could of course retain just one item and keep adding new segments to it on each mouse press, but that will, eventually, have performance implications - especially if you zoom into the scene, where you'd expect the performance to get better as less is shown.

// 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个单独的工程图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆