QTableWidget整行高亮去虛線,樣式定製
阿新 • • 發佈:2021-01-13
技術標籤:c/c++qtningto.com
很常見的一種需求,但是很可惜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的需求都是
很有必要的,也容易擴充一些新的功能。