Evgenii Legotckoi
Evgenii LegotckoiMarch 30, 2017, 1:47 p.m.

Qt/C++ - Lesson 061. Adding images to the application using the Drag And Drop method from the file manager

Let's write a small application that will allow Drag and Drop to drag and drop images from the file manager into the application itself. In this application, there will be an image preview area and a list of all the images that we put into our application. In this case, when clicking on the image in the list, the image will be placed in the main view area, by which we clicked. In this list, each element will have a preview of the image without text. This preview will be generated using a delegate inherited from QStyledDelegate .

The application will look like this:


Project structure

  • DropEvent.pro - project profile;
  • main.cpp - File with the main function;
  • widget.h - The header file for the application window;
  • widget.cpp - The application source code file;
  • imagedelegate.h - Header file of the list item delegate;
  • Imagedelegate.cpp - File of the source code of the delegate of the list item.

A delegate in this project is required in order to delete the text under the images. The fact is that for displaying thumbnails of images, QListView and QStandardItemModel will be used, which do not have the functionality of displaying icons without text. But you can remove the text using the delegate, completely redefining the appearance of the list item.

I will not bring the source code for the DropEvent.pro and main.cpp files, because there is the default code generated when creating the project.

widget.h

In the window of the application window, we redefine the methods for the Drag and Drop events, and also add objects for the interface and the data model for the images.

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPalette>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QDropEvent>
#include <QScrollArea>
#include <QLabel>
#include <QListView>
#include <QGridLayout>
#include <QStandardItemModel>

class Widget : public QWidget
{
    Q_OBJECT

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

    // Drag event method
    virtual void dragEnterEvent(QDragEnterEvent* event) override;
    // Method for drop an object with data
    virtual void dropEvent(QDropEvent *event) override;

private slots:
    // Slot for processing clicks on list items
    void onImagesListViewClicked(const QModelIndex& index);

private:
    QScrollArea*        m_scrollArea;       // Image scrolling area
    QLabel*             m_imageLabel;       // Label for displaying pictures
    QListView*          m_imagesListView;   // List with images
    QGridLayout*        m_gridLayout;       // Grid for the interface
    QStandardItemModel* m_imagesModel;      // Data Model with Images
};

#endif // WIDGET_H

widget.cpp

To form a list with images, QStandardItemModel will be used, and QListView will be used to display the model elements. For customized display of items in the list, the Delegate will be used, because only redefining the appearance display can remove the text. By the way, this text contains the path to the image file, which will be used to create a QPixmap and display the image both in the main view and in the previews. To get the path to the file from the data model, you need to use the data() method, and pass QModellndex and enum Qt::DisplayRole as the arguments, which is the default argument.

#include "widget.h"
#include "ui_widget.h"

#include <QStandardItem>
#include "imagedelegate.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    setAcceptDrops(true);       // Allow drop events for data objects
    setMinimumWidth(640);
    setMinimumHeight(480);

    /// Configure the interface
    m_gridLayout = new QGridLayout(this);
    m_imagesListView = new QListView(this);

    // Create a data model for the image list
    m_imagesModel = new QStandardItemModel(m_imagesListView);
    m_imagesListView->setModel(m_imagesModel);  // Install the model in the view for preview images
    m_imagesListView->setFixedWidth(200);

    // Without a delegate, you can not get rid of the text in the list item and set the display of the preview
    m_imagesListView->setItemDelegate(new ImageDelegate(m_imagesModel, m_imagesListView));

    // Adjust the scrolling area for the current image
    m_scrollArea = new QScrollArea(this);
    m_scrollArea->setBackgroundRole(QPalette::Dark);
    m_imageLabel = new QLabel(this);
    m_scrollArea->setWidget(m_imageLabel);
    m_gridLayout->addWidget(m_scrollArea, 0, 0);
    m_gridLayout->addWidget(m_imagesListView, 0, 1);

    connect(m_imagesListView, &QListView::clicked, this, &Widget::onImagesListViewClicked);
}

Widget::~Widget()
{

}

void Widget::dragEnterEvent(QDragEnterEvent *event)
{
    // You must necessarily accept the data transfer event in the application window area
    event->accept();
}

void Widget::dropEvent(QDropEvent *event)
{
    // When we drop the file into the application area, we take the path to the file from the MIME data
    QString filePath = event->mimeData()->urls()[0].toLocalFile();
    // Create an image
    QPixmap pixmap(filePath);
    // We place it in the scrolling area through QLabel
    m_imageLabel->setPixmap(pixmap);
    m_imageLabel->resize(pixmap.size());

    // Adding an item to the list
    m_imagesModel->appendRow(new QStandardItem(QIcon(pixmap), filePath));
}

void Widget::onImagesListViewClicked(const QModelIndex &index)
{
    // When we click on an element in the list, we take the path to the file
    QPixmap pixmap(m_imagesModel->data(index).toString());
    // And install the file in the main view area
    m_imageLabel->setPixmap(pixmap);
    m_imageLabel->resize(pixmap.size());
}

imagedelegate.h

And here is the delegate himself, whose task it is to display the item in the list. To get the path to the image file, I passed a pointer to the data model, and through QModelIndex in the paint method I get the path to the image.

Another important point is the use of the sizeHint() method. Which adjusts the size of the item in the list. If it does not make a size adjustment, then the element's size will be equal in height to the text line. The preview will look absolutely awful.

#ifndef IMAGEDELEGATE_H
#define IMAGEDELEGATE_H

#include <QStyledItemDelegate>
#include <QPainter>
#include <QStyleOptionViewItem>
#include <QModelIndex>
#include <QStandardItemModel>
#include <QPixmap>
#include <QDebug>

class ImageDelegate : public QStyledItemDelegate
{
public:
    explicit ImageDelegate(QStandardItemModel *model, QObject *parent = nullptr);

    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
    QStandardItemModel* m_model;
};


#endif // IMAGEDELEGATE_H

Imagedelegate.cpp

Another important point is the use of QRect from QStyleOptionViewItem. The fact is that it contains not only the height and width of the element, but also its position in x and y in the list. If you do not take into account these coordinates, you can see that all the elements will be drawn in one place. For example, in the upper left corner of the list, if you specify x = 0 and y = 0 when drawing.

#include "imagedelegate.h"

ImageDelegate::ImageDelegate(QStandardItemModel *model, QObject *parent) :
    QStyledItemDelegate(parent),
    m_model(model)
{

}

void ImageDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    // Instead of drawing icons and text, we will draw only one image with small indents of 5 pixels
    QPixmap pix(m_model->data(index).toString());
    QRect optionRect = option.rect;
    painter->drawPixmap(optionRect.x() + 5,
                        optionRect.y() + 5,
                        optionRect.width() - 10,
                        optionRect.height() - 10 ,
                        pix);
}

QSize ImageDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    // Correct the size of the display area of the object in the list
    QSize result = QStyledItemDelegate::sizeHint(option, index);
    result.setHeight(140);
    result.setWidth(140);
    return QSize(140, 140);
}

Project application with Drag and Drop

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!

Юрий
  • Jan. 20, 2021, 1:34 p.m.

// Вместо отрисовки иконки и текста будем отрисовывать только одно изображение
// с небольшими отступами в 5 пикселей
QPixmap pix(m_model->data(index).toString());

А можно сразу передовать Qpixmap?

Evgenii Legotckoi
  • July 2, 2021, 7:45 a.m.

Нет, нужно сконвертировать информацию в удобоваримый mime type

Ruslan Polupan
  • Aug. 11, 2022, 3:37 a.m.

Доброго времени суток.
А если нужно и изображение и текст?
Что-то потерялся немного....

// Вместо отрисовки иконки и текста будем отрисовывать только одно изображение
// с небольшими отступами в 5 пикселей
QPixmap pix(m_model->data(index).toString());

Evgenii Legotckoi
  • Aug. 24, 2022, 7:32 a.m.

Добрый день. Посмотрите описание методов drawText у QPainter, он позволит и текст нарисовать

Comments

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

C++ - Test 001. The first program and data types

  • Result:40points,
  • Rating points-8
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
Last comments
ИМ
Игорь МаксимовNov. 22, 2024, 7:51 p.m.
Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiOct. 31, 2024, 9:37 p.m.
Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEOct. 19, 2024, 3:19 p.m.
Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовOct. 5, 2024, 2:51 p.m.
Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5July 5, 2024, 6:02 p.m.
QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Now discuss on the forum
Evgenii Legotckoi
Evgenii LegotckoiJune 24, 2024, 10:11 p.m.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Nov. 15, 2024, 2:04 p.m.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectJune 4, 2022, 10:49 a.m.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimOct. 25, 2024, 4:10 p.m.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Follow us in social networks