3

我想允许用户使用鼠标在图像上画线,我正在使用图形视图和鼠标事件,但我得到的位置不是相对于图像的正确位置这里是鼠标事件函数

void InitializationDialog::mousePressEvent(QMouseEvent *event) {
    if(drawing) {
        points.append(event->pos());
        if(!points.isEmpty()) {
            if(points.size()==1) {
                QString fileName = list.at(choosed);
                QImage image(fileName);
                QGraphicsScene* scene = new QGraphicsScene();
                QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
                scene->addItem(item);
                QColor color(255,0,0);
                QBrush brush(color);
                QPen pen(brush, 4);
                QGraphicsLineItem* line = new QGraphicsLineItem(points.at(0).x(),points.at(0).y(),points.at(0).x()+1,points.at(0).y()+1);
                line->setPen(pen);
                scene->addItem(line);

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

那应该画一个点(我用一个像素长的线代替它看起来像一个点)

现在我得到了远离鼠标点击的红点,如图所示 在此处输入图像描述

我怎样才能让它完全在鼠标光标上?

编辑:

我为图形场景创建了一个自定义类以获得相对于它的点击,我尝试覆盖鼠标按下图形视图,但场景与图形视图的大小不同,并且鼠标点击仍然远离

在我的自定义场景中按下覆盖鼠标并没有太大帮助,因为无论我在哪里点击,我总是获得 0,0 位置来点击场景

新文件代码:

头文件

#ifndef INITGRAPH_H
#define INITGRAPH_H
#include <QtGui>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPoint>
#include <QGraphicsSceneMouseEvent>
class InitGraph : public QGraphicsView {
    Q_OBJECT
public:
    InitGraph(QWidget *parent = 0);
    virtual ~InitGraph() {};
};

class CustomScene : public QGraphicsScene {
    Q_OBJECT
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
signals:
    void pressed(QPoint p);
};
#endif // INITGRAPH_H

源文件

#include "initgraph.h"
InitGraph::InitGraph(QWidget *parent):QGraphicsView(parent)
{
}
void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event){
    qDebug(QString::number(event->pos().rx()).toLatin1());
    QPoint p = event->pos().toPoint();
    emit pressed(p);
}
4

3 回答 3

2

如果你想添加一个QGraphicsLineItem你必须使用场景的系统坐标,你必须使用函数的scenePos()方法QGraphicsSceneMouseEventmapFromScene()项目的方法。

为此,我们必须重写方法mousePressEventmouseMoveEvent以及mouseReleaseEvent以上QGraphicsScene所有内容,我在以下类中实现了它:

class CustomScene : public QGraphicsScene
{
    Q_OBJECT
    QGraphicsLineItem *item;
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event){

        item = new QGraphicsLineItem;
        addItem(item);
        const QPointF p = event->scenePos();

        item->setPos(p);
    }

    void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
        const QPointF p  =item->mapFromScene(event->scenePos());
        QLineF l = item->line();
        l.setP2(p);
        item->setLine(l);
    }

    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
        const QPointF p  =item->mapFromScene(event->scenePos());
        QLineF l = item->line();
        l.setP2(p);
        item->setLine(l);
    }

};

完整的代码在以下链接中。

于 2017-09-06T02:28:57.857 回答
1

由于您正在重载对话框的鼠标事件,因此鼠标位置位于对话框坐标中。最好使用绘图小部件事件让 Qt 为您进行所有对话,并且不过滤对话框区域。

为了使其真正可重用,您可以实现 QGraphicsItem Drawable 子类并在那里处理鼠标事件,添加或编辑子类。

编辑 这里是你的工作示例qt-drawable-item-example

简要地:

void DrawableItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
    m_activePath = new QGraphicsPathItem(this);
    m_activePath->setPen(QPen(Qt::GlobalColor(rand()%17+2), 2.0));
    m_activePath->setPath(QPainterPath(event->pos()));
}

void DrawableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
    if(!m_activePath) {
        QGraphicsItem::mouseMoveEvent(event);
        return;
    }

    auto path = m_activePath->path();
    path.lineTo(event->pos());
    m_activePath->setPath(path);
}

void DrawableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
    if(!m_activePath) {
        QGraphicsItem::mouseReleaseEvent(event);
        return;
    }
    m_activePath = nullptr;
}
于 2017-09-05T09:34:40.610 回答
1

您正在接收点击 InitializationDialog 的位置,但不是在您的 graphicsView 上,因此您需要通过减去您的 graphicsView 的 x 和 y 来转换此位置

QGraphicsLineItem* line = new QGraphicsLineItem(
                          points.at(0).x()-graphicsView->rect().x(), 
                          points.at(0).y()-graphicsView->rect().y(), 
                          points.at(0).x()+1, points.at(0).y()+1);
于 2017-09-05T11:54:50.860 回答