Форум программистов, компьютерный форум, киберфорум
Dmitriy_M
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Используем Qt модели и QImage/QPixmap в QML, на примере FileBrowser

Запись от Dmitriy_M размещена 14.02.2013 в 22:44
Показов 14686 Комментарии 0

В прошлой записи рассмотрели использование своих C++ моделей в QML.
Сейчас же раcсмотрим использование Qt моделей на примере QFileSystemModel.

QFileSystemModel содержит следующие роли:
C++ (Qt)
1
2
3
4
QFileSystemModel::FileIconRole  Qt::DecorationRole
QFileSystemModel::FilePathRole  Qt::UserRole + 1
QFileSystemModel::FileNameRole  Qt::UserRole + 2
QFileSystemModel::FilePermissions   Qt::UserRole + 3
В принципе этого достаточно, для отображения имен файлов, но не достаточно, для обхода файловой системы.
QFileSystemModel содержит много полезных методов, но не содержит Q_INVOKABLE методов, позволяющих использовать их из QML, поэтому придется переопределить следующим способом:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class FileSystemModel: public QFileSystemModel
{
  Q_OBJECT
 
  Q_PROPERTY(QString rootPath READ rootPath WRITE setRootPath NOTIFY rootPathChanged)
public:
  FileSystemModel(QObject* parent = 0);
 
  /*!
   * @brief получить корень
   */
  QString rootPath()const;
 
  /*!
   * @brief установить корень
   */
  void setRootPath(const QString& path);
 
  /*!
   * @brief обертка над QFileSystemModel::index
   */
  Q_INVOKABLE QModelIndex indexFromPath(const QString & path, int column = 0) const;
 
  /*!
   * @brief получение имени файла
   */
  Q_INVOKABLE QString fileName(const QModelIndex & index) const;
 
  /*!
   * @brief получиение пути
   */
  Q_INVOKABLE QString filePath(const QModelIndex & index) const;
 
  /*!
   * @brief проверка на каталог
   */
  Q_INVOKABLE bool isDir(const QString& path) const;
 
  /*!
   * @brief получение родительского индекса
   */
  Q_INVOKABLE QModelIndex parentIndex(const QModelIndex& child) const;
 
signals:
  void rootPathChanged();
 
};
Реализация крайне проста:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
FileSystemModel::FileSystemModel(QObject* parent):
  QFileSystemModel(parent)
{
  setFilter(QDir::Files | QDir::AllDirs);
}
 
QString FileSystemModel::rootPath()const
{
  return QFileSystemModel::rootPath();
 
}
 
void FileSystemModel::setRootPath(const QString& path)
{
  QFileSystemModel::setRootPath(path);
  emit rootPathChanged();
}
 
QModelIndex FileSystemModel::indexFromPath(const QString & path, int column ) const
{
  return QFileSystemModel::index(path, column);
}
 
QString FileSystemModel::fileName(const QModelIndex & index) const
{
  return QFileSystemModel::fileName(index);
}
QString FileSystemModel::filePath(const QModelIndex & index) const
{
  return QFileSystemModel::filePath(index);
}
 
bool FileSystemModel::isDir(const QString& path) const
{
    return QFileSystemModel::isDir(index(path));
}
 
QModelIndex FileSystemModel::parentIndex(const QModelIndex& child) const
{
  return QFileSystemModel::parent(child);
}
Стоит отметить установку фильтра в конструкторе.
Далее следует обычная регистрация типа в QML:
C++ (Qt)
1
qmlRegisterType<FileSystemModel>(uri, 1, 0, "FileSystemModelBinding");
Большинство методов принимают QModelIndex в качестве параметра, а в том же ListModel используются целые индексы.
Тут и приходит на помощь VisualDataModel имеющий в себе свойство
JavaScript
1
rootIndex : QModelIndex
.
Инкапсулируем свою модель в VisualDataModel:
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import QtQuick 2.0
import QmlExtension 1.0
 
VisualDataModel{
    id: fsModel
 
    property alias rootPath:fsBinding.rootPath
 
    function cdUp(){
        rootIndex = fsBinding.parentIndex(fsModel.rootIndex);
    }
 
    function isDir(path){
        return fsBinding.isDir(path);
    }
 
    function cd(path){
        rootIndex=fsBinding.indexFromPath(path)
    }
 
    model:FileSystemModelBinding{
        id: fsBinding
 
        }
}
Сохраним это в FileSystemModel.qml
Вот простой пример использования:
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Rectangle {
    width: 500
    height: 500
    //color: "#4e4d4e"
 
    FileSystemModel{
        id:fsModel
        rootPath:"/"
        delegate:Item{
            height: view.cellHeight
            width: view.cellWidth
                Text{
                    anchors.horizontalCenter: icon.horizontalCenter
                    text:fileName
                    horizontalAlignment: Text.AlignHCenter
                    wrapMode:Text.WordWrap
                    width: parent.width
 
                    font.family: "Verdana"
                    //color: "white"
                }
        }
    }
 
    GridView{
        id:view
        width: parent.width
        height: parent.height
        anchors.fill: parent
        model: fsModel
        cellHeight : 128
        cellWidth : 128
    }
}
В Windows отобразится сетка с названием диска, в Unix сетка с содержимым корня.

Теперь хочется отображать иконки. И тут встает вопрос, как использовать QIcon или QImage/QPixmap в QML?
Для этих целей есть поставщик изображений QQuickImageProvider
Когда мы пишем такую схему:
JavaScript
1
Image { source: "image://MyImageProvider/image.png" }
То ищется поставщик зарегистрированный под именем MyImageProvider, в который передастся идентификатор
объекта, который требуется отобразит, в данном случае это image.png.

Описываем поставщика:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*!
 * @brief поставщик иконок
 */
class FileSystemIconProvider: public QQuickImageProvider
{
public:
  /*!
    \brief дефолтная длина
    */
  static const size_t DEFAULT_WIDTH  = 64;
 
  /*!
    \brief дефолтная высота
    */
  static const size_t DEFAULT_HEIGTH = 64;
 
  FileSystemIconProvider();
 
  virtual QPixmap requestPixmap(const QString & id, QSize * size, const QSize & requestedSize);
 
private:
  QFileIconProvider iconProvider_; //!< поставщик иконок fs
 
};
И реализация:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
FileSystemIconProvider::FileSystemIconProvider():
  QQuickImageProvider(QQmlImageProviderBase::Pixmap)
{
}
 
QPixmap FileSystemIconProvider::requestPixmap(const QString & id, QSize * size, const QSize & requestedSize)
{
  *size = QSize(DEFAULT_WIDTH, DEFAULT_HEIGTH);
 
  QIcon icon = iconProvider_.icon(id);
 
  return icon.pixmap( requestedSize.isValid() ? requestedSize :  *size);
}
Здесь id идентификатор ресурса, size истинный размер ресурса, requestedSize запрашиваемый размер из QML Image.
Добавляем поставщика в движек:
C++ (Qt)
1
2
3
4
void QMLExtensionPlugin::initializeEngine(QQmlEngine * engine, const char * uri)
{
  engine->addImageProvider("filesystem", new FileSystemIconProvider());
}
Теперь собираем все вместе:
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import QtQuick 2.0
 
Rectangle {
    width: 500
    height: 500
    //color: "#4e4d4e"
 
    FileSystemModel{
        id:fsModel
        rootPath:"/"
        delegate:Item{
            height: view.cellHeight
            width: view.cellWidth
 
            Column{
                anchors.centerIn: parent
                width: parent.width
 
 
                Image {
 
                    id: icon
                    source: "image://filesystem/"+filePath
                    smooth: true
                }
 
                Text{
                    anchors.horizontalCenter: icon.horizontalCenter
                    text:fileName
                    horizontalAlignment: Text.AlignHCenter
                    wrapMode:Text.WordWrap
                    width: parent.width
 
                    font.family: "Verdana"
                    //color: "white"
                }
 
            }
 
            MouseArea{
                anchors.fill: parent
                onDoubleClicked: {
                    fsModel.cd(filePath)
                }
            }
        }
 
 
    }
 
    GridView{
        id:view
        width: parent.width
        height: parent.height
        anchors.fill: parent
        model: fsModel
        cellHeight : 128
        cellWidth : 128
    }
}
Одна из особенности QFileIconProvider в Windows, он не может отдавать большие иконки Windows Vista.
Миниатюры
Нажмите на изображение для увеличения
Название: drivers.png
Просмотров: 766
Размер:	29.8 Кб
ID:	1730   Нажмите на изображение для увеличения
Название: folrers.png
Просмотров: 951
Размер:	41.1 Кб
ID:	1731  
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru