gpt4 book ai didi

c++ - 如何用 QStringList 填充 ListView ?

转载 作者:行者123 更新时间:2023-11-30 02:21:18 26 4
gpt4 key购买 nike

我正在开发一个应用程序,用于查找 sdcard 中的所有 mp4 视频并将它们列在 ListView 中。制作一个按钮来播放列表中的所有视频,或者单击视频列表中的一个可以播放该视频。

我不知道如何实现 C++ 中的 QStringlist 和 QML 中的 folderModel 之间的链接。也许它应该使用另一种方式来使用 QStringlist 填充 ListView 。我已经在 C++ 端实现了 mp4 文件的搜索部分,但不知道如何使用存储 mp4 视频文件路径的 QStringlist 填充 ListView 。请帮忙。

源代码:

文件模型.cpp

#ifndef FILEMODEL_H
#define FILEMODEL_H

#include <QObject>
#include <QStringList>
#include <QDirIterator>
#include <QString>

class MyObject : public QObject{
Q_OBJECT
public:
explicit MyObject (QObject* parent = 0) : QObject(parent) {}
Q_INVOKABLE QStringList findfile();
};


QStringList MyObject::findfile( ) {
QStringList all_dirs;
QDirIterator it(dir, QStringList() << "*.mp4", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()){
all_dirs << it.next();
}
}

#endif // FILEMODEL_H

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);

QQmlApplicationEngine engine;
MyObject obj;
engine.rootCtontext()->setContextProperty("MyObject", &obj);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;

return app.exec();
}

ma​​in.qml

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.1
import Qt.labs.folderlistmodel 2.1
import QtMultimedia 5.0
import QtQuick.Controls.Styles 1.4
import Qt.labs.platform 1.0

ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")

SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex

Page1 {
ListView {
width: 200; height: 400

FolderListModel {
id: folderModel
nameFilters: ["*.mp4"]
}

Component {
id: fileDelegate
Text { text: fileName }
}

model: folderModel
delegate: fileDelegate
}

Button {
id: button

width: parent.width
text: "Play"
background: Rectangle {
implicitHeight: 40
border.color: "#26282a"
border.width: 2
radius: 4
}
onClicked:
{
player.source = folderModel.get (0, "fileURL")
playTimer.start()
player.play()
swipeView.setCurrentIndex(1)
}
}
}

Page {
MediaPlayer {
id: player
}

VideoOutput {
id: video
anchors.fill: parent
source: player
}
}
}

function setImageIndex(i)
{
index = i;
if (index >= 0 && index < folderModel.count){
player.source = folderModel.get (index, "fileURL");
player.play();
}
else{
player.source = folderModel.get (index, "fileURL");
player.play();
}
}

Timer {
id: playTimer
interval: 2000
repeat: true
running: true
onTriggered: {
var source_name = player.source;

if(source_name.toString().indexOf(".mp4")>0){ //processing .mp4
if (player.status == MediaPlayer.EndOfMedia){
if (index + 1 < folderModel.count){
setImageIndex(index + 1);
}
else{
index = 0;
setImageIndex(index);
}
}
}
}
}

footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
TabButton {
text: qsTr("First")
}
TabButton {
text: qsTr("Second")
}
}
}

最佳答案

如果你想用 C++ 制作你自己的过滤器,你不应该使用 FolderListModel,有几种可能性。

  1. 其中之一是为它实现自己的模型,我们创建一个继承自 QAbstractListModel 的类:

#ifndef FILEMODEL_H
#define FILEMODEL_H

#include <QAbstractListModel>
#include <QDirIterator>
#include <QUrl>
#include <QMetaType>
#include <QFuture>
#include <QtConcurrent>

struct File
{
Q_GADGET
Q_PROPERTY(QString name MEMBER name)
Q_PROPERTY(QUrl url MEMBER url)
public:
QString name;
QUrl url;
File(const QString& name=""){
this->name = QFileInfo(name).fileName();
this->url = QUrl::fromLocalFile(name);
}
};
Q_DECLARE_METATYPE(File)

class FileModel : public QAbstractListModel
{
enum dashBoardRoles {
NameRole=Qt::UserRole+1,
URLRole
};
Q_OBJECT
Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged)
Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged)
public:
FileModel(QObject *parent=Q_NULLPTR):QAbstractListModel(parent){
}

Q_INVOKABLE QVariant get(int index){
return QVariant::fromValue(m_all_dirs[index]);
}

int rowCount(const QModelIndex &parent=QModelIndex()) const{
Q_UNUSED(parent)
return m_all_dirs.count();
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const{
if(index.row()<0 && index.row()>= rowCount())
return QVariant();
File file = m_all_dirs[index.row()];
if(role == NameRole)
return file.name;
else if(role == URLRole)
return file.url;
return QVariant();
}

QHash<int, QByteArray> roleNames() const {
QHash <int,QByteArray> roles;
roles [NameRole]="fileName";
roles [URLRole]="url";
return roles;
}

QString folder() const{
return mFolder;
}

void setFolder(const QString &folder)
{
if(mFolder == folder)
return;
mFolder = folder;
emit folderChanged();
findFiles();
}

QStringList nameFilters() const{
return mNameFilters;
}

void setNameFilters(const QStringList &nameFilters){
if(mNameFilters == nameFilters)
return;
mNameFilters = nameFilters;
emit nameFiltersChanged();
findFiles();
}

signals:
void folderChanged();
void nameFiltersChanged();

private:
void findFiles(){

beginResetModel();
m_all_dirs.clear();
if(QDir(mFolder).exists()){
QFuture<QStringList> future = QtConcurrent::run([=]() {
QStringList files;
QDirIterator it(mFolder, mNameFilters, QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()){
files<<it.next();
}
return files;
});
QStringList fullNames = future.result();
for(const QString& fullName: fullNames){
File file{fullName};
m_all_dirs << file;
}
}
endResetModel();
}
QString mFolder;
QList<File> m_all_dirs;
QStringList mNameFilters;
};

#endif // FILEMODEL_H

然后在.qml中注册使用

main.cpp

qmlRegisterType<FileModel>("com.eyllanesc.filemodel", 1,0, "FileModel");

ma​​in.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtMultimedia 5.8

import com.eyllanesc.filemodel 1.0

ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Tabs")

SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex

Page {

ListView {
id: lv
width: 200; height: 400

Component {
id: fileDelegate
Text { text: fileName
MouseArea{
anchors.fill: parent
onClicked: playMusic(index)
}
}
}

model: FileModel{
id: myModel
folder: "/home/eyllanesc"
nameFilters: ["*.mp4"]
}

delegate: fileDelegate
}

Button {
id: button
anchors.top: lv.bottom
width: parent.width
text: "Play"
background: Rectangle {
implicitHeight: 40
border.color: "#26282a"
border.width: 2
radius: 4
}
onClicked: playMusic(0)
}
}

Page {
MediaPlayer {
id: player
onStopped: {
if(status===MediaPlayer.EndOfMedia){
playMusic((lv.currentIndex+1) % lv.count)
}
}
}

VideoOutput {
id: video
anchors.fill: parent
source: player
}
}
}

function playMusic(index){
player.stop()
player.source = myModel.get(index).url
player.play()
swipeView.setCurrentIndex(1)
}

footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex

TabButton {
text: qsTr("Page 1")
}
TabButton {
text: qsTr("Page 2")
}
}
}
  1. 另一种解决方案是使用 QQmlListProperty 并公开这些属性:

#ifndef FILEMANAGER_H
#define FILEMANAGER_H

#include <QDirIterator>
#include <QFileInfo>
#include <QFuture>
#include <QObject>
#include <QQmlListProperty>
#include <QUrl>
#include <QVector>
#include <QtConcurrent>

class File: public QObject{
Q_OBJECT
Q_PROPERTY(QString fileName READ fileName CONSTANT)
Q_PROPERTY(QUrl url READ url CONSTANT)
public:
File(const QString fullPath="", QObject *parent = nullptr):QObject(parent){
mFullPath = fullPath;
}
QString fileName() const
{
return QFileInfo(mFullPath).fileName();
}
QUrl url() const{
return QUrl::fromLocalFile(mFullPath);
}

private:
QString mFullPath;
};

class FileManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<File> files READ files NOTIFY filesChanged)
Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged)
Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged)
public:
explicit FileManager(QObject *parent = nullptr):QObject(parent){}
QQmlListProperty<File> files(){
return QQmlListProperty<File>(this, this,
&FileManager::filesCount,
&FileManager::file);
}

QString folder() const
{
return mFolder;
}

void setFolder(const QString &folder)
{
if(mFolder == folder)
return;
mFolder = folder;
emit folderChanged();
findFiles();
}

int filesCount() const{
return mFiles.count();
}

File *file(int index) const{
return mFiles.at(index);
}
QStringList nameFilters() const{
return mNameFilters;
}

void setNameFilters(const QStringList &nameFilters){
if(mNameFilters == nameFilters)
return;
mNameFilters = nameFilters;
emit nameFiltersChanged();
findFiles();
}

signals:
void folderChanged();
void filesChanged();
void nameFiltersChanged();
private:

void findFiles( ) {
mFiles.clear();
if(QDir(mFolder).exists()){
QFuture<QStringList> future = QtConcurrent::run([=]() {
QStringList files;
QDirIterator it(mFolder, mNameFilters, QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()){
files<<it.next();
}
return files;
});

for(const QString& fullName: future.result()){
File* file = new File(fullName);
mFiles << file;
}
}
emit filesChanged();
}

static int filesCount(QQmlListProperty<File>* list){
return reinterpret_cast<FileManager* >(list->data)->filesCount();
}
static File* file(QQmlListProperty<File>* list, int index){
return reinterpret_cast<FileManager* >(list->data)->file(index);
}
QVector<File *> mFiles;
QString mFolder;
QStringList mNameFilters;
};

#endif // FILEMANAGER_H

然后在.qml中注册使用

main.cpp

qmlRegisterType<FileManager>("com.eyllanesc.filemanager", 1,0, "FileManager");

ma​​in.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtMultimedia 5.8

import com.eyllanesc.filemanager 1.0

ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Tabs")

FileManager{
id: manager
folder: "/home/eyllanesc"
nameFilters: ["*.mp4"]
}

SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex

Page {

ListView {
id: lv
width: 200; height: 400

Component {
id: fileDelegate
Text { text: fileName
MouseArea{
anchors.fill: parent
onClicked: playMusic(index)
}
}
}

model: manager.files
delegate: fileDelegate
}

Button {
id: button
anchors.top: lv.bottom
width: parent.width
text: "Play"
background: Rectangle {
implicitHeight: 40
border.color: "#26282a"
border.width: 2
radius: 4
}
onClicked: playMusic(0)
}
}

Page {
MediaPlayer {
id: player
onStopped: {
if(status===MediaPlayer.EndOfMedia){
playMusic((lv.currentIndex+1) % lv.count)
}
}
}

VideoOutput {
id: video
anchors.fill: parent
source: player
}
}
}

function playMusic(index){
player.stop()
player.source = manager.files[index].url
player.play()
swipeView.setCurrentIndex(1)
}

footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex

TabButton {
text: qsTr("Page 1")
}
TabButton {
text: qsTr("Page 2")
}
}
}

两个例子都可以在下面的链接中找到

关于c++ - 如何用 QStringList 填充 ListView ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48534529/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com