Михаиллл
МихаилллМаусым 8, 2019, 1: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 Т.Ж.

                          Скролл появляется лишь в том случае, елси картинка не вмещается в область. Если вы считаете, что она у вас вмещается, то скорее всего у вас другая проблема, может быть в вёрстке или ещё где-то в другом месте, но точно не в скролле 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;
                                              }
                                              

                                                Пікірлер

                                                Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                                                Кіріңіз немесе Тіркеліңіз
                                                m
                                                • molni99
                                                • Қаз. 26, 2024, 1:37 Т.Ж.

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

                                                • Нәтиже:80ұпай,
                                                • Бағалау ұпайлары4
                                                m
                                                • molni99
                                                • Қаз. 26, 2024, 1:29 Т.Ж.

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

                                                • Нәтиже:20ұпай,
                                                • Бағалау ұпайлары-10

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

                                                • Нәтиже:42ұпай,
                                                • Бағалау ұпайлары-8
                                                Соңғы пікірлер
                                                i
                                                innorwallҚар. 10, 2024, 1:03 Т.Қ.
                                                Джанго - Сабақ 029. Сайтқа жеке хабарламалар мен чаттар қосу - 1 бөлім priligy at walgreens ortho ciprofloxacin tablet uses in telugu Republicans in Congress have chastised Obama s top health adviser, Health and Human Services Secretary Kathleen Sebelius, …
                                                i
                                                innorwallҚар. 10, 2024, 9:55 Т.Ж.
                                                Linux жүйесінде файлдарды қалай көшіруге болады In dogs, it is used to facilitate synchronized cardioversion of atrial fibrillation buy priligy usa
                                                i
                                                innorwallҚар. 10, 2024, 9:03 Т.Ж.
                                                Qt тілінде ойын қалай жазылады - 3-сабақ. Басқа объектілермен әрекеттесу priligy otc I routinely do not tell patients and or parents of patients with atopic dermatitis to avoid glutamates in food
                                                i
                                                innorwallҚар. 10, 2024, 4:31 Т.Ж.
                                                QMYSQL драйверін құру (MariaDB) Windows 10 x64 QT 5.13.0 Mingw73_64 amazon priligy Conclusion This is the first study of the adverse effects of quetiapine ingestion by children under 7 years of age
                                                Енді форумда талқылаңыз
                                                i
                                                innorwallҚар. 10, 2024, 8:22 Т.Ж.
                                                добавить qlineseries в функции The information provided in Dosage Posology and method of administration of Tamoxifen Actavis is based on data of another medicine with exactly the same composition as the Tamoxifen Actavis …
                                                9
                                                9AnonimҚаз. 25, 2024, 9:10 Т.Ж.
                                                Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
                                                F
                                                FynjyШілде 22, 2024, 4:15 Т.Ж.
                                                при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

                                                Бізді әлеуметтік желілерде бақылаңыз