© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB
12 октября 2017 г. 18: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);
    }
}

Добрый день!

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

Для Django рекомендую VDS-хостинг TIMEWEB

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

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

Смотрите какие здесб будут моменты:
Не нужно передавать 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();
}
Весь проект во вложении.

Для Django рекомендую VDS-хостинг TIMEWEB

  • #
  • 15 октября 2017 г. 15:30

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

Ответы

Только авторизованные пользователи могут отвечать на форуме.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
21 сентября 2018 г. 15:37
irishaa

C++ - Тест 005. Структуры и Классы

  • Результат 41баллов,
  • Очки рейтинга-8
20 сентября 2018 г. 20:16
ZaRYa

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

  • Результат 46баллов,
  • Очки рейтинга-6
17 сентября 2018 г. 20:45
Иван Поп

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

  • Результат 93баллов,
  • Очки рейтинга8
Последние комментарии
21 сентября 2018 г. 9:24
Евгений Легоцкой

Qt Linux - Урок 001. Автозапуск Qt приложения под Linux

Если я вас правильно понял, то авторестарт сюда дописывается  QString autorunContent. Не могли бы вы не выделять пока слова жирным текстом, в комментариях сломан парсинг тегов, завтра буд...
21 сентября 2018 г. 9:08
avovana

Qt Linux - Урок 001. Автозапуск Qt приложения под Linux

Спасибо за статью! Пример рабочий! Со своим проектом тоже получилось! Наткнулся на эту статью когда решал задачу запуска Qt app с помощью . Когда пробовал с помощью...
20 сентября 2018 г. 13:27
Евгений Легоцкой

Привет Qt для Python

Может быть, я не все новости отслеживаю по Qt. По возможности слежу, но не всегда удаётся.
20 сентября 2018 г. 13:17
OBEH

Привет Qt для Python

По моему. в последней версии Qt анонсировали поддержку Python. Я где-то видел видео. К сожалению. не помню ссылку. Там что-то. типа. проекта "Qt forPython". Все аналогично тому. как для ...
20 сентября 2018 г. 9:58
Евгений Легоцкой

Привет Qt для Python

Qt Creator и Qt Designer по сути не имеют поддержки Python, чтобы код автоматически генерировался и т.д. Нужно устанавливаться дополнительные инструменты. Например сам Python, рекмоендую...
Сейчас обсуждают на форуме
22 сентября 2018 г. 16:21
Евгений Сальников

Проблемы при создании приложения под андроид

Добрый день!Хочу написать приложения для себя на телефон. Но запнулся на этапе создания проекта. в профилях Qt для Qt 5.11.2 for Android ARMv7 и Qt 5.11.2 for Android x86 пишет что: компилятор не...
21 сентября 2018 г. 8:25
Евгений Легоцкой

Прокси-модель, содержащая на 1 столбец больше, чем модель-источник.

Попробуйте ещё PySide 2 - это официально поддерживаемый пакет привязок Python к Qt, возможно, что там не будет таких проблем.
20 сентября 2018 г. 20:06
Евгений Легоцкой

Qt Installer Framework

Добрый день. Зачем собирать Qt Installer Framework-то из исходников? Я ещё понимаю Qt собирают из исходников статически (хотя тоже считаю по большей части бесполезной тратой времени),...
19 сентября 2018 г. 10:19
Евгений Легоцкой

Как в listview подставить модель?

Добрый день. А нельзя ли использовать какой-нибудь глобальный map контейнер, который бы мапил названия моделей на указатели этих моделей?
17 сентября 2018 г. 11:08
Евгений Легоцкой

Проблемы с статической компиляцией Qt с MySQL

Ну если, то да. Тогда просто буду давать ссылку на этот топик, если будут возникать подобные вопросы. Спасибо за ответ.
Присоединяйтесь к нам в социальных сетях