使用鼠标更改QTableView中的列宽

时间:2013-08-09 12:14:28

标签: c++ qt

我需要QTableView中的行为更改列宽,不仅可以QHeaderView的帮助,还可以直接在QTableView区域本身。如果我可以在QTableView区域中的单元格之间设置光标指针并通过QTableView区域本身上的“单击并拖动”更改列宽,那将是一件好事。

3 个答案:

答案 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的建议也有效(虽然计算效率参数不相关),但总的来说我认为你可以尝试另一种更通用的方法:即使用horizo​​ntalHeader项作为代理处理程序,因为我们已经拥有了所有必需的工作逻辑。

如果您想尝试(并了解)这些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);
}