m
mihenze12 жовтня 2017 р. 14: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);
    }
}
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

4
Evgenii Legotckoi
  • 13 жовтня 2017 р. 03:14

Добрый день!

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

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

      Evgenii Legotckoi
      • 14 жовтня 2017 р. 08: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();
      }
      Весь проект во вложении.
        m
        • 15 жовтня 2017 р. 11:30

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

          Коментарі

          Only authorized users can post comments.
          Please, Log in or Sign up
          Дмитрий

          C++ - Тест 004. Указатели, Массивы и Циклы

          • Результат:60бали,
          • Рейтинг балів-1
          Дмитрий

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

          • Результат:92бали,
          • Рейтинг балів8
          d
          • dsfs
          • 26 квітня 2024 р. 04:56

          C++ - Тест 004. Указатели, Массивы и Циклы

          • Результат:80бали,
          • Рейтинг балів4
          Останні коментарі
          k
          kmssr08 лютого 2024 р. 18:43
          Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
          АК
          Анатолий Кононенко05 лютого 2024 р. 01:50
          Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
          EVA
          EVA25 грудня 2023 р. 10:30
          Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
          J
          JonnyJo25 грудня 2023 р. 08:38
          Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
          G
          Gvozdik18 грудня 2023 р. 21:01
          Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
          Тепер обговоріть на форумі
          G
          George1307 травня 2024 р. 00:27
          добавить qlineseries в функции в функции: "GPlotter::addSeries(QString title, QVector &arr)" я вызываю метод setChart(...), я в конструктор передал адрес на QChartView элемент
          BlinCT
          BlinCT05 травня 2024 р. 05:46
          Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
          PS
          Peter Son03 травня 2024 р. 17:57
          Best Indian Food Restaurant In Cincinnati OH Ready to embark on a gastronomic journey like no other? Join us at App india restaurant and discover why we're renowned as the Best Indian Food Restaurant In Cincinnati OH . Whether y…
          Evgenii Legotckoi
          Evgenii Legotckoi02 травня 2024 р. 14:07
          Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
          IscanderChe
          IscanderChe30 квітня 2024 р. 04:22
          Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

          Слідкуйте за нами в соціальних мережах