头文件 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秒
这样改进后,当表头内容太长显示不全时,鼠标悬停会显示完整的文本内容,提升了用户体验。