我需要QTableView
改变列宽的行为,不仅是在 的帮助下QHeaderView
,而且是直接在QTableView
区域本身的帮助下。如果我可以在区域中的单元格之间设置光标指针并通过在区域本身QTableView
上“单击并拖动”来更改列宽,那将会很好。QTableView
3 回答
实际上,我认为这种行为没有任何问题。特别是对于可能非常方便的只读表视图。
实现这一点的最快方法是安装将捕获鼠标事件并发出调整大小命令的事件处理程序。显然,如果鼠标在列分隔符上方/周围,您将不得不手动计算。
UPD:要了解光标是否围绕垂直轴,您可以使用以下方法:
/* Returns the x-coordinate in contents coordinates of the given column. */
int x = tableView->columnViewportPosition(int column);
mouse 事件将为您提供鼠标位置,然后您可以轻松查看它是否与任何列轴匹配。
UPD2:我什至会以更复杂的方式实现它,以处理 mousemove 以及一个 eventHandler 中的标题调整大小/滚动事件......以缓存排序列表中的列位置,以优化在 mousemove 处理程序中花费的时间......所以,你将获得二进制搜索和距离检查..但它当然取决于一般接口的重量..
这里是部分答案,展示了如何访问列分隔符
/** sense mouse position */
bool FreezeTableWidget::eventFilter(QObject *, QEvent *event) {
if (event->type() == QEvent::MouseMove) {
QMouseEvent *m = static_cast<QMouseEvent*>(event);
QPoint p = m->pos();
QRect r = visualRect(indexAt(p));
if (abs(p.x() - r.x()) < 3) // || abs(p.x() - r.right()) < 3)
setCursor(Qt::SplitHCursor);
else
unsetCursor();
}
return false;
}
eventFilter 是一个虚函数,但您必须注册它才能调用它。我在 FreezeTableWidget 构造函数中添加:
qApp->installEventFilter(this);
编辑:关于位置检查,来自 evilruff 的建议也有效(尽管计算效率参数是无关紧要的),但总的来说,我认为您可以尝试另一种更通用的方法:即使用 HorizontalHeader 项目作为代理处理程序,因为在那里,我们已经拥有了所有必需的、有效的逻辑。
如果您想尝试(并了解)这些 GUI 细节,请尝试移动垂直鼠标位置,并将事件赋予标题...我认为它可以工作,并且比自己跟踪状态更简单。
谢谢大家!
下面是我的源代码结果,它实现了问题中的行为(有点脏,但有一般的想法):
#define DELTA_SPLIT 4
static bMouseBetweenCols= false;
static int nResizeColumn= -1;
void CHeaderTableView::mouseMoveEvent(QMouseEvent * event)
{
QMouseEvent *m = static_cast<QMouseEvent*>(event);
QPoint p = m->pos();
QRect r = visualRect(indexAt(p));
if (bMouseBetweenCols && nResizeColumn != -1)
{
QTableView* pT= dynamic_cast<QTableView*>(parent());
if (pT)
{
Q_ASSERT(pT->horizontalHeader());
int nMinSectionSize= pT->horizontalHeader()->minimumSectionSize();
int nSectionSize= p.x() - columnViewportPosition(nResizeColumn);
if (nSectionSize >= nMinSectionSize)
{
pT->horizontalHeader()->resizeSection(nResizeColumn, nSectionSize);
}
}
}
if ( abs(p.x() - r.right()) <= DELTA_SPLIT
|| abs(p.x() - r.left()) <= DELTA_SPLIT)
{
setCursor(Qt::SplitHCursor);
event->ignore();
return;
}
else
unsetCursor();
QTableView::mouseMoveEvent(event);
}
void CHeaderTableView::mousePressEvent(QMouseEvent *event)
{
QMouseEvent *m = static_cast<QMouseEvent*>(event);
QPoint p = m->pos();
QRect r = visualRect(indexAt(p));
if ( abs(p.x() - r.right()) <= DELTA_SPLIT
|| abs(p.x() - r.left()) <= DELTA_SPLIT)
{
QTableView* pT= dynamic_cast<QTableView*>(parent());
if (pT)
{
nResizeColumn= pT->horizontalHeader()->visualIndex(indexAt(p).column());
if (abs(p.x() - r.left()) <= DELTA_SPLIT) { nResizeColumn--; }
nResizeColumn= pT->horizontalHeader()->logicalIndex(nResizeColumn);
if (nResizeColumn >= 0)
bMouseBetweenCols= true;
event->ignore();
return;
}
}
QTableView::mousePressEvent(event);
}
void CHeaderTableView::mouseReleaseEvent(QMouseEvent *event)
{
QMouseEvent *m = static_cast<QMouseEvent*>(event);
QPoint p = m->pos();
QRect r = visualRect(indexAt(p));
if ( abs(p.x() - r.right()) <= DELTA_SPLIT
|| abs(p.x() - r.left()) <= DELTA_SPLIT)
{
bMouseBetweenCols= false;
nResizeColumn= -1;
event->ignore();
return;
}
bMouseBetweenCols= false;
nResizeColumn= -1;
QTableView::mouseReleaseEvent(event);
}
void CHeaderTableView::mouseDoubleClickEvent(QMouseEvent *event)
{
QMouseEvent *m = static_cast<QMouseEvent*>(event);
QPoint p = m->pos();
QRect r = visualRect(indexAt(p));
if ( abs(p.x() - r.right()) <= DELTA_SPLIT
|| abs(p.x() - r.left()) <= DELTA_SPLIT)
{
QTableView* pT= dynamic_cast<QTableView*>(parent());
if (pT)
{
int nDblClickColumn= pT->horizontalHeader()->visualIndex(indexAt(p).column());
if (abs(p.x() - r.left()) <= DELTA_SPLIT) { nDblClickColumn--; }
nDblClickColumn= pT->horizontalHeader()->logicalIndex(nDblClickColumn);
pT->resizeColumnToContents(nDblClickColumn);
}
event->ignore();
return;
}
QTableView::mouseDoubleClickEvent(event);
}