Реклама
  • 13 октября 2017 г. 0:15

Рисуем линию QGraphicsItem за мышью

Здравствуйте. Два дня пытался сделать отрисовку линии объявленной как QGraphicsItem в сцене. Хочу чтобы при зажатой кнопке прямая линия отрисовывалась за мышью. Но что-то не выходит. Прочитал данный топик https://evileg.com/forum/topic/218/ , но он как раз про простой способ рисования, когда методы мыши реализованы в сцене(это получилось). Но когда я хочу чтобы сам Item отвечал за отрисовку, выходит нечто странное.  Вообщем зашел в тупик и не знаю что делать. Вот мой исходный код:

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "myscene.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
};

#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);
    MyScene *pScene = new MyScene(this);
    ui->centralWidget->setScene(pScene);

    connect(ui->actionRect, SIGNAL(triggered(bool)), ui->centralWidget->scene(), SLOT(mySlotLine()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
myscene.h
#ifndef MYSCENE_H
#define MYSCENE_H

#include<QObject>
#include<QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include<QColor>
#include<QString>
#include"myline.h"

class MyScene : public QGraphicsScene
{
    Q_OBJECT
public:
    MyScene(QObject *parent =0);

protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent);
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);

private:
    MyLine *line;
    bool isDrawLine = false;
    void addMyLine(QPointF p);


public slots:
    void mySlotLine();

};

#endif // MYSCENE_H
myscene.cpp
#include "myscene.h"

MyScene::MyScene(QObject *parent) : QGraphicsScene(parent)
{

    setSceneRect(0,0,500,500);

    setFocus();

}

void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if ((mouseEvent->button() == Qt::LeftButton)&&(isDrawLine))
    {
        isDrawLine = false;
        addMyLine(mouseEvent->scenePos());
    }
    line->mousePressEvent(mouseEvent);

}

void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    line->mouseMoveEvent(mouseEvent);
}

void MyScene::mySlotLine()
{
    line = new MyLine(this);
    isDrawLine = true;
}

void MyScene::addMyLine(QPointF p)
{

    line->setPoint(p, p);
    line->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
    addItem(line);
}
myline.h
#ifndef MYLINE_H
#define MYLINE_H

#include <QObject>
#include <QGraphicsItem>
#include <QRectF>
#include <QGraphicsSceneMouseEvent>
#include <QPen>
#include <QPainter>

class MyLine : public QObject , public QGraphicsItem
{
    Q_OBJECT
public:
    MyLine(QObject *parent = 0);
    ~MyLine();

    void setPoint(QPointF beginP, QPointF endP);

    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

protected:
    virtual QRectF boundingRect() const;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
    QPointF p1;
    QPointF p2;


};

#endif // MYLINE_H
myline.cpp
#include "myline.h"

MyLine::MyLine(QObject *parent): QObject(parent), QGraphicsItem()
{

}

MyLine::~MyLine()
{

}

void MyLine::setPoint(QPointF beginP, QPointF endP)
{
    p1 = beginP;
    p2 = endP;
}

void MyLine::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mousePressEvent(event);
}

void MyLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    p2 = event->scenePos();
    this->setPoint(p1, p2);
    QGraphicsItem::mouseMoveEvent(event);
}

void MyLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mouseReleaseEvent(event);
}

QRectF MyLine::boundingRect() const
{
    return QRectF(p1,p2).normalized();
}

void MyLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen pen;

    pen.setWidth(5);
    pen.setBrush(Qt::black);

    painter->setPen(pen);

    if (p1 == p2)
    {
        painter->drawPoint(p1);
    }
    else
    {
        painter->drawLine(p1,p2);
    }
}
  • #
  • 13 октября 2017 г. 13:14

Добрый день!

Фух, надо будет у себя повторить ваш код, да посмотреть, как у вас работает, если имеете возможность, то прикрепите в сообщении архив проекта. Я вечером после работы гляну его.
  • #
  • 13 октября 2017 г. 13:32

Файлы проекта

testGraphics.zip
  • mihenze
  • #
  • отредактировано 14 октября 2017 г. 18:29
  • 14 октября 2017 г. 18:29

Я поправил немного Ваш код.

Смотрите какие здесб будут моменты:
Не нужно передавать mouseEvent в метод mouseMoveEvent(), лучше сделать отдельный методв для установки конечной точки линии и вызывать метод перерисовки.
void MyLine::setEndPoint(QPointF endPoint)
{
    p2 = endPoint;
    update();
}
Также, неправильная реализация методы boundingRect(), там нужно следить за правильностью использования точек topLeft и rightBottom, поскольку точки p1 и p2 могут им несоответсвуовать в линии.
QRectF MyLine::boundingRect() const
{
    QPointF topLeft = QPointF(p1.x() < p2.x() ? p1.x() : p2.x(),
                              p1.y() < p2.y() ? p1.y() : p2.y());
    QPointF rightBootom = QPointF(p1.x() > p2.x() ? p1.x() : p2.x(),
                                  p1.y() > p2.y() ? p1.y() : p2.y());
    return QRectF(topLeft, rightBootom);
}
Метода mouse event`ов в линии не потребуются в данном случае, я их удалил.
Также несколько поправил методы перемещения мыши в графической сцене.
void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if ((mouseEvent->button() == Qt::LeftButton)&&(isDrawLine))
    {
        isDrawLine = false;
        addMyLine(mouseEvent->scenePos());
    }
}

void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    line->setEndPoint(mouseEvent->scenePos());
    update();
}
Весь проект во вложении.
testGraphics.zip
  • #
  • 15 октября 2017 г. 21:30

Большое спасибо!

Реклама

Ответы

Только авторизованные пользователи могут отвечать на форуме.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
  • BlinCT
  • 22 октября 2017 г. 12:46

C++ - Тест 003. Условия и циклы

  • Результат 64 баллов
  • Очки рейтинга -1
  • Kiops
  • 22 октября 2017 г. 3:56

C++ - Тест 001. Первая программа и типы данных

  • Результат 86 баллов
  • Очки рейтинга 6
  • Kiops
  • 22 октября 2017 г. 2:41

Qt - Тест 001. Сигналы и слоты

  • Результат 100 баллов
  • Очки рейтинга 10
Последние комментарии
  • EVILEG
  • 21 октября 2017 г. 3:06

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

Добавил архив с проектом

  • EVILEG
  • 20 октября 2017 г. 20:06

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

После работы поищу, должен где-то быть на винте.

  • Миша
  • 20 октября 2017 г. 20:04

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

не могли бы вы выложить архив с рабочей версией скрипта?

  • EVILEG
  • 20 октября 2017 г. 20:03

Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками

Использование дизайнера в Qt Creator и использование ui файлов является распространённой практикой в Qt фреймворке. Написать отдельную статью про то, что это такое? - может быть. Опи...

  • Миша
  • 20 октября 2017 г. 19:43

Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками

Но почему вы это не описали? Не могли бы вы описать.

Сейчас обсуждают на форуме
  • EVILEG
  • 22 октября 2017 г. 12:05

Закрепление якорей в момент создания объекта через JS

Добрый день! Якоря - это не те свойства, которые можно устанавливать сразу по инициализации, лучше их править после создания объекта, поскольку при одновременной установке они могут в...

  • EVILEG
  • 21 октября 2017 г. 23:33

Создание истории редактирования постов на сайте

Ясно. Тогда я лучше не буду тратить время на его проверку. Тем более, что я использую гугловский prettyprint для подсветки кода. Спасибо за информацию.

QFile::copy() возвращает false

Получилось! Спасибо огромное! path1 = "C:/Users/555/Pictures/00GAF13AP001-002.jpg"true

  • cordsac
  • 19 октября 2017 г. 15:49

How can I select the QGraphicView Item and change the properties

Ok I'll check it sir,If you can please do article(tutorial) about this,Its really useful.Thank you if you can give me some sample code when you free.thanks again

  • cordsac
  • 17 октября 2017 г. 19:28

How can I open SVG file through QT

Okay,Thank you sir :)