qtableview和qlistview使用的一些经验(1)

307 阅读2分钟

示例

demo.gif

功能

功能是参照本地资源管理器

  • 按键盘字母,自动选中文件名开头对应的字母
  • 列表视图和图标视图按住ctrl滚轮切换
  • 排序
  • 重命名
  • shift多选
  • ctrl单选反选

列表视图

使用了QTableView,QAbstractTableModel,QStyledItemDelegate

图标视图

使用了QListView,QAbstractListModel,QStyledItemDelegate

功能具体实现

按键盘字母选中

列表视图和图标视图做法一样,复写keyPressEvent方法

// 键盘接收到的字母
const QString key = event->text();
// 前置过滤,如果没有前置过滤,下面的while循环则会无限循环
// 作用是判断出当前界面中有对应字母开头的名字
const auto it = std::find_if(items_.begin(), items_.end(), [key](const PathInfo& item) {
	return item.name.left(1).toLower() == key;
	});
if (it == items_.end()) {
	return;
}
// 清空所有选中
restore();
// 从最后一个选中开始检索
int index = delegate_->getLastSelectedIndex() + 1;
int nextIndex = -1;
while (true) {
	bool keep = false;
        // 如果找到了,则跳出循环
        // 如果没找到,则从头开始找,直到找到为止
	for (int i = index; i < items_.size(); i++) {
		if (items_[i].name.left(1).toLower() == key) {
			keep = true;
			nextIndex = i;
			break;
		}
	}
	if (keep) {
		break;
	}
	index = 0;
}
// 选中找到的目标
selectRow(nextIndex);
// 跳转到对应目标
scrollTo(model_->index(nextIndex, 0));

按住ctrl滚轮切换视图

两个视图分别复现eventFilter方法

// 列表视图
if (watched == verticalScrollBar() && event->type() == QEvent::Wheel) {
	const auto wheelEvent = dynamic_cast<QWheelEvent*>(event);
        // 按住ctrl,并且滚轮滑动距离大于0,切换图标视图
	if (wheelEvent && wheelEvent->modifiers() == Qt::ControlModifier) {
		if (wheelEvent->delta() > 0) {
			emit switchIconMode();
		}
		return true;
	}
}

// 图标视图
const auto wheelEvent = dynamic_cast<QWheelEvent*>(event);
if (wheelEvent && wheelEvent->modifiers() == Qt::ControlModifier) {
	if (wheelEvent->delta() < 0) {
                // 如果图标尺寸到达显示的最小值(这里是100),则切换成列表模式
		if (delegate_->getIconWidth() == 100) {
			emit switchListMode();
			return QListView::eventFilter(watched, event);
		}
                // 动态设置图标尺寸,这样delegate在绘制的时候,根据动态尺寸来进行绘制
		delegate_->setIconWidth(delegate_->getIconWidth() - 5);
	}
	else {
                // 如果图标尺寸到达显示的最大值(这里是234),则再滚动就没变化
		if (delegate_->getIconWidth() >= 234) {
			return QListView::eventFilter(watched, event);
		}
		delegate_->setIconWidth(delegate_->getIconWidth() + 5);
	}
        // 获取当前所有选中的图标名称
        // 需要在重新绘制后重新选中,不然在绘制后会全部取消
	const auto items = getSelectedItems();
	QList<QString> names;
	for(const auto & item : items) {
		names << item.name;
	}
        // 重新绘制
	model_->load();
	selectItems(names);
}

// switchIconMode和switchListMode实现,则是将两个控件hide和show的操作

排序

列表模式表头排序使用了QTableView的特性

// 表头设置允许排序
horizontalHeader()->setSortIndicatorShown(true);
// 监听表头排序
connect(horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &xxxxx::xxxxx);