Михаиллл
June 8, 2019, 11:21 p.m.

Как в Qt рисовать поверх рисунка на QLabel

QLabel

Добрый день.
У меня есть Qlabel c рисунком.
Как рисовать поверх этого рисунка овальчики и другие сложные фигуры полупрозрачными красками?

2

Do you like it? Share on social networks!

23
Михаиллл
  • June 9, 2019, 2:01 p.m.

Рисовать можно так. Но как определить положение мышки и при нажатии рисовать, как в Paint?

  1. #include <QMainWindow>
  2. #include <QScrollArea>
  3. #include <QLabel>
  4. #include <QApplication>
  5. #include <QPainter>
  6.  
  7. class MyLabel : public QLabel {
  8. protected:
  9. virtual void paintEvent(QPaintEvent* e) {
  10. QLabel::paintEvent(e);
  11.  
  12. QPainter p(this);
  13. QPen myPen;
  14. myPen.setColor(Qt::black);
  15. myPen.setWidth(5);
  16.  
  17. p.setPen(myPen);
  18. p.drawLine(0, 0, 100, 100);
  19. }
  20. };
  21.  
  22. class ImageView : public QMainWindow {
  23. public:
  24.  
  25. ImageView() : QMainWindow() {
  26. QScrollArea* scr = new QScrollArea();
  27. setCentralWidget( scr );
  28.  
  29. QLabel* label = new MyLabel();
  30. label->setPixmap(QPixmap("C:\\Users\\New Owner\\Downloads\\mapMain.png"));
  31. scr->setWidget(label);
  32. }
  33. };
  34.  
  35.  
  36. int main(int argc, char* argv[]) {
  37. QApplication app(argc, argv);
  38.  
  39. ImageView view;
  40. view.setGeometry(100, 100, 500, 400);
  41. view.show();
  42.  
  43. return app.exec();
  44. }
    Михаиллл
    • June 9, 2019, 6:23 p.m.

    Нашел такой пример. Но как в нем сделать рисование не линиями, а кривые линии при нажатии кнопки мыши , как в Paint?

      Михаиллл
      • June 9, 2019, 8:54 p.m.

      Нашел такой пример. Но тут слишком много ненужного кода. Не могли бы мне помочь уюрать ненужный кодд?!

        Михаиллл
        • June 9, 2019, 9:10 p.m.
        • The answer was marked as a solution.

        Нашел решение тут : https://evileg.com/ru/post/84/

          Evgenii Legotckoi
          • June 10, 2019, 1:49 p.m.

          Вообще для этого лучше использовать графическую сцену, как в ссылке на мой пример, QLabel имеет совершенно другие функции.

            Михаиллл
            • June 10, 2019, 2:13 p.m.

            Понятно. Спасибо.
            Так задал рисунок для графической сцены:

            1. QImage mapImage("C:\\Users\\New Owner\\Downloads\\mapMain.png");
            2. scene->addPixmap(QPixmap::fromImage(mapImage));//add image

            Скажите пожалуйста как добаить QScrollArea, делаю так, но ничего не показывается.:

            1. scrollArea = new QScrollArea(); //QScrollArea
            2. scrollArea->setBackgroundRole(QPalette::Dark);
            3. scrollArea->setWidget(ui->graphicsView);

            И можно ли графической сцене задать 2 картинки и рисовать только на верхней?

              Evgenii Legotckoi
              • June 10, 2019, 2:16 p.m.

              На графическую сцену можно задавать сколько угодно изображений или объектов. Вопрос только в объёме памяти на компьютере.

              Что касается рисования, то вы рисуете не на картинках, которые добавили, а на самой графической сцене.

                Михаиллл
                • June 10, 2019, 2:21 p.m.
                • (edited)

                Но можно ли сцену сохранить как картинку? И растягивать как картинку? И как задать QScrollArea?
                Посмотрел, везде пишут такие варианты добавления QScrollArea:

                1. QLabel *l1 = new QLabel("label1");
                2. scrollArea->setWidget(l1);
                  Evgenii Legotckoi
                  • June 10, 2019, 2:24 p.m.

                  Да, можно, с использованием метода render .

                  QScrollArea не нужна, графическая сцена сама по себе имеет встроенные скроллбары. Они работают автоматически

                    Михаиллл
                    • June 10, 2019, 2:41 p.m.
                    • (edited)

                    По поводу QScrollArea не так. У Меня картинка не влезат в графическую сцену и я вижу только часть картинки, растягиваю окно программы, виджет увеличивается и я вижу немного большую часть моей картинки. Отсюда делаю вывод что QScrollArea нужно. Но она почему то не добовляется.
                    Попробовал сделать так, тоже не добавилась:

                    1. QGraphicsView *myQGraphicsScene = new QGraphicsView();
                    2. myQGraphicsScene->setScene(scene);
                    3.  
                    4. scrollArea = new QScrollArea(); //QScrollArea
                    5. scrollArea->setWidget(myQGraphicsScene);
                    6.  
                    7. ui->verticalLayout->addWidget(myQGraphicsScene);
                      Evgenii Legotckoi
                      • June 10, 2019, 2:52 p.m.
                      • (edited)

                      QGraphicsView наследован от QAbstractScrollArea, то есть он по умолчанию является объектом, который реализует функционал QScrollArea, который также наследован от QAbstractScrollArea, поэтому ваши выводы ошибочны .

                      Если вам нужно, чтобы scrollbar показывался всегда, то включайте его через методы

                      setHorizontalScrollBarPolicy и setVerticalScrollBarPolicy , там нужно установить флаг Qt::ScrollBarAlwaysOn .

                        Михаиллл
                        • June 10, 2019, 2:58 p.m.

                        Спасибо, ScrollBar появился, но в нем нет скрола. Почему? Нужно задать размер чего-то, равный размеру картинки?

                          Evgenii Legotckoi
                          • June 10, 2019, 3 p.m.

                          Скролл появляется лишь в том случае, елси картинка не вмещается в область. Если вы считаете, что она у вас вмещается, то скорее всего у вас другая проблема, может быть в вёрстке или ещё где-то в другом месте, но точно не в скролле QGraphicsView

                            Михаиллл
                            • June 10, 2019, 3:29 p.m.

                            В том то и дело, что я вижу , что картинка не вмещается, в QGraphicsView видно только часть картинки.
                            Других виджетов нет. Картинку задаю только в одном месте в конструкторе

                            1. mapImage.load("C:\\Users\\New Owner\\Downloads\\mapMain.png");
                            2. scene->addPixmap(QPixmap::fromImage(mapImage));//add image
                              Михаиллл
                              • June 10, 2019, 4:03 p.m.
                              • (edited)

                              Дело в сцене, если сделать так, то скрол работает, но программ сразу вылетает

                              1. QGraphicsScene* scene = new QGraphicsScene();
                                Evgenii Legotckoi
                                • June 10, 2019, 4:06 p.m.

                                Графическую сцену и все объекты, которые наследованы от QGraphicsItem в принципе лучше всегда создавать через оператор new. Они очень плохо работают на стеке. Иногда воовсе не работают. Уничтожаются в неподходящий момент и приложение крашится, или просто "не добавляются" на сцену

                                  Михаиллл
                                  • June 10, 2019, 4:08 p.m.

                                  Дело оказалось в строчке

                                  1. scene->setSceneRect(0,0, ui->graphicsView->width() - 20, ui->graphicsView->height() - 20);

                                  закоментировал ее и заработало.

                                    Evgenii Legotckoi
                                    • June 10, 2019, 4:10 p.m.
                                    • (edited)

                                    Ну это вы уже обрезали размер графической сцены. Она автоматически корректируется при изменении размеров QGraphicsView и добавлении новых объектов. А вы принудительно её обрезали. Ничего удивительного что получили "баг".

                                      Михаиллл
                                      • June 10, 2019, 4:32 p.m.

                                      Эта строчку есть у вас в примере, наверно, лучшее ее удалить..
                                      Пробую перенести создание QGraphicsView в класс paintScene.
                                      В конструкторе написал так

                                      1. myQGraphicsScene = new QGraphicsView();
                                      2. scene = new paintScene(); // Инициализируем графическую сцену

                                      И пытаюсь эти воспользоваться, но делаю что то нетак. Скажите пожалуйста, как правильно

                                      1. paintScene mypaintScene;
                                      2. mypaintScene.scene->addPixmap(QPixmap::fromImage(mapImage));//add image
                                      3. //или так
                                      4. paintScene().scene->addPixmap(QPixmap::fromImage(mapImage));//add image
                                        Михаиллл
                                        • June 10, 2019, 5:11 p.m.

                                        Создал такой класс, теперь буду возиться с масштабированием. :

                                        1. class graphicsView: public QGraphicsView
                                        2. {
                                        3. public:
                                        4. graphicsView();
                                        5. ~graphicsView() {};
                                        6. double scaleFactor;
                                        7. QGraphicsView * myGraphicsView;
                                        8. };
                                        9.  
                                        10. graphicsView::graphicsView()
                                        11. {
                                        12. myGraphicsView = new QGraphicsView();
                                        13. }
                                        14.  
                                          Михаиллл
                                          • June 10, 2019, 6:23 p.m.
                                          • (edited)

                                          Написал класс с масштабированием.
                                          Но при масштабировании продолжается рисование (при использовании колесика, а если передаскивать мышкой картинку, то не рисует)(видимо по точке на виджите QGraphicsView). Скажите пожалуйста, как это можно убрать?
                                          .h

                                          1. #ifndef GRAPHICSVIEW_H
                                          2. #define GRAPHICSVIEW_H
                                          3. #include <QGraphicsScene>
                                          4. #include <QGraphicsSceneMouseEvent>
                                          5. #include "QGraphicsView"
                                          6. #include <QTimer>
                                          7. #include <QDebug>
                                          8. #include "QWidget"
                                          9. #include "QObject"
                                          10. #include <QMainWindow>
                                          11. #include "QWheelEvent"
                                          12.  
                                          13.  
                                          14. class graphicsView: public QGraphicsView
                                          15. {
                                          16. Q_OBJECT
                                          17. public:
                                          18. graphicsView();
                                          19. ~graphicsView() {};
                                          20. QGraphicsView * myGraphicsView;
                                          21.  
                                          22. private:
                                          23. bool eventFilter(QObject *obj, QEvent *event); //должно отключить verticalScrollBar от колесика мыши
                                          24. void scaleImage(double factor);
                                          25. qreal _numScheduledScalings = 0;
                                          26. QPoint wheelEventMousePos;
                                          27.  
                                          28. //чужое
                                          29. public slots:
                                          30. void wheelEvent(QWheelEvent* event);
                                          31. void scalingTime(qreal x);
                                          32. void animFinished();
                                          33.  
                                          34.  
                                          35. private slots:
                                          36. };
                                          37.  
                                          38. #endif // GRAPHICSVIEW_H
                                          39.  

                                          .cpp:

                                          1. #include "graphicsview.h"
                                          2. #include "QTimeLine"
                                          3.  
                                          4. graphicsView::graphicsView()
                                          5. {
                                          6. myGraphicsView = new QGraphicsView();
                                          7. //scrollArea->viewport()->installEventFilter(this); //должно отключить verticalScrollBar от колесика мыши
                                          8. myGraphicsView->viewport()->installEventFilter(this); //должно отключить verticalScrollBar от колесика мыши
                                          9.  
                                          10. setTransformationAnchor(QGraphicsView::NoAnchor);
                                          11. setResizeAnchor(QGraphicsView::NoAnchor);
                                          12. }
                                          13.  
                                          14. bool graphicsView::eventFilter(QObject *obj, QEvent *event) //должно отключить verticalScrollBar от колесика мыши
                                          15. {
                                          16. if (event->type() == QEvent::Wheel) {
                                          17. // Don't propagate
                                          18. return true;
                                          19. }
                                          20. // Other events should propagate
                                          21. return false;
                                          22. }
                                          23.  
                                          24. void graphicsView::wheelEvent(QWheelEvent* event)
                                          25. {
                                          26. wheelEventMousePos = event->pos();
                                          27.  
                                          28. int numDegrees = event->delta() / 8;
                                          29. int numSteps = numDegrees / 15; // see QWheelEvent documentation
                                          30. _numScheduledScalings += numSteps;
                                          31. if (_numScheduledScalings * numSteps < 0) // if user moved the wheel in another direction, we reset previously scheduled scalings
                                          32. _numScheduledScalings = numSteps;
                                          33.  
                                          34. QTimeLine *anim = new QTimeLine(350, this);
                                          35. anim->setUpdateInterval(20);
                                          36.  
                                          37. connect(anim, SIGNAL (valueChanged(qreal)), SLOT (scalingTime(qreal)));
                                          38. connect(anim, SIGNAL (finished()), SLOT (animFinished()));
                                          39. anim->start();
                                          40. }
                                          41.  
                                          42. void graphicsView::scalingTime(qreal x)
                                          43. {
                                          44. QPointF oldPos = mapToScene(wheelEventMousePos);
                                          45.  
                                          46. qreal factor = 1.0+ qreal(_numScheduledScalings) / 300.0;
                                          47. scale(factor, factor);
                                          48.  
                                          49. QPointF newPos = mapToScene(wheelEventMousePos);
                                          50. QPointF delta = newPos - oldPos;
                                          51. this->translate(delta.x(), delta.y());
                                          52. }
                                          53.  
                                          54. void graphicsView::animFinished()
                                          55. {
                                          56. if (_numScheduledScalings > 0)
                                          57. _numScheduledScalings--;
                                          58. else
                                          59. _numScheduledScalings++;
                                          60.  
                                          61. sender()->~QObject();
                                          62. }
                                          63.  
                                            Михаиллл
                                            • June 10, 2019, 7:07 p.m.

                                            Видимо нужно добавить функцию отпускания левой кнопки, но как ее реализовать ?

                                              Михаиллл
                                              • June 10, 2019, 7:29 p.m.

                                              Вот так работает:

                                              1. #include "paintscene.h"
                                              2.  
                                              3.  
                                              4. paintScene::paintScene(QObject *parent) : QGraphicsScene(parent)
                                              5. {
                                              6. //myQGraphicsScene = new QGraphicsView();
                                              7. //scene = new paintScene(); // Инициализируем графическую сцену
                                              8. }
                                              9.  
                                              10. paintScene::~paintScene()
                                              11. {
                                              12.  
                                              13. }
                                              14.  
                                              15. void paintScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
                                              16. {
                                              17. // При нажатии кнопки мыши отрисовываем эллипс
                                              18. addEllipse(event->scenePos().x() - 5,
                                              19. event->scenePos().y() - 5,
                                              20. 10,
                                              21. 10,
                                              22. QPen(Qt::NoPen),
                                              23. QBrush(Qt::red));
                                              24. // Сохраняем координаты точки нажатия
                                              25. previousPoint = event->scenePos();
                                              26. buttonIsPressed = true;
                                              27. }
                                              28.  
                                              29. void paintScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
                                              30. {
                                              31. if (buttonIsPressed)
                                              32. {
                                              33. // Отрисовываем линии с использованием предыдущей координаты
                                              34. addLine(previousPoint.x(),
                                              35. previousPoint.y(),
                                              36. event->scenePos().x(),
                                              37. event->scenePos().y(),
                                              38. QPen(Qt::red,10,Qt::SolidLine,Qt::RoundCap));
                                              39. // Обновляем данные о предыдущей координате
                                              40. previousPoint = event->scenePos();
                                              41. }
                                              42. }
                                              43.  
                                              44. void paintScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
                                              45. {
                                              46. buttonIsPressed = false;
                                              47. }

                                                Comments

                                                Only authorized users can post comments.
                                                Please, Log in or Sign up
                                                • Last comments
                                                • IscanderChe
                                                  April 12, 2025, 5:12 p.m.
                                                  Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
                                                • AK
                                                  April 1, 2025, 11:41 a.m.
                                                  Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
                                                • Evgenii Legotckoi
                                                  March 9, 2025, 9:02 p.m.
                                                  К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
                                                • VP
                                                  March 9, 2025, 4:14 p.m.
                                                  Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
                                                • ИМ
                                                  Nov. 22, 2024, 9:51 p.m.
                                                  Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…