自定义QTreeView中的条目编辑器

               默认情况下QTreeView中的条目在用户双击情况下会产生编辑器,允许用户输入,但是自己用了这么久,每个功能都是不需要的,往往都是右键啊,其它功能键啊,激活编辑器。

               而同时,在项目中,这种原生的编辑器往往都不能满足需求,因为在某些机器测试情况下,会出现怪怪的样子,不是编辑器的高度过窄,就是不能限制用户输入,而这是非常重要的。今天,我们用QItemDelegate生成自己的编辑器(当然编辑器是QLineEdit)。

EditDelegate::EditDelegate(QObject* parent)
:QItemDelegate(parent)
{

}

QWidget* EditDelegate::createEditor(QWidget* parent,
					  const QStyleOptionViewItem& option,
					  const QModelIndex& index) const
{
	QLineEdit* editor = NULL;
	if(index.isValid())
	{
		editor  = new QLineEdit(parent);
		editor->setMaxLength(32);//限制最大只能输入32个字符
		editor->setFixedHeight(20);//调到满意为止

	}
	return editor;
}

void EditDelegate::setEditorData(QWidget* editor,const QModelIndex& index) const
{
		if(index.isValid())
		{
			QLineEdit* lineE = qobject_cast<QLineEdit*>(editor);
			lineE->setText(index.data(Qt::DisplayRole).toString());//text() == data(Qt::DispalyRole).toString()
		}
}

void EditDelegate::setModelData(QWidget* editor,
				  QAbstractItemModel* model, 
				  const QModelIndex& index
				  ) const
{
	if(index.isValid())
	{
		QLineEdit* lineE = qobject_cast<QLineEdit*>(editor);
		model->setData(index,lineE->text());
	}
}

void EditDelegate::updateEditorGeometry(QWidget* editor,
						  const QStyleOptionViewItem& option,
						  const QModelIndex& index
						  ) const
{
	editor->setGeometry(option.rect);
}
二话不说,贴代码(主要来自Qt高级编程一书,感谢作者)

使用的话,当使用QTreeView槽函数edit(位置索引)时,就跳出这个编辑器了,而且还可以通过样式表设置外观,挺不错的。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C++实现自定义QTreeview和QFileSystemModel的完整代码及注释: ``` #include <QTreeView> #include <QFileSystemModel> #include <QTimer> #include <QThread> #include <QDebug> #include <QVBoxLayout> #include <QApplication> // 定义扫描文件的数量 const int MAX_FILES = 100; // 定义扫描的时间间隔 const int SCAN_INTERVAL = 500; // 毫秒 // 定义文件类型过滤器 const QStringList FILTERS = {"*.txt"}; // 自定义QFileSystemModel类,继承自QFileSystemModel class CustomFileSystemModel : public QFileSystemModel { public: CustomFileSystemModel(QObject *parent = nullptr) : QFileSystemModel(parent) { } // 重写canFetchMore函数,用于判断是否还有更多的数据需要获取 bool canFetchMore(const QModelIndex &parent) const override { // 如果当前的文件数小于总文件数,则还有更多数据需要获取 return rowCount(parent) < m_totalFiles; } // 设置总文件数 void setTotalFiles(int totalFiles) { m_totalFiles = totalFiles; } private: // 总文件数 int m_totalFiles = 0; }; // 自定义QTreeView类,继承自QTreeView class CustomTreeView : public QTreeView { public: CustomTreeView(QWidget *parent = nullptr) : QTreeView(parent) { // 创建QFileSystemModel对象 m_fileSystemModel = new CustomFileSystemModel(this); // 设置过滤器 m_fileSystemModel->setNameFilters(FILTERS); // 设置排序方式 m_fileSystemModel->setSort(QDir::Name | QDir::IgnoreCase); // 设置根目录 setModel(m_fileSystemModel); setRootIndex(m_fileSystemModel->index(QDir::rootPath())); // 开始定时器 m_timer.start(SCAN_INTERVAL); // 连接定时器的timeout信号到scanFiles槽函数 connect(&m_timer, &QTimer::timeout, this, &CustomTreeView::scanFiles); } ~CustomTreeView() { // 停止定时器 m_timer.stop(); // 删除QFileSystemModel对象 delete m_fileSystemModel; } private: // 扫描文件 void scanFiles() { // 如果当前正在扫描,则退出函数 if (m_isScanning) return; // 标记为正在扫描 m_isScanning = true; // 获取当前目录 QString currentPath = m_fileSystemModel->rootPath(); // 获取当前目录下的所有文件 QStringList files = QDir(currentPath).entryList(FILTERS, QDir::Files | QDir::NoSymLinks); // 获取当前目录下的所有子目录 QStringList dirs = QDir(currentPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot); // 计算总文件数 int totalFiles = files.count(); // 遍历子目录,计算总文件数 for (const QString &dir : qAsConst(dirs)) { QString subdir = QString("%1/%2").arg(currentPath).arg(dir); totalFiles += QDir(subdir).count(FILTERS); } // 设置总文件数 m_fileSystemModel->setTotalFiles(totalFiles); // 获取当前的QModelIndex QModelIndex currentIndex = currentIndex(); // 如果当前的QModelIndex没有对应的QFileInfo,则退出函数 if (!currentIndex.isValid() || !m_fileSystemModel->hasChildren(currentIndex)) { m_isScanning = false; return; } // 获取当前的QFileInfo QFileInfo currentFileInfo = m_fileSystemModel->fileInfo(currentIndex); // 如果当前的QFileInfo不是目录,则退出函数 if (!currentFileInfo.isDir()) { m_isScanning = false; return; } // 获取当前目录 QString path = currentFileInfo.absoluteFilePath(); // 获取当前目录下的所有文件和子目录 QStringList allFilesAndDirs = QDir(path).entryList(QDir::AllEntries | QDir::NoDotAndDotDot); // 遍历所有文件和子目录 int count = 0; for (const QString &fileOrDir : qAsConst(allFilesAndDirs)) { // 获取文件或子目录的绝对路径 QString filePath = QString("%1/%2").arg(path).arg(fileOrDir); // 如果是文件,则添加到模型 if (QFileInfo(filePath).isFile()) { // 添加文件到模型 m_fileSystemModel->addFile(filePath, currentIndex); // 计数器加1 count++; // 如果计数器大于等于MAX_FILES,则退出循环 if (count >= MAX_FILES) break; } } // 标记为扫描完毕 m_isScanning = false; } private: // 文件系统模型 CustomFileSystemModel *m_fileSystemModel; // 定时器 QTimer m_timer; // 是否正在扫描 bool m_isScanning = false; }; // 自定义QThread类,用于在单独的线程运行QApplication::exec函数 class AppThread : public QThread { public: void run() override { QApplication::exec(); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); // 创建自定义QTreeView对象 CustomTreeView *treeView = new CustomTreeView; // 创建垂直布局 QVBoxLayout *layout = new QVBoxLayout; // 将自定义QTreeView添加到布局 layout->addWidget(treeView); // 创建QWidget对象,作为窗口的主体 QWidget *widget = new QWidget; // 将布局添加到QWidget widget->setLayout(layout); // 创建AppThread对象 AppThread appThread; // 启动线程 appThread.start(); // 显示窗口 widget->show(); // 进入主线程的消息循环 return a.exec(); } ``` 在上面的代码,我们首先定义了一些常量,包括扫描文件的数量、扫描的时间间隔和文件类型过滤器。然后,我们定义了一个自定义的QFileSystemModel类和一个自定义QTreeView类。自定义的QFileSystemModel类继承自QFileSystemModel类,重写了canFetchMore函数和setTotalFiles函数。canFetchMore函数用于判断是否还有更多的数据需要获取,setTotalFiles函数用于设置总文件数。自定义QTreeView类继承自QTreeView类,具有扫描文件的功能。我们在构造函数创建了一个QFileSystemModel对象,并设置过滤器和排序方式。然后,我们使用定时器每隔一段时间扫描目录下的文件和子目录,并将它们添加到模型。我们使用一个布尔变量m_isScanning来判断当前是否正在扫描文件。如果正在扫描,则退出函数。在scanFiles函数,我们首先获取当前目录下的所有文件和子目录,计算总文件数,设置总文件数和当前目录的QModelIndex。然后,我们遍历所有文件和子目录,将文件添加到模型。最后,我们标记为扫描完毕。在main函数,我们创建了一个自定义QTreeView对象和一个QWidget对象,并将其添加到布局。然后,我们创建了一个AppThread对象,用于在单独的线程运行QApplication::exec函数。最后,我们显示窗口并进入主线程的消息循环。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值