頭文件?frozencolumnheader.h
:
cpp
#ifndef FROZENCOLUMNHEADER_H #define FROZENCOLUMNHEADER_H#include <QHeaderView> #include <QTableView> #include <QPainter> #include <QMouseEvent> #include <QStyleOptionHeader> #include <QItemSelectionModel> #include <QEvent> #include <QToolTip>class FrozenColumnHeader : public QHeaderView {Q_OBJECTpublic:explicit FrozenColumnHeader(QTableView* tableView);~FrozenColumnHeader() override = default;// 新增方法:設置字體void setHeaderFont(const QFont& font);void setHeaderFontSize(int pointSize);void setHeaderFontBold(bool bold);void setHeaderTextColor(const QColor& color);// 新增方法:設置工具提示相關屬性void setToolTipEnabled(bool enabled);bool isToolTipEnabled() const;void setToolTipDuration(int milliseconds);int toolTipDuration() const;signals:void sectionClicked(int logicalIndex);protected:void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const override;void mousePressEvent(QMouseEvent* event) override;void mouseMoveEvent(QMouseEvent* event) override;void leaveEvent(QEvent* event) override;QSize sizeHint() const override;bool event(QEvent* event) override;private slots:void onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);private:QString getElidedText(const QString& text, const QFont& font, int width) const;bool needToolTip(const QString& text, const QFont& font, int width) const;private:QTableView* m_tableView;int m_hoveredSection = -1;QFont m_headerFont; // 新增:字體設置QColor m_headerTextColor; // 新增:文字顏色bool m_toolTipEnabled = true; // 新增:是否啟用工具提示int m_toolTipDuration = 3000; // 新增:工具提示顯示時間(毫秒)QString m_lastToolTipText; // 新增:上次顯示的工具提示文本 };#endif // FROZENCOLUMNHEADER_H
實現文件?frozencolumnheader.cpp
:
cpp
#include "frozencolumnheader.h" #include <QDebug> #include <QFontMetrics>FrozenColumnHeader::FrozenColumnHeader(QTableView* tableView): QHeaderView(Qt::Vertical, tableView), m_tableView(tableView) {// 初始化默認字體設置m_headerFont = QFont("Microsoft YaHei"); // 默認字體和大小m_headerFont.setPixelSize(12);m_headerTextColor = Qt::black; // 默認文字顏色setSectionsClickable(true);setHighlightSections(true);//setDefaultSectionSize(35);setMinimumWidth(200);setAttribute(Qt::WA_Hover, true);// 連接選擇變化信號if (tableView && tableView->selectionModel()) {connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged,this, &FrozenColumnHeader::onSelectionChanged);} }// 設置字體 void FrozenColumnHeader::setHeaderFont(const QFont& font) {m_headerFont = font;update(); // 重繪 }// 設置字體大小 void FrozenColumnHeader::setHeaderFontSize(int pointSize) {m_headerFont.setPointSize(pointSize);update(); // 重繪 }// 設置字體加粗 void FrozenColumnHeader::setHeaderFontBold(bool bold) {m_headerFont.setBold(bold);update(); // 重繪 }// 設置文字顏色 void FrozenColumnHeader::setHeaderTextColor(const QColor& color) {m_headerTextColor = color;update(); // 重繪 }// 設置是否啟用工具提示 void FrozenColumnHeader::setToolTipEnabled(bool enabled) {m_toolTipEnabled = enabled; }// 獲取工具提示啟用狀態 bool FrozenColumnHeader::isToolTipEnabled() const {return m_toolTipEnabled; }// 設置工具提示顯示時間 void FrozenColumnHeader::setToolTipDuration(int milliseconds) {m_toolTipDuration = milliseconds; }// 獲取工具提示顯示時間 int FrozenColumnHeader::toolTipDuration() const {return m_toolTipDuration; }// 獲取省略文本 QString FrozenColumnHeader::getElidedText(const QString& text, const QFont& font, int width) const {QFontMetrics metrics(font);return metrics.elidedText(text, Qt::ElideRight, width - 10); // 留出10像素的邊距 }// 檢查是否需要顯示工具提示 bool FrozenColumnHeader::needToolTip(const QString& text, const QFont& font, int width) const {if (text.isEmpty()) {return false;}QFontMetrics metrics(font);return metrics.horizontalAdvance(text) > (width - 10); // 留出10像素的邊距 }void FrozenColumnHeader::paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const {if (!m_tableView || !m_tableView->model())return;if (!painter || logicalIndex < 0 || logicalIndex >= count()) {return;}// 使用靜態變量緩存顏色static const QColor selectedBgColor("#0078d7");static const QColor selectedBorderColor("#005a9e");static const QColor normalBgColor("#f8f8f8");static const QColor normalBorderColor("#d0d0d0");static const QColor hoverBgColor("#e3f2fd");static const QColor textColorWhite(Qt::white);static const QColor textColorBlack(Qt::black);// 關鍵修復:正確檢查選擇狀態bool isSelected = false;if (m_tableView->selectionModel()) {// 檢查該行是否有任何選中的單元格QModelIndex index = m_tableView->model()->index(logicalIndex, 0);isSelected = m_tableView->selectionModel()->isSelected(index);}const bool isHovered = (logicalIndex == m_hoveredSection);// 獲取數據const QString data = m_tableView->model()->data(m_tableView->model()->index(logicalIndex, 0)).toString();painter->save();// 確定背景和文字顏色QColor backgroundColor;QColor textColor;QColor borderColor;if (isSelected) {backgroundColor = selectedBgColor;textColor = textColorWhite;borderColor = selectedBorderColor;}else if (isHovered) {backgroundColor = hoverBgColor;textColor = textColorBlack;borderColor = normalBorderColor;}else {backgroundColor = normalBgColor;textColor = textColorBlack;borderColor = normalBorderColor;}// 繪制背景painter->fillRect(rect, backgroundColor);// 繪制邊框painter->setPen(palette().mid().color());painter->drawRect(rect);// 設置字體和文字顏色painter->setFont(m_headerFont);painter->setPen(m_headerTextColor);// 繪制文本painter->setPen(textColor);QFont font = painter->font();if (isSelected) {font.setBold(true);}painter->setFont(font);// 如果文本太長,顯示省略號QString displayText = getElidedText(data, font, rect.width());painter->drawText(rect, Qt::AlignCenter, displayText);// 繪制邊框painter->setPen(borderColor);painter->drawRect(rect.adjusted(0, 0, -1, -1));painter->restore(); }bool FrozenColumnHeader::event(QEvent* event) {if (m_toolTipEnabled && event->type() == QEvent::ToolTip) {QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);int logicalIndex = logicalIndexAt(helpEvent->pos());if (logicalIndex >= 0 && logicalIndex < count()) {// 獲取數據QString data = m_tableView->model()->data(m_tableView->model()->index(logicalIndex, 0)).toString();// 獲取該section的矩形區域QRect sectionRect(sectionViewportPosition(logicalIndex), 0, sectionSize(logicalIndex), height());// 檢查是否需要顯示工具提示if (needToolTip(data, m_headerFont, sectionRect.width())) {QToolTip::showText(helpEvent->globalPos(), data, this, sectionRect, m_toolTipDuration);m_lastToolTipText = data;return true;}}QToolTip::hideText();event->ignore();return true;}return QHeaderView::event(event); }void FrozenColumnHeader::mousePressEvent(QMouseEvent* event) {if (!m_tableView || !m_tableView->selectionModel()) {QHeaderView::mousePressEvent(event);return;}const int logicalIndex = logicalIndexAt(event->pos());if (logicalIndex >= 0) {// 清除所有現有選擇m_tableView->selectionModel()->clearSelection();// 選擇整行(包括隱藏的第一列)for (int col = 0; col < m_tableView->model()->columnCount(); ++col) {QModelIndex index = m_tableView->model()->index(logicalIndex, col);m_tableView->selectionModel()->select(index, QItemSelectionModel::Select);}emit sectionClicked(logicalIndex);}else {// 點擊表頭空白處時清除所有選擇m_tableView->selectionModel()->clearSelection();}update();QHeaderView::mousePressEvent(event); }void FrozenColumnHeader::mouseMoveEvent(QMouseEvent* event) {QHeaderView::mouseMoveEvent(event);const int newHoveredSection = logicalIndexAt(event->pos());if (newHoveredSection != m_hoveredSection) {m_hoveredSection = newHoveredSection;update();} }void FrozenColumnHeader::leaveEvent(QEvent* event) {QHeaderView::leaveEvent(event);m_hoveredSection = -1;update(); }QSize FrozenColumnHeader::sizeHint() const {return QSize(200, QHeaderView::sizeHint().height()); }void FrozenColumnHeader::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {Q_UNUSED(selected);Q_UNUSED(deselected);// 強制立即更新整個表頭update();// 確保視圖也更新if (viewport()) {viewport()->update();} }
主要改進內容:
添加工具提示功能:
重寫?
event()
?方法處理?QEvent::ToolTip
?事件添加?
setToolTipEnabled()
、isToolTipEnabled()
?等方法控制工具提示行為添加?
setToolTipDuration()
、toolTipDuration()
?方法設置工具提示顯示時間
文本省略處理:
添加?
getElidedText()
?方法處理文本過長時的省略顯示添加?
needToolTip()
?方法判斷是否需要顯示工具提示在?
paintSection()
?中使用省略文本繪制
智能工具提示顯示:
只在文本確實過長時才顯示工具提示
工具提示顯示完整內容
工具提示位置與對應的表頭section對齊
性能優化:
只在需要時顯示工具提示,避免不必要的提示
使用字體度量準確計算文本寬度
使用方法:
cpp
FrozenColumnHeader* header = new FrozenColumnHeader(tableView); header->setToolTipEnabled(true); // 啟用工具提示(默認已啟用) header->setToolTipDuration(5000); // 設置工具提示顯示5秒
這樣改進后,當表頭內容太長顯示不全時,鼠標懸停會顯示完整的文本內容,提升了用戶體驗。