QTableWidget整行高亮去虚线,样式定制

Posted ningto.com

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QTableWidget整行高亮去虚线,样式定制相关的知识,希望对你有一定的参考价值。

很常见的一种需求,但是很可惜Qt没有一种比较简单的实现方式。在网上找了很多资料也没有找到,实现方法比较复杂,但是经过
我的实验,下面这种方法是可行的,而且有很多意想不到的好处。

定义接口类

存储当前hovered行,split行是实现其他需求的可以不考虑

	class IView
	
	public:
		virtual void setHoveredRow(int row)  row_ = row; 
		virtual void setSplitRow(int row)  splitRow_ = row; 
		int hoveredRow() const  return row_; 
		int splitRow() const  return splitRow_; 

	private:
		int row_ = -1;
		int splitRow_ = -1;
	;

表格绘制代理类delegate

这个类里面可以实现对每个item的定制化绘制,下面split相关的实现可以不考虑

	class Delegate : public QStyledItemDelegate
	
	public:
		Delegate(QObject *parent = 0);
		~Delegate();
		void setView(IView *view)  view_ = view; 
		void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
	private:
		IView *view_ = nullptr;
	;
	
	Delegate::Delegate(QObject *parent /* = 0 */)
		: QStyledItemDelegate(parent)
	
	

	Delegate::~Delegate()
	
	

	void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
	
		QStyleOptionViewItem opt = option;
		// 去掉焦点虚线框
		if (opt.state & QStyle::State_HasFocus) 
			opt.state = opt.state & ~QStyle::State_HasFocus;
		

		// hover时整行高亮
		if (index.row() == view_->hoveredRow()) 
			opt.state |= QStyle::State_MouseOver;
		 else 
			opt.state &= ~QStyle::State_MouseOver;
		

		// 表格上部分样式
		int splitRow = view_->splitRow();
		bool isFollower = index.row() <= splitRow;
		painter->fillRect(opt.rect, isFollower ? QColor("#0C1E1E") : QColor("#000000"));

		// 上下两部分分隔线
		if (index.row() == splitRow) 
			QRect rect = opt.rect;
			rect.setTop(rect.top() + rect.height() - 2);
			painter->fillRect(rect, QColor("#273F3D"));
		

		QStyledItemDelegate::paint(painter, opt, index);
	

table的具体应用

结合上面两个类来实现我们的需求,由于去掉了一些业务代码下面的类并不完整,不过不影响我们要实现的需求。

	class TableWidget : public QTableWidget, public IView
	
		Q_OBJECT
	public:
		TableWidget(QWidget *parent = 0);
		
	protected:
		void mouseMoveEvent(QMouseEvent *event) override;
		void leaveEvent(QEvent *event) override;
	
	
	TableWidget::TableWidget(QWidget *parent)
		: QTableWidget(parent)
	
		// 隐藏水平垂直头
		this->verticalHeader()->hide();
		this->horizontalHeader()->hide();
		// 去掉虚线框
		this->setShowGrid(false);
		// 单行选择
		this->setSelectionBehavior(QAbstractItemView::SelectRows);
		this->setSelectionMode(QAbstractItemView::SingleSelection);
		// 禁止编辑
		this->setEditTriggers(QTableWidget::NoEditTriggers);
		// 关闭水平垂直滚动条,使用自定义的悬浮滚动条(为了满足样式需求)
		this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
		this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
		// 鼠标跟踪
		this->setMouseTracking(true);
		// 扩展最后一列
		this->horizontalHeader()->setStretchLastSection(true);
		// 支持拖拽
		this->setDragDropMode(QAbstractItemView::DragDrop);
		this->setDragEnabled(true);
		this->setAcceptDrops(true);
		// 应用基本qss样式
		this->setProperty("qssname", "BindingTraderTable");

		Delegate *delegate = new Delegate();
		delegate->setView(this);
		this->setItemDelegate(delegate);
	
	
	void TableWidget::mouseMoveEvent(QMouseEvent *event)
	
		QModelIndex index = this->indexAt(event->pos());
		if (index.isValid()) 
			this->setHoveredRow(index.row());
		
		QTableWidget::mouseMoveEvent(event);
	
	
	void TableWidget::leaveEvent(QEvent *event)
	
		this->setHoveredRow(-1);
		QTableWidget::leaveEvent(event);
	

主要是通过mouseMoveEvent来设置当前hovered的行,然后delegate就可以根据当前row来绘制样式。
虽然上面实现看起来有些复杂,但是这种分层方式是很灵活的在业务中很多对于table的需求都是
很有必要的,也容易扩充一些新的功能。

以上是关于QTableWidget整行高亮去虚线,样式定制的主要内容,如果未能解决你的问题,请参考以下文章

QT如何获取QTableWidget表格中的高亮位置的行数?

如何为 QTableWidget 行绘制边框?

我是新手,在QT中 qtablewidget我选中了一行,此时它属于高亮状态,用啥函数读取高亮处数据?? 急!谢

QTableWidget 颜色、样式

scss 定制虚线边框css

QTableWidget CSS样式