@kaka888
C, C++, Qt, Python Flask, MySQL, Lua

Почему трясётся виджет во время перемещения мышью?

Создал собственный класс, унаследованный от QWidget, определил для него методы mousePressEvent, mouseMoveEvent и mouseReleaseEvent для того, чтобы пользователь мог перемещать его по экрану курсором мыши. Перемещается, но почему-то с низкой скоростью, да ещё и заметно трясётся в стороны.
Почему так происходит и как это исправить?

Код:
canvas.h
#ifndef CANVAS_H
#define CANVAS_H

#include <QObject>
#include "figures.h"
#include <functional>


class Canvas : public QFrame
{
    Q_OBJECT
public:
    Figure *elements;
    std::function<void(void)> figureCreator;
    explicit Canvas(QWidget *parent = nullptr);
    ~Canvas();

protected:
    void mousePressEvent(QMouseEvent *event) override;

private:
    bool onAddingFigure;
    bool onAddingLink;
    bool onMoving;
    bool onDeleting;

signals:
    void addingFigureFinished(FigureType figureType);
};

#endif // CANVAS_H

figures.h
#ifndef FIGURE_H
#define FIGURE_H

#include <QObject>
#include <QRect>
#include <QSet>
#include <QWidget>
#include <QStyle>
#include <QStyleOption>
#include <QPainter>
#include <QMouseEvent>


enum class FigureType
{
    Rectangle,
    Triangle,
    Ellipse
};


class Figure : public QWidget
{
    Q_OBJECT

private:
    QPoint oldPos;
    bool dragging = false;

protected:
    QSet<Figure*> linkedFigures;

    virtual void mousePressEvent(QMouseEvent *event) override;
    virtual void mouseMoveEvent(QMouseEvent *event) override;
    virtual void mouseReleaseEvent(QMouseEvent *event) override;

public:
    Figure(int left, int top, int width, int height, QWidget *parent = nullptr);
    void connect(Figure *figure);

signals:

};


class Rectangle : public Figure
{
    Q_OBJECT

public:
    Rectangle(int left, int top, int width, int height, QWidget *parent);

protected:
    virtual void paintEvent(QPaintEvent *event) override;

signals:

};


#endif // FIGURE_H

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

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

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    bool addingRectangle;
    bool addingTriangle;
    bool addingEllipse;

private slots:
    void on_figure_added(FigureType figureType);

    void on_pushButton_rectangle_clicked();

    void on_pushButton_triangle_clicked();

    void on_pushButton_ellipse_clicked();

    void on_pushButton_connection_clicked();

    void on_pushButton_move_clicked();

    void on_pushButton_delete_clicked();

    void on_pushButton_load_clicked();

    void on_pushButton_save_clicked();

private:
    Ui::MainWindow *ui;
    Canvas *canvas;
};
#endif // MAINWINDOW_H

canvas.cpp
#include "canvas.h"
#include <QDebug>

Canvas::Canvas(QWidget *parent)
    : QFrame{parent}
{
    this->setFrameShape(StyledPanel);
    this->setFrameShadow(Sunken);
}

Canvas::~Canvas()
{
}

// Для добавления новых фигур на холст
void Canvas::mousePressEvent(QMouseEvent *event)
{
#define figureTypeId (FigureType::Rectangle) // заглушка
    emit addingFigureFinished(figureTypeId);
#undef figureTypeId // заглушка
}

figures.cpp
#include "figures.h"
#include <QDebug>


void Figure::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        dragging = true;
        this->raise();
        QPoint pos = event->position().toPoint();
        oldPos = pos;
    }
}

void Figure::mouseMoveEvent(QMouseEvent *event)
{
    if (dragging)
    {
        QPoint pos = event->position().toPoint();
        QPoint delta = pos - oldPos;
        oldPos = pos;
        QPoint figurePos = this->pos();
        this->move(figurePos + delta);
    }
}

void Figure::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        dragging = false;
}

Figure::Figure(int left, int top, int width, int height, QWidget *parent)
    : QWidget(parent)
{
    this->setGeometry(left, top, width, height);
    this->setStyleSheet("background-color: #999999");
}

void Figure::connect(Figure *figure)
{
    linkedFigures.insert(figure);
    figure->linkedFigures.insert(this);
}

Rectangle::Rectangle(int left, int top, int width, int height, QWidget *parent)
    : Figure(left, top, width, height, parent)
{
}

void Rectangle::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(QPen(Qt::NoPen));
    painter.setBrush(QBrush(0xEEEE00, Qt::SolidPattern));
    painter.drawRect(QRect(QPoint(0, 0), this->size()));
    Q_UNUSED(event);
}

mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    canvas = new Canvas(this);
    canvas->setGeometry(10, 50, 771, 361);
    canvas->setStyleSheet("background-color: white;");
    // Добавление фигуры на холст
    Figure *figure1 = new Rectangle(100, 20, 200, 100, canvas);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_figure_added(FigureType figureType)
{
}

void MainWindow::on_pushButton_rectangle_clicked()
{
    this->addingRectangle = true;
}

void MainWindow::on_pushButton_triangle_clicked()
{
    this->addingTriangle = true;
}

void MainWindow::on_pushButton_ellipse_clicked()
{
    this->addingEllipse = true;
}

void MainWindow::on_pushButton_connection_clicked()
{

}

void MainWindow::on_pushButton_move_clicked()
{

}

void MainWindow::on_pushButton_delete_clicked()
{

}

void MainWindow::on_pushButton_load_clicked()
{

}

void MainWindow::on_pushButton_save_clicked()
{

}

main.cpp
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.setWindowTitle("Visio");
    w.show();
    return a.exec();
}

visio.pro
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    canvas.cpp \
    figures.cpp \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    canvas.h \
    figures.h \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>791</width>
    <height>457</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton_rectangle">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>101</width>
      <height>24</height>
     </rect>
    </property>
    <property name="text">
     <string>Прямоугольник</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_triangle">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>10</y>
      <width>81</width>
      <height>24</height>
     </rect>
    </property>
    <property name="text">
     <string>Треугольник</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_ellipse">
    <property name="geometry">
     <rect>
      <x>210</x>
      <y>10</y>
      <width>71</width>
      <height>24</height>
     </rect>
    </property>
    <property name="text">
     <string>Эллипс</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_connection">
    <property name="geometry">
     <rect>
      <x>310</x>
      <y>10</y>
      <width>71</width>
      <height>24</height>
     </rect>
    </property>
    <property name="text">
     <string>Связь</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_move">
    <property name="geometry">
     <rect>
      <x>410</x>
      <y>10</y>
      <width>91</width>
      <height>24</height>
     </rect>
    </property>
    <property name="text">
     <string>Переместить</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_delete">
    <property name="geometry">
     <rect>
      <x>510</x>
      <y>10</y>
      <width>71</width>
      <height>24</height>
     </rect>
    </property>
    <property name="text">
     <string>Удалить</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>791</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>
  • Вопрос задан
  • 183 просмотра
Решения вопроса 1
@kaka888 Автор вопроса
C, C++, Qt, Python Flask, MySQL, Lua
Причина оказалась в относительных координатах курсора. Корректные координаты получаются только если вызывать event->globalPosition().
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы