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 г. 3:14

Добрый день!

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

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

      Evgenii Legotckoi
      • 14 октября 2017 г. 8: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

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

          Комментарии

          Только авторизованные пользователи могут публиковать комментарии.
          Пожалуйста, авторизуйтесь или зарегистрируйтесь
          AD

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

          • Результат:50баллов,
          • Очки рейтинга-4
          m
          • molni99
          • 26 октября 2024 г. 9:37

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

          • Результат:80баллов,
          • Очки рейтинга4
          m
          • molni99
          • 26 октября 2024 г. 9:29

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

          • Результат:20баллов,
          • Очки рейтинга-10
          Последние комментарии
          i
          innorwall14 ноября 2024 г. 8:03
          Как написать игру на Qt - Урок 3. Взаимодействие с другими объектами what is priligy tablets What happens during the LASIK surgery process
          i
          innorwall14 ноября 2024 г. 5:09
          Использование переменных объявленных в CMakeLists.txt внутри C++ файлов where can i buy priligy online safely Tom Platz How about things like we read about in the magazines like roid rage and does that really
          i
          innorwall12 ноября 2024 г. 7:12
          Django - Урок 055. Как написать функционал auto populate field Freckles because of several brand names retin a, atralin buy generic priligy
          i
          innorwall12 ноября 2024 г. 3:23
          QML - Урок 035. Использование перечислений в QML без C++ priligy cvs 24 Together with antibiotics such as amphotericin B 10, griseofulvin 11 and streptomycin 12, chloramphenicol 9 is in the World Health Organisation s List of Essential Medici…
          i
          innorwall12 ноября 2024 г. 0:50
          Qt/C++ - Урок 052. Кастомизация Qt Аудио плеера в стиле AIMP It decreases stress, supports hormone balance, and regulates and increases blood flow to the reproductive organs buy priligy online safe Promising data were reported in a PDX model re…
          Сейчас обсуждают на форуме
          i
          innorwall14 ноября 2024 г. 9:39
          добавить qlineseries в функции Listen intently to what Jerry says about Conditional Acceptance because that s the bargaining chip in the song and dance you will have to engage in to protect yourself and your family from AMI S…
          i
          innorwall11 ноября 2024 г. 19:55
          Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
          9
          9Anonim25 октября 2024 г. 17:10
          Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
          ИМ
          Игорь Максимов3 октября 2024 г. 12:05
          Реализация навигации по разделам Спасибо Евгений!

          Следите за нами в социальных сетях