m
mihenzeҚаз. 12, 2017, 2: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, 1:37 Т.Ж.

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

          • Нәтиже:80ұпай,
          • Бағалау ұпайлары4
          m
          • molni99
          • Қаз. 26, 2024, 1:29 Т.Ж.

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

          • Нәтиже:20ұпай,
          • Бағалау ұпайлары-10
          Соңғы пікірлер
          ИМ
          Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
          Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
          Evgenii Legotckoi
          Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
          Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
          A
          ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
          Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
          ИМ
          Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
          Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
          d
          dblas5Шілде 5, 2024, 11:02 Т.Ж.
          QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
          Енді форумда талқылаңыз
          m
          moogoҚар. 22, 2024, 7:17 Т.Ж.
          Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
          Evgenii Legotckoi
          Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
          добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
          t
          tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
          google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
          NSProject
          NSProjectМаусым 4, 2022, 3:49 Т.Ж.
          Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

          Бізді әлеуметтік желілерде бақылаңыз