简体   繁体   English

使用鼠标更改QTableView中的列宽

[英]Change column width in QTableView with mouse

I need behaviour in QTableView for changing of column width not only with help of QHeaderView , but directly on QTableView area itself. 我需要的行为QTableView不仅有帮助的列宽的改变QHeaderView ,而是直接在QTableView区本身。 It will be good if I can set cursor pointer between cells in QTableView area and change the column width with "click and drag" on QTableView area itself. 如果可以在QTableView区域中的单元格之间设置光标指针,并通过对QTableView区域本身进行“单击并拖动”来更改列宽,那将是很好的。

Actually I don't see anything wrong with such behaviour. 实际上,我没有发现这种行为有任何问题。 Especially for read-only table views where it could be really convenient. 特别是对于只读表视图,这可能真的很方便。

Fastest way to implement this to install event handler which will catch mouse events and issue resize commands. 实现此目的的最快方法是安装事件处理程序,该事件处理程序将捕获鼠标事件并发出调整大小命令。 Obviously you will have to calculate manually if mouse is over/around column separator. 显然,如果鼠标位于列分隔符上方/周围,则必须手动计算。

UPD: to get an idea if cursor is around vertical axes you can use following method: UPD:要了解光标是否在垂直轴周围,可以使用以下方法:

/* Returns the x-coordinate in contents coordinates of the given column. */
int x = tableView->columnViewportPosition(int column); 

mouse event will give you mouse position and then you can easily see if it matches any of column axes. 鼠标事件将为您提供鼠标位置,然后您可以轻松查看它是否与任何列轴匹配。

UPD2: I would even implement it in a bit more complicated way to handle mousemove together with header resize/scroll events within one eventHandler... to cache column positions in a sorted list, to optimise time spent in mousemove handler.. so, you will get binary search and distance check.. but its of course depends how heavy is interface in general.. UPD2:我什至可以用一种更为复杂的方式来实现它,以便在一个eventHandler中处理mousemove以及标头调整大小/滚动事件……将列位置缓存在排序列表中,以优化在mousemove处理程序中花费的时间。将获得二进制搜索和距离检查..但是它当然取决于接口的总体重量。

Here a partial answer, showing how to access column separators 这是部分答案,显示了如何访问列分隔符

/** 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 is a virtual function, but you must register it to get it called. eventFilter是一个虚拟函数,但是必须注册它才能调用它。 I added in the FreezeTableWidget constructor: 我在FreezeTableWidget构造函数中添加了:

qApp->installEventFilter(this);

edit : about position check, the suggestion from evilruff also works (albeit the computational efficiency argument is irrilevant), but in general I think that you could try an alternative, more general approach: namely to use the horizontalHeader item as a surrogate handler, because there we already have all the required, working, logic. 编辑 :关于位置检查,evilruff的建议也可以使用(尽管计算效率参数是不友好的),但总的来说,我认为您可以尝试另一种更通用的方法:即使用horizo​​ntalHeader项作为代理处理程序,因为到此,我们已经拥有了所有必需的,有效的逻辑。

If you like to experiment with (and learn about) these GUI details, try to shift the vertical mouse position, and give the event to the header... I think it could work, and will be simpler than tracking the state by yourself. 如果您想尝试(并了解)这些GUI详细信息,请尝试移动鼠标的垂直位置,并将事件提供给标题...我认为它可以工作,并且比您自己跟踪状态更简单。

Thanks to all! 谢谢大家!

Below is my result with source code, that implement behaviour like in the question (little bit dirty, but with general idea): 以下是我的源代码结果,该源代码实现了类似问题的行为(有点脏,但具有总体思路):

#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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM