Михаиллл
Михаиллл8 июня 2019 г. 13:21

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

QLabel

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

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

23
Михаиллл
  • 9 июня 2019 г. 4:01

Рисовать можно так. Но как определить положение мышки и при нажатии рисовать, как в 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();
}
    Михаиллл
    • 9 июня 2019 г. 8:23

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

      Михаиллл
      • 9 июня 2019 г. 10:54

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

        Михаиллл
        • 9 июня 2019 г. 11:10
        • Ответ был помечен как решение.

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

          Evgenii Legotckoi
          • 10 июня 2019 г. 3:49

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

            Михаиллл
            • 10 июня 2019 г. 4:13

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

            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
              • 10 июня 2019 г. 4:16

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

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

                Михаиллл
                • 10 июня 2019 г. 4:21
                • (ред.)

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

                QLabel *l1 = new QLabel("label1"); 
                scrollArea->setWidget(l1);
                
                  Evgenii Legotckoi
                  • 10 июня 2019 г. 4:24

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

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

                    Михаиллл
                    • 10 июня 2019 г. 4:41
                    • (ред.)

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

                        QGraphicsView *myQGraphicsScene = new QGraphicsView();
                        myQGraphicsScene->setScene(scene);
                    
                        scrollArea = new QScrollArea();  //QScrollArea
                        scrollArea->setWidget(myQGraphicsScene);
                    
                        ui->verticalLayout->addWidget(myQGraphicsScene);
                    
                      Evgenii Legotckoi
                      • 10 июня 2019 г. 4:52
                      • (ред.)

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

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

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

                        Михаиллл
                        • 10 июня 2019 г. 4:58

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

                          Evgenii Legotckoi
                          • 10 июня 2019 г. 5:00

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

                            Михаиллл
                            • 10 июня 2019 г. 5:29

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

                                mapImage.load("C:\\Users\\New Owner\\Downloads\\mapMain.png");
                                scene->addPixmap(QPixmap::fromImage(mapImage));//add image
                            
                              Михаиллл
                              • 10 июня 2019 г. 6:03
                              • (ред.)

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

                              QGraphicsScene* scene = new QGraphicsScene();
                              
                                Evgenii Legotckoi
                                • 10 июня 2019 г. 6:06

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

                                  Михаиллл
                                  • 10 июня 2019 г. 6:08

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

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

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

                                    Evgenii Legotckoi
                                    • 10 июня 2019 г. 6:10
                                    • (ред.)

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

                                      Михаиллл
                                      • 10 июня 2019 г. 6:32

                                      Эта строчку есть у вас в примере, наверно, лучшее ее удалить..
                                      Пробую перенести создание 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
                                      
                                        Михаиллл
                                        • 10 июня 2019 г. 7:11

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

                                        class graphicsView: public QGraphicsView
                                        {
                                        public:
                                            graphicsView();
                                            ~graphicsView() {};
                                            double scaleFactor;
                                            QGraphicsView * myGraphicsView;
                                        };
                                        
                                        graphicsView::graphicsView()
                                        {
                                            myGraphicsView = new QGraphicsView();
                                        }
                                        
                                        
                                          Михаиллл
                                          • 10 июня 2019 г. 8:23
                                          • (ред.)

                                          Написал класс с масштабированием.
                                          Но при масштабировании продолжается рисование (при использовании колесика, а если передаскивать мышкой картинку, то не рисует)(видимо по точке на виджите 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();
                                          }
                                          
                                          
                                            Михаиллл
                                            • 10 июня 2019 г. 9:07

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

                                              Михаиллл
                                              • 10 июня 2019 г. 9:29

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

                                              #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;
                                              }
                                              

                                                Комментарии

                                                Только авторизованные пользователи могут публиковать комментарии.
                                                Пожалуйста, авторизуйтесь или зарегистрируйтесь
                                                d
                                                • dsfs
                                                • 26 апреля 2024 г. 14:56

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

                                                • Результат:80баллов,
                                                • Очки рейтинга4
                                                d
                                                • dsfs
                                                • 26 апреля 2024 г. 14:45

                                                C++ - Тест 002. Константы

                                                • Результат:50баллов,
                                                • Очки рейтинга-4
                                                d
                                                • dsfs
                                                • 26 апреля 2024 г. 14:35

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

                                                • Результат:73баллов,
                                                • Очки рейтинга1
                                                Последние комментарии
                                                k
                                                kmssr9 февраля 2024 г. 5:43
                                                Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                                АК
                                                Анатолий Кононенко5 февраля 2024 г. 12:50
                                                Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                                EVA
                                                EVA25 декабря 2023 г. 21:30
                                                Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                                                J
                                                JonnyJo25 декабря 2023 г. 19:38
                                                Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                                                G
                                                Gvozdik19 декабря 2023 г. 8:01
                                                Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                                                Сейчас обсуждают на форуме
                                                G
                                                Gar22 апреля 2024 г. 15:46
                                                Clipboard Как скопировать окно целиком в clipb?
                                                DA
                                                Dr Gangil Academics20 апреля 2024 г. 17:45
                                                Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
                                                a
                                                a_vlasov14 апреля 2024 г. 16:41
                                                Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                                                Павел Дорофеев
                                                Павел Дорофеев14 апреля 2024 г. 12:35
                                                QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
                                                f
                                                fastrex4 апреля 2024 г. 14:47
                                                Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

                                                Следите за нами в социальных сетях