Evgenii Legotckoi
Evgenii Legotckoi30. März 2017 13:47

Qt/C++ - Lektion 061. Hinzufügen von Bildern zur Anwendung mithilfe der Drag-and-Drop-Methode aus dem Dateimanager

Lassen Sie uns eine kleine Anwendung schreiben, die es ermöglicht, die Drag and Drop -Methode zu verwenden, um Bilder aus dem Dateimanager in unsere Anwendung selbst zu ziehen und dort abzulegen. Damit verfügt die Anwendung über ein Bildansichtsfenster und eine Liste aller Bilder, die wir in unserer Anwendung platziert haben. Wenn Sie in diesem Fall auf ein Bild in der Liste klicken, wird das Bild, auf das wir geklickt haben, im Hauptanzeigebereich platziert. In dieser Liste wird für jedes Element ein Vorschaubild ohne Text generiert. Eine solche Vorschau wird mithilfe eines von QStyledDelegate. geerbten Delegaten generiert.

Die Anwendung wird wie folgt aussehen:


Projektstruktur

  • DropEvent.pro - Projektprofil;
  • main.cpp - Datei mit main-Funktion;
  • widget.h - Header-Datei des Anwendungsfensters;
  • widget.cpp - Quellcodedatei der Anwendung;
  • imagedelegate.h - Header-Datei des Listenelement-Delegaten;
  • Imagedelegate.cpp - Quellcodedatei des Listenelement-Delegaten.

Der Delegierte in diesem Projekt ist erforderlich, um den Text unter den Bildern zu entfernen. Der Punkt ist, dass QListView und QStandardItemModel verwendet werden, um Bildvorschauen anzuzeigen, die nicht die Funktionalität haben, Symbole ohne Text anzuzeigen. Es ist jedoch möglich, den Text mithilfe eines Delegaten zu entfernen, wodurch die Darstellung des Listenelements vollständig neu definiert wird.

Ich werde den Quellcode der Dateien DropEvent.pro und main.cpp nicht angeben, da beim Erstellen eines Projekts standardmäßig ein Programmcode erstellt wird.

Widget.h

In der Header-Datei des Anwendungsfensters werden wir die Methoden für die Ereignisse Drag und Drop überschreiben und auch Objekte hinzufügen, um die Schnittstelle und ein Datenmodell für Bilder zu bilden.

#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();

    // Метод события перетаскивания
    virtual void dragEnterEvent(QDragEnterEvent* event) override;
    // Метод события отпускания объекта с данными
    virtual void dropEvent(QDropEvent *event) override;

private slots:
    // Слот для обработки кликов по элементам списка
    void onImagesListViewClicked(const QModelIndex& index);

private:
    QScrollArea*        m_scrollArea;       // Область скроллинга изображения
    QLabel*             m_imageLabel;       // Лейбл для отображения картинок
    QListView*          m_imagesListView;   // Список с изображениями
    QGridLayout*        m_gridLayout;       // Сетка для интерфейса
    QStandardItemModel* m_imagesModel;      // Модель данных с изображениями
};

#endif // WIDGET_H

Widget.cpp

QStandardItemModel wird verwendet, um eine Liste mit Bildern zu erstellen, und QListView wird verwendet, um Modellelemente anzuzeigen. Für eine angepasste Anzeige von Elementen in der Liste wird der Delegate verwendet, da es nur durch Überschreiben der Anzeige des Erscheinungsbilds möglich ist, den Text zu entfernen. Dieser Text enthält übrigens den Pfad zur Bilddatei, die verwendet wird, um eine QPixmap zu erstellen und das Bild sowohl in der Hauptansicht als auch in Vorschauen anzuzeigen. Um den Dateipfad aus dem Datenmodell abzurufen, müssen Sie die Methode data(), verwenden und QModellndex und enum Qt::DisplayRole , das das Standardargument ist, als übergeben Argumente.

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

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

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    setAcceptDrops(true);       // разрешаем события отпускания объектов данных
    setMinimumWidth(640);
    setMinimumHeight(480);

    /// Настраиваем интерфейс
    m_gridLayout = new QGridLayout(this);
    m_imagesListView = new QListView(this);

    // Создадим модель данных для списка изображений
    m_imagesModel = new QStandardItemModel(m_imagesListView);
    m_imagesListView->setModel(m_imagesModel);  // Установим модель во вьюшку для превью изображений
    m_imagesListView->setFixedWidth(200);

    // Без делегата не удастся избавиться от текста в элементе списка и настроить отображение превью
    m_imagesListView->setItemDelegate(new ImageDelegate(m_imagesModel, m_imagesListView));

    // Настраиваем область скроллинга для текущего изображения
    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)
{
    // Обязательно необходимо допустить событие переноса данных в область окна приложения
    event->accept();
}

void Widget::dropEvent(QDropEvent *event)
{
    // Когда отпускаем файл в область приложения,
    // то забираем путь к файлу из MIME данных
    QString filePath = event->mimeData()->urls()[0].toLocalFile();
    // Создаём изображение
    QPixmap pixmap(filePath);
    // Помещаем его в область скроллинга через QLabel
    m_imageLabel->setPixmap(pixmap);
    m_imageLabel->resize(pixmap.size());

    // Добавляем элемент в список
    m_imagesModel->appendRow(new QStandardItem(QIcon(pixmap), filePath));
}

void Widget::onImagesListViewClicked(const QModelIndex &index)
{
    // Когда кликаем по элементу в списке, то забираем путь к файлу
    QPixmap pixmap(m_imagesModel->data(index).toString());
    // И устанавливаем файл в область основного просмотра
    m_imageLabel->setPixmap(pixmap);
    m_imageLabel->resize(pixmap.size());
}

imagedelegate.h

Und hier ist der Delegat selbst, dessen Aufgabe es ist, das Element in der Liste anzuzeigen. Um den Pfad zur Bilddatei zu erhalten, habe ich einen Zeiger auf das Datenmodell übergeben, und über QModelIndex in der Paint-Methode erhalte ich den Pfad zum Bild.

Ein weiterer wichtiger Punkt ist die Verwendung der Methode sizeHint(). , die die Größe des Elements in der Liste anpasst. Wenn Sie darin keine Größenanpassung vornehmen, entspricht die Größe des Elements der üblichen Textzeile. Die Vorschau wird absolut schrecklich aussehen.

#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

Ein weiterer wichtiger Punkt ist die Verwendung von QRect aus QStyleOptionViewItem. Fakt ist, dass es nicht nur die Höhe und Breite des Elements enthält, sondern auch seine x- und y-Position in der Liste. Wenn Sie diese Koordinaten nicht berücksichtigen, können Sie sehen, dass alle Elemente an einer Stelle gezeichnet werden. Zum Beispiel in der oberen linken Ecke der Liste, wenn Sie beim Zeichnen x = 0 und y = 0 setzen.

#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
{
    // Вместо отрисовки иконки и текста будем отрисовывать только одно изображение
    // с небольшими отступами в 5 пикселей
    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
{
    // Корректируем размеры области отображения объекта в списке
    QSize result = QStyledItemDelegate::sizeHint(option, index);
    result.setHeight(140);
    result.setWidth(140);
    return QSize(140, 140);
}

Bewerbungsentwurf per Drag and Drop

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

Юрий
  • 20. Januar 2021 13:34

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

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

Evgenii Legotckoi
  • 2. Juli 2021 07:45

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

Ruslan Polupan
  • 11. August 2022 03:37

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

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

Evgenii Legotckoi
  • 24. August 2022 07:32

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

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
A
ALO1ZE19. Oktober 2024 08:19
Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken