Михаиллл
Михаиллл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
                                                AD

                                                C ++ - Test 004. Pointers, Arrays and Loops

                                                • Result:50points,
                                                • Rating points-4
                                                m

                                                C ++ - Test 004. Pointers, Arrays and Loops

                                                • Result:80points,
                                                • Rating points4
                                                m

                                                C ++ - Test 004. Pointers, Arrays and Loops

                                                • Result:20points,
                                                • Rating points-10
                                                Last comments
                                                i
                                                innorwallNov. 15, 2024, 5:44 a.m.
                                                Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column? Many OPKs would advise users to start using the test strips around day 9 of your cycle, considering day 1 to be the first day of full menstrual flow buy priligy australia
                                                i
                                                innorwallNov. 15, 2024, 2:27 a.m.
                                                Release of C++/Qt and QML application deployment utility CQtDeployer v1.4.0 (Binary Box) optionally substituted alkoxy, optionally substituted alkenyloxy, optionally substituted alkynyloxy, optionally substituted aryloxy, OCH, OC H, OC H, OC H, OC H, OC H, OC H, O C CH, OCH CH OH, O…
                                                i
                                                innorwallNov. 14, 2024, 9:26 p.m.
                                                Qt/C++ - Lesson 031. QCustomPlot – The build of charts with time buy generic priligy We can just chat, and we will not lose too much time anyway
                                                i
                                                innorwallNov. 14, 2024, 7:03 p.m.
                                                Qt/C++ - Lesson 060. Configuring the appearance of the application in runtime I didnt have an issue work colors priligy dapoxetine 60mg revia cost uk August 3, 2022 Reply
                                                i
                                                innorwallNov. 14, 2024, 12:07 p.m.
                                                Circuit switching and packet data transmission networks Angioedema 1 priligy dapoxetine
                                                Now discuss on the forum
                                                i
                                                innorwallNov. 15, 2024, 5:50 a.m.
                                                добавить qlineseries в функции priligy for sale Gently flush using an ear syringe
                                                i
                                                innorwallNov. 11, 2024, 10:55 a.m.
                                                Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
                                                9
                                                9AnonimOct. 25, 2024, 9:10 a.m.
                                                Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

                                                Follow us in social networks