C++ QT, 改进这个类FrozenColumnHeader。当内容太长时,显示不全,需要鼠标悬浮显示。
·
头文件 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_OBJECT
public:
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秒
这样改进后,当表头内容太长显示不全时,鼠标悬停会显示完整的文本内容,提升了用户体验。
更多推荐


所有评论(0)