K
30 октября 2017 г. 19:46

открытие файла и его передача в PaintEvent

QPaintEvent, C++, QPainter, QImage

Доброго времени суток.

Появился вопрос. Не могу придумать, как его решить.

Есть некая папка. Мы из этой папки прекрасно можем считать файлы png.
И есть прекрасная функция PaintEvent, которая перерисовывает всё, что в неё не сунь.

#include <QMainWindow>
#include <QPicture>
#include <QImage>
#include <QPainter>
#include <QFileDevice>
#include <QFileDialog>
#include <QWidgets>


MainWindow::MainWindow(QWidget *parent):QWidget(parent)
{
       setPalette(QPaette(QT::white));
       setWindowTitle("Image")
}

void MainWindow::paintEvent(QPaintEvent *)
{
    QString fileName  = QFileDialog::getOpenFileName(this, tr("Open file"), QDir::currentPath());
    QImage img(fileName); 

    QPainter painter(this);
    painter.drawImage(0,0, img.scaled(this->size())); 
}
Вопрос заключается в том, что как сначала считать картинку,  а потом отправить её в paintEvent??? Пробовал подавать в paintEvent дополнительные параметры, но ничего не происходило.

2

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

8
Evgenii Legotckoi
  • 31 октября 2017 г. 0:05

Картинку можно считать ещё в конструкторе класса и сохранить изображение в локальную переменную, которая будет объявлена в заголовочном файле, в объявлении класса MainWindow.

#include <QMainWindow>
#include <QPicture>
#include <QImage>
#include <QPainter>
#include <QFileDevice>
#include <QFileDialog>
#include <QWidgets>


MainWindow::MainWindow(QWidget *parent):QWidget(parent)
{
       setPalette(QPaette(QT::white));
       setWindowTitle("Image")
       QString fileName  = QFileDialog::getOpenFileName(this, tr("Open file"), QDir::currentPath());
       m_img = QImage(fileName); 
}

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawImage(0,0, m_img.scaled(this->size())); 
}
В объявлении класса MainWindow добавить этот самый объект QImage
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QImage m_img;
};

#endif // MAINWINDOW_H
    Evgenii Legotckoi
    • 31 октября 2017 г. 0:34

    Забыл добавить. Перерисовка через paintEvent() метод вызывается с помощью метода update() , вызов метода update() инициирует перерисовку через стек вызовов событий в виджете.

      K
      • 15 ноября 2017 г. 16:54

      Спасибо за прошлый ответ. Но вот сейчас хотел бы задать уточняющий вопрос. А как это сделать не вызывая файл в конструкторе.
      На самом деле делаю просмотр изображений

      mainwindow.cpp
      #include "MainWindow.h"
      #include <QMessageBox>
      
      MainWindow::MainWindow(QWidget *parent)
      	: QMainWindow(parent), ui(new Ui::MainWindowClass)
      
      {
      	ui->setupUi(this);
      	
      
      	setWindowTitle(tr("Viewer"));
      
      	connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(close()));
      	connect(ui->actionAbout_app, SIGNAL(triggered()), this, SLOT(about_app()));
      	connect(ui->actionAbout_qt, SIGNAL(triggered()), this, SLOT(about_qt()));
      	connect(ui->actionOpen_file, SIGNAL(triggered()), this, SLOT(open()));
      	
      	connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), ui->m_imagevw, SLOT(horScroll(int)));
      
      }
      
      void MainWindow::open()
      {
      	ui->m_imagevw->imageview::openFile();
      }
      
      void MainWindow::about_app()
      {
      	QMessageBox::about(this, tr("About "), tr("<b>B</b>."));
      }
      void MainWindow::about_qt()
      {
      	QMessageBox::aboutQt(this, QStringLiteral("About QT"));
      }
      mainwindow.h
      #pragma once
      #include <QtWidgets/QMainWindow>
      #include "imageview.h"
      #include "ui_MainWindow.h"
      #include <QtWidgets/QWidget>
      #include <QFileDevice>
      #include <QTemporaryFile>
      #include <QFileDialog>
      
      namespace Ui
      {
      	class MainWindowClass;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = Q_NULLPTR);
      	QString m_fileIn;
      
      private slots:
      	void open();
      	void about_app();
      	void about_qt();
      private:
          Ui::MainWindowClass *ui;
      	imageview *my_imageview;
      
      };
      А вот дальше imageview.cpp
      #include "imageview.h"
      
      imageview::imageview(QWidget *parent)
      	: QWidget(parent)
      {
      	ui.setupUi(this);
      	setPalette(QPalette(Qt::white));
      	setWindowTitle("Image");
      	openFile();
      }
      
      void imageview::openFile()
      {
      	m_fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath());
      	  m_img = QImage(m_fileName); 
      	m_img = img;
      	update();
      }
      
      
      
      void imageview::paintEvent(QPaintEvent *event)
      {
      		QPainter painter(this);
      		painter.drawImage(0, 0, m_img.scaled(this->size()));
      }
      И к нему .h
      #pragma once
      
      #include <QWidget>
      #include <QtGui>
      #include <QFileDevice>
      #include <QTemporaryFile>
      #include <QPushButton.h>
      #include <QFileDialog>
      #include <iostream>
      #include <QImage>
      #include "ui_imageview.h"
      namespace Ui
      {
      	class imageview;
      }
      
      class imageview : public QWidget
      {
      	Q_OBJECT
      
      public:
      	imageview(QWidget *parent = Q_NULLPTR);
      	void openFile();
      
      
      protected:
      	void paintEvent(QPaintEvent *event);
      
      private:
      	Ui::imageview ui;
      	QString m_fileName;
      	QImage m_img;
      };

      Но картинка никак не обновляется. Совсем. Или происходит утечка памяти.
      Как лучше вызвать изображение?
        Evgenii Legotckoi
        • 15 ноября 2017 г. 17:08

        Скорее всего проблема вот в этом месте.

        void MainWindow::open()
        {
        	ui->m_imagevw->imageview::openFile();
        }
        Зачем Вы так написали?
        Нужно так писать
        void MainWindow::open()
        {
        	ui->m_imagevw->openFile();
        }
        И вот этот объект вообще непонятно для чего написан... нигде не используется.
        imageview *my_imageview;
          K
          • 15 ноября 2017 г. 20:15
          • (ред.)

          Нет, не работает зависает в

          void imageview::paintEvent(QPaintEvent *event)
          {
          		QPainter painter(this);
          		painter.drawImage(0, 0, m_img.scaled(this->size()));
          }
          и просто из него не выходит

          после  выбора  картинки 
          Unhandled exception at 0x00007FFE48AFE793 (Qt5Guid.dll) in test_gui_app_2.exe: 0xC0000005: Access violation reading location 0x0000019128820000.

          а про не использованные элементы - забыл удалить, перед тем, как выкладывал код.
          Сейчас пробую как раз на примере, что выложил. Он чист от всякой всячины уже.
            Evgenii Legotckoi
            • 15 ноября 2017 г. 20:33

            Понятия не имею, почему у вас это не работает. Возможно ещё из-за вот этой непонятной строчки, которая по логике там быть не должна.

            void imageview::openFile()
            {
            	m_fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath());
            	  m_img = QImage(m_fileName); 
            	m_img = img; // Это очевидно не может быть здесь
            	update();
            }
            А так я приложил рабочий пример. Посмотрите и сравните с вашим кодом
              K
              • 15 ноября 2017 г. 21:00
              • (ред.)

              Хорошо, тогда прошу пояснить мне вот что.  В вашем примере. Как его изменить так, чтобы создавать  изображение не из конструктора а из своей функции. А потом кидать картинку в paintE...
              В отладчике - выбрал файл - он создал картику - возникает ошибка

                Evgenii Legotckoi
                • 15 ноября 2017 г. 21:09

                Пример-то посмотрите как следует. Там нет создания картинки в конструкторе. Вы путаете объявление класса с конструктором класса. А иначе как через локальную переменную вы перекинуть изображение или путь к нему не сможете. Метод paintEvent() вызывается в рамках стеках событий приложения Qt, а значит добавить дополнительные аргументы у вас не получится к этому методу, только перегрузка.

                  Комментарии

                  Только авторизованные пользователи могут публиковать комментарии.
                  Пожалуйста, авторизуйтесь или зарегистрируйтесь
                  • Последние комментарии
                  • Evgenii Legotckoi
                    16 апреля 2025 г. 17:08
                    Благодарю за отзыв. И вам желаю всяческих успехов!
                  • IscanderChe
                    12 апреля 2025 г. 17:12
                    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
                  • AK
                    1 апреля 2025 г. 11:41
                    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
                  • Evgenii Legotckoi
                    9 марта 2025 г. 21:02
                    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
                  • VP
                    9 марта 2025 г. 16:14
                    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…