我需要QTableView
中的行为更改列宽,不仅可以QHeaderView
的帮助,还可以直接在QTableView
区域本身。如果我可以在QTableView
区域中的单元格之间设置光标指针并通过QTableView
区域本身上的“单击并拖动”更改列宽,那将是一件好事。
答案 0 :(得分:1)
实际上我没有看到这种行为有什么问题。特别是对于可以非常方便的只读表视图。
实现此目的的最快方法是安装事件处理程序,该事件处理程序将捕获鼠标事件并发出调整大小命令。显然,如果鼠标位于列分隔符上方/周围,则必须手动计算。
UPD:要了解光标是否在垂直轴周围,您可以使用以下方法:
/* Returns the x-coordinate in contents coordinates of the given column. */
int x = tableView->columnViewportPosition(int column);
鼠标事件将为您提供鼠标位置,然后您可以轻松查看它是否与任何列轴匹配。
UPD2:我甚至会以更复杂的方式实现它,以便在一个eventHandler中处理mousemove和header resize / scroll事件...以缓存排序列表中的列位置,以优化mousemove处理程序所花费的时间。所以,你会得到二进制搜索和距离检查..但它当然取决于界面的重要程度..
答案 1 :(得分:1)
这是一个部分答案,显示了如何访问列分隔符
/** 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细节,请尝试移动垂直鼠标位置,并将事件提供给标题...我认为它可以工作,并且比跟踪状态更简单你自己。
答案 2 :(得分:1)
感谢所有人!
下面是我的源代码结果,它实现了问题中的行为(有点脏,但有一般的想法):
#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);
}