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

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

QLabel

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

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

23
Михаиллл
  • June 9, 2019, 4:01 a.m.

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

#include <QMainWindow>
#include <QScrollArea>
#include <QLabel>
#include <QApplication>
#include <QPainter>

class MyLabel : public QLabel {
protected:
  virtual void paintEvent(QPaintEvent* e) {
    QLabel::paintEvent(e);

    QPainter p(this);
    QPen myPen;
    myPen.setColor(Qt::black);
    myPen.setWidth(5);

    p.setPen(myPen);
    p.drawLine(0, 0, 100, 100);
  }
};

class ImageView : public QMainWindow {
public:

  ImageView() : QMainWindow() {
    QScrollArea* scr = new QScrollArea();
    setCentralWidget( scr );

    QLabel* label = new MyLabel();
    label->setPixmap(QPixmap("C:\\Users\\New Owner\\Downloads\\mapMain.png"));
    scr->setWidget(label);
  }
};


int main(int argc, char* argv[]) {
  QApplication app(argc, argv);

  ImageView view;
  view.setGeometry(100, 100, 500, 400);
  view.show();

  return app.exec();
}
    Михаиллл
    • June 9, 2019, 8:23 a.m.

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

      Михаиллл
      • June 9, 2019, 10:54 a.m.

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

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

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

          Evgenii Legotckoi
          • June 10, 2019, 3:49 a.m.

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

            Михаиллл
            • June 10, 2019, 4:13 a.m.

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

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

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

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

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

              Evgenii Legotckoi
              • June 10, 2019, 4:16 a.m.

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

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

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

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

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

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

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

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

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

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

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

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

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

                        Михаиллл
                        • June 10, 2019, 4:58 a.m.

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

                          Evgenii Legotckoi
                          • June 10, 2019, 5 a.m.

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

                            Михаиллл
                            • June 10, 2019, 5:29 a.m.

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

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

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

                              QGraphicsScene* scene = new QGraphicsScene();
                              
                                Evgenii Legotckoi
                                • June 10, 2019, 6:06 a.m.

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

                                  Михаиллл
                                  • June 10, 2019, 6:08 a.m.

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

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

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

                                    Evgenii Legotckoi
                                    • June 10, 2019, 6:10 a.m.
                                    • (edited)

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

                                      Михаиллл
                                      • June 10, 2019, 6:32 a.m.

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

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

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

                                      paintScene mypaintScene;
                                      mypaintScene.scene->addPixmap(QPixmap::fromImage(mapImage));//add image
                                      //или так 
                                      paintScene().scene->addPixmap(QPixmap::fromImage(mapImage));//add image
                                      
                                        Михаиллл
                                        • June 10, 2019, 7:11 a.m.

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

                                        class graphicsView: public QGraphicsView
                                        {
                                        public:
                                            graphicsView();
                                            ~graphicsView() {};
                                            double scaleFactor;
                                            QGraphicsView * myGraphicsView;
                                        };
                                        
                                        graphicsView::graphicsView()
                                        {
                                            myGraphicsView = new QGraphicsView();
                                        }
                                        
                                        
                                          Михаиллл
                                          • June 10, 2019, 8:23 a.m.
                                          • (edited)

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

                                          #ifndef GRAPHICSVIEW_H
                                          #define GRAPHICSVIEW_H
                                          #include <QGraphicsScene>
                                          #include <QGraphicsSceneMouseEvent>
                                          #include "QGraphicsView"
                                          #include <QTimer>
                                          #include <QDebug>
                                          #include "QWidget"
                                          #include "QObject"
                                          #include <QMainWindow>
                                          #include "QWheelEvent"
                                          
                                          
                                          class graphicsView: public QGraphicsView
                                          {
                                              Q_OBJECT
                                          public:
                                              graphicsView();
                                              ~graphicsView() {};
                                              QGraphicsView * myGraphicsView;
                                          
                                          private:
                                              bool eventFilter(QObject *obj, QEvent *event); //должно отключить verticalScrollBar  от колесика мыши
                                              void scaleImage(double factor);
                                              qreal _numScheduledScalings = 0;
                                              QPoint wheelEventMousePos;
                                          
                                          //чужое
                                          public slots:
                                              void wheelEvent(QWheelEvent* event);
                                              void scalingTime(qreal x);
                                              void animFinished();
                                          
                                          
                                          private slots:
                                          };
                                          
                                          #endif // GRAPHICSVIEW_H
                                          
                                          

                                          .cpp:

                                          #include "graphicsview.h"
                                          #include "QTimeLine"
                                          
                                          graphicsView::graphicsView()
                                          {
                                              myGraphicsView = new QGraphicsView();
                                              //scrollArea->viewport()->installEventFilter(this); //должно отключить verticalScrollBar  от колесика мыши
                                              myGraphicsView->viewport()->installEventFilter(this); //должно отключить verticalScrollBar  от колесика мыши
                                          
                                              setTransformationAnchor(QGraphicsView::NoAnchor);
                                              setResizeAnchor(QGraphicsView::NoAnchor);
                                          }
                                          
                                          bool graphicsView::eventFilter(QObject *obj, QEvent *event)   //должно отключить verticalScrollBar  от колесика мыши
                                          {
                                              if (event->type() == QEvent::Wheel) {
                                                  // Don't propagate
                                                  return true;
                                              }
                                              // Other events should propagate
                                              return false;
                                          }
                                          
                                          void graphicsView::wheelEvent(QWheelEvent* event)
                                          {
                                              wheelEventMousePos = event->pos();
                                          
                                              int numDegrees = event->delta() / 8;
                                              int numSteps = numDegrees / 15; // see QWheelEvent documentation
                                              _numScheduledScalings += numSteps;
                                              if (_numScheduledScalings * numSteps < 0) // if user moved the wheel in another direction, we reset previously scheduled scalings
                                                  _numScheduledScalings = numSteps;
                                          
                                              QTimeLine *anim = new QTimeLine(350, this);
                                              anim->setUpdateInterval(20);
                                          
                                              connect(anim, SIGNAL (valueChanged(qreal)), SLOT (scalingTime(qreal)));
                                              connect(anim, SIGNAL (finished()), SLOT (animFinished()));
                                              anim->start();
                                           }
                                          
                                          void graphicsView::scalingTime(qreal x)
                                          {
                                              QPointF oldPos = mapToScene(wheelEventMousePos);
                                          
                                              qreal factor = 1.0+ qreal(_numScheduledScalings) / 300.0;
                                              scale(factor, factor);
                                          
                                              QPointF newPos = mapToScene(wheelEventMousePos);
                                              QPointF delta = newPos - oldPos;
                                              this->translate(delta.x(), delta.y());
                                          }
                                          
                                          void graphicsView::animFinished()
                                          {
                                              if (_numScheduledScalings > 0)
                                                  _numScheduledScalings--;
                                              else
                                                  _numScheduledScalings++;
                                          
                                              sender()->~QObject();
                                          }
                                          
                                          
                                            Михаиллл
                                            • June 10, 2019, 9:07 a.m.

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

                                              Михаиллл
                                              • June 10, 2019, 9:29 a.m.

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

                                              #include "paintscene.h"
                                              
                                              
                                              paintScene::paintScene(QObject *parent) : QGraphicsScene(parent)
                                              {
                                                  //myQGraphicsScene = new QGraphicsView();
                                                  //scene = new paintScene();       // Инициализируем графическую сцену
                                              }
                                              
                                              paintScene::~paintScene()
                                              {
                                              
                                              }
                                              
                                              void paintScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
                                              {
                                                  // При нажатии кнопки мыши отрисовываем эллипс
                                                  addEllipse(event->scenePos().x() - 5,
                                                             event->scenePos().y() - 5,
                                                             10,
                                                             10,
                                                             QPen(Qt::NoPen),
                                                             QBrush(Qt::red));
                                                  // Сохраняем координаты точки нажатия
                                                  previousPoint = event->scenePos();
                                                  buttonIsPressed = true;
                                              }
                                              
                                              void paintScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
                                              {
                                                  if (buttonIsPressed)
                                                  {
                                                      // Отрисовываем линии с использованием предыдущей координаты
                                                      addLine(previousPoint.x(),
                                                              previousPoint.y(),
                                                              event->scenePos().x(),
                                                              event->scenePos().y(),
                                                              QPen(Qt::red,10,Qt::SolidLine,Qt::RoundCap));
                                                      // Обновляем данные о предыдущей координате
                                                      previousPoint = event->scenePos();
                                                  }
                                              }
                                              
                                              void paintScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
                                              {
                                                  buttonIsPressed = false;
                                              }
                                              

                                                Comments

                                                Only authorized users can post comments.
                                                Please, Log in or Sign up
                                                e
                                                • ehot
                                                • March 31, 2024, 2:29 p.m.

                                                C++ - Тест 003. Условия и циклы

                                                • Result:78points,
                                                • Rating points2
                                                B

                                                C++ - Test 002. Constants

                                                • Result:16points,
                                                • Rating points-10
                                                B

                                                C++ - Test 001. The first program and data types

                                                • Result:46points,
                                                • Rating points-6
                                                Last comments
                                                k
                                                kmssrFeb. 8, 2024, 6:43 p.m.
                                                Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                                Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                                EVA
                                                EVADec. 25, 2023, 10:30 a.m.
                                                Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                                                J
                                                JonnyJoDec. 25, 2023, 8:38 a.m.
                                                Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                                                G
                                                GvozdikDec. 18, 2023, 9:01 p.m.
                                                Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                                                Now discuss on the forum
                                                a
                                                a_vlasovApril 14, 2024, 6:41 a.m.
                                                Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                                                Павел Дорофеев
                                                Павел ДорофеевApril 14, 2024, 2:35 a.m.
                                                QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
                                                f
                                                fastrexApril 4, 2024, 4:47 a.m.
                                                Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
                                                AC
                                                Alexandru CodreanuJan. 19, 2024, 11:57 a.m.
                                                QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…

                                                Follow us in social networks