问题描述
对于一个需要在QListView中整合大量数据的项目,我从QThread获取数据并将其存储在QMap
example.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QListView>
#include <QStandardItemmodel>
#include <QDebug>
#include <QThread>
#include "mythread.h"
class exemple : public QMainWindow
{
Q_OBJECT
public:
explicit exemple(QWidget *parent = nullptr);
private:
QPushButton *btn_start;
QListView *lv_file;
QMap<QString,QString> myMap;
MyThread *m_thread;
QStandardItemmodel *model;
public slots:
void addFileinformation(QString,QString);
void startShow();
private slots:
void startThread();
};
#endif // MAINWINDOW_H
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QDebug>
#include <QDirIterator>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent);
void run();
signals:
void addFileinformation(QString,QString);
void startShow();
};
#endif // MYTHREAD_H
示例.cpp
#include "exemple.h"
exemple::exemple(QWidget *parent) : QMainWindow(parent)
{
setFixedSize(750,750);
btn_start = new QPushButton("start",this);
btn_start->setGeometry(50,40,150,30);
btn_start->setCursor(Qt::PointingHandCursor);
lv_file = new QListView(this);
lv_file->setGeometry(50,100,600,500);
m_thread = new MyThread(this);
model = new QStandardItemmodel(this);
lv_file->setModel(model);
connect(btn_start,SIGNAL(clicked()),this,SLOT(startThread()));
connect(m_thread,SIGNAL(addFileinformation(QString,QString)),SLOT(addFileinformation(QString,QString)));
connect(m_thread,SIGNAL(startShow()),SLOT(startShow()));
}
void exemple::startThread(){
m_thread->start();
}
void exemple::addFileinformation(QString param1,QString param2)
{
myMap.insert(param1,param2);
}
void exemple::startShow(){
for (int i = 0; i < myMap.size(); i++){
model->appendRow(new QStandardItem(myMap.keys()[i]));
}
}
在这个例子中,当线程调用 startShow 插槽时,我的冻结就会出现。
我知道我不再在线程中,这就是冻结的原因,但如果不是像我在这里那样向“示例”上的 QMap 添加信息,示例的 addFileinformation 插槽,我会遇到同样的问题。 cpp 直接显示信息。像这样:
示例.cpp
void exemple::addFileinformation(QString param1,QString param2)
{
model->appendRow(new QStandardItem(param1));
}
如果您有解决方案、曲目或链接可以在不冻结的情况下执行此操作,我很感兴趣:)
如果我不清楚,请不要犹豫,再次要求我解释,感谢那些愿意花时间帮助我的人。
解决方法
如果您的数据集很大,您可能需要实现自己的模型,以您存储数据的方式使用数据。 Qt 中的模型很棘手,但是一旦您完成了一些模型,它们就会开始变得有意义。
我的 github 上有一个示例:https://github.com/jplflyer/qt-TreeViewDemo。它可能并不完美。我在试图弄清楚如何编写它时写了它。这适用于 QTreeView
,但 QListView
不会有什么不同。
我这里也有一个通用版本:https://github.com/jplflyer/Git-Dashboard。向下查看 GenericItemModel
的树。这是一个模板,实际上很酷。它也可能功能不全,但可能会有所帮助。
您可以尝试从视图 lv_file->setModel(nullptr);
中取消设置模型以摆脱不必要的视图刷新(每行插入后),更改模型并将其重新设置为视图。
您必须使用信号将您的地图数据发送到 ui 线程并在您的线程中追加一行,而不是直接在您的线程中追加一行。
我仔细检查了你的代码,也许你应该试试这种方式:
void exemple::startShow()
{
QList<QStandardItem*> itemList;
for (int i = 0; i < myMap.size(); i++)
{ itemList<<(new QStandardItem(myMap.keys()[i]));
}
model->appendRow(itemList);
}