Михаиллл
Михаиллл08 червня 2019 р. 13:21

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

QLabel

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

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

Вам це подобається? Поділіться в соціальних мережах!

23
Михаиллл
  • 09 червня 2019 р. 04: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();
}
    Михаиллл
    • 09 червня 2019 р. 08:23

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

      Михаиллл
      • 09 червня 2019 р. 10:54

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

        Михаиллл
        • 09 червня 2019 р. 11:10
        • Відповідь була позначена як рішення.

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

          Evgenii Legotckoi
          • 10 червня 2019 р. 03:49

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

            Михаиллл
            • 10 червня 2019 р. 04: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 р. 04:16

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

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

                Михаиллл
                • 10 червня 2019 р. 04:21
                • (відредаговано)

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

                QLabel *l1 = new QLabel("label1"); 
                scrollArea->setWidget(l1);
                
                  Evgenii Legotckoi
                  • 10 червня 2019 р. 04:24

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

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

                    Михаиллл
                    • 10 червня 2019 р. 04: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 р. 04:52
                      • (відредаговано)

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

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

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

                        Михаиллл
                        • 10 червня 2019 р. 04:58

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

                          Evgenii Legotckoi
                          • 10 червня 2019 р. 05:00

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

                            Михаиллл
                            • 10 червня 2019 р. 05:29

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

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

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

                              QGraphicsScene* scene = new QGraphicsScene();
                              
                                Evgenii Legotckoi
                                • 10 червня 2019 р. 06:06

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

                                  Михаиллл
                                  • 10 червня 2019 р. 06:08

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

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

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

                                    Evgenii Legotckoi
                                    • 10 червня 2019 р. 06:10
                                    • (відредаговано)

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

                                      Михаиллл
                                      • 10 червня 2019 р. 06: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 р. 07:11

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

                                        class graphicsView: public QGraphicsView
                                        {
                                        public:
                                            graphicsView();
                                            ~graphicsView() {};
                                            double scaleFactor;
                                            QGraphicsView * myGraphicsView;
                                        };
                                        
                                        graphicsView::graphicsView()
                                        {
                                            myGraphicsView = new QGraphicsView();
                                        }
                                        
                                        
                                          Михаиллл
                                          • 10 червня 2019 р. 08: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 р. 09:07

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

                                              Михаиллл
                                              • 10 червня 2019 р. 09: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;
                                              }
                                              

                                                Коментарі

                                                Only authorized users can post comments.
                                                Please, Log in or Sign up
                                                AD

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

                                                • Результат:50бали,
                                                • Рейтинг балів-4
                                                m
                                                • molni99
                                                • 26 жовтня 2024 р. 01:37

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

                                                • Результат:80бали,
                                                • Рейтинг балів4
                                                m
                                                • molni99
                                                • 26 жовтня 2024 р. 01:29

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

                                                • Результат:20бали,
                                                • Рейтинг балів-10
                                                Останні коментарі
                                                ИМ
                                                Игорь Максимов22 листопада 2024 р. 11:51
                                                Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                                Evgenii Legotckoi
                                                Evgenii Legotckoi31 жовтня 2024 р. 14:37
                                                Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                                A
                                                ALO1ZE19 жовтня 2024 р. 08:19
                                                Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                                ИМ
                                                Игорь Максимов05 жовтня 2024 р. 07:51
                                                Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                                d
                                                dblas505 липня 2024 р. 11:02
                                                QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                                Тепер обговоріть на форумі
                                                Evgenii Legotckoi
                                                Evgenii Legotckoi24 червня 2024 р. 15:11
                                                добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                                t
                                                tonypeachey115 листопада 2024 р. 06:04
                                                google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                                                NSProject
                                                NSProject04 червня 2022 р. 03:49
                                                Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                                                9
                                                9Anonim25 жовтня 2024 р. 09:10
                                                Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

                                                Слідкуйте за нами в соціальних мережах