如何知道 VerticalScrollBar 何时显示? [英] How to know when the VerticalScrollBar is showing?

查看:73
本文介绍了如何知道 VerticalScrollBar 何时显示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要知道我的 QTableWidgetverticalScrollBar 何时显示.我目前正在使用以下说明:

I need to know when the verticalScrollBar of my QTableWidget is being shown. I am currently using the following instruction:

标题:

#ifndef MYCLASS_H
#define MYCLASS_H

#include <QDebug>
#include <QWidget>
#include <QScrollBar>

namespace Ui {
class MyClass;
}

class MyClass: public QWidget
{
    Q_OBJECT

public:
    explicit MyClass(QWidget *parent = 0);
    ~MyClass();

private:
    void populateTable(QVector<QString> content);

private:
    Ui::MyClass *ui;
};

#endif // MYCLASS_H

填充表函数:

void MyClass::populateTable(QVector<QString> content)
{
    while( ui->myTableWidget->rowCount() > 0 )
    {
        ui->myTableWidget->removeRow(0);
    }

    QTableWidgetItem* item;
    for (int row = 0; row < content.length(); ++row)
    {
        ui->myTableWidget->insertRow(row);

        item = new QTableWidgetItem( QString::number(row) );
        item->setTextAlignment(Qt::AlignCenter);
        ui->myTableWidget->setItem(row, 0, item);

        item = new QTableWidgetItem( content.at(row) );
        item->setTextAlignment(Qt::AlignCenter);
        ui->myTableWidget->setItem(row, 1, item);
    }

    qDebug() << "This : " << this->isVisible();
    qDebug() << "QTableWidget : " << ui->myTableWidget->isVisible();
    qDebug() << "VerticalScrollBar : " << ui->myTableWidget->verticalScrollBar()->isVisible(); // <-HERE
}

输出:

// Called from the constructor
This :  false
QTableWidget :  false
VerticalScrollBar :  false

// Called by a button pressed
This :  true
QTableWidget :  true
VerticalScrollBar :  true
This :  true
QTableWidget :  true
VerticalScrollBar :  false

但它返回了错误的值.当 ScrollBar 可见时返回 false,不可见时返回 true.注意:myTableWidget (QTableWidget) 始终可见.

But it returns a wrong value. When the ScrollBar is visible it returns false and when it is not visible it returns true. Note: myTableWidget (QTableWidget) is always visible.

有没有其他方法可以做到这一点?

Is there any other way that I can do this?

我使用的是 Qt 5.3.2 版

I'm using Qt version 5.3.2

推荐答案

总的来说,您使用的代码应该可以工作 - 在 Qt 5.3.0 上检查.

In general the code you are using is supposed to work - checked on Qt 5.3.0.

但是,您必须确保在进行调用时 QTableWidget 本身是可见的.

However, you must be sure that when you are making the call the QTableWidget itself is visible.

例如,如果您在 MainWindow 构造函数内进行调用,您肯定会得到 false 答案.只有在显示表单后,对特定滚动条上的 isVisible() 的调用才会返回正确的值.

For example if you make the call inside the MainWindow constructor you will certainly get a false answer. Only after the form is shown the call to isVisible() on particular scrollbar would return the correct value.

粘贴您的代码后,我能够重现该问题.我需要稍微浏览一下 Qt 代码,看看发生了什么.基本上事实证明,对于作为 QTableWidget 父类的 QTableView 滚动条值是通过 updateGeometries 更新的(不要将它与常规的 updateGeometry 我提到的是 protected).在内部,此方法要么直接调用,要么通过事件循环处理事件.简而言之,这取决于您添加的是列还是行.

With your code pasted I was able to reproduce the issue. I needed to go through the Qt code a bit to see whats going on. Basically it turns out that for QTableView which is parent class of QTableWidget scroll bar values are updated via updateGeometries (do not confuse it with the regular updateGeometry the one I'm mentioning is protected). Internally this method is called either directly or the event is processed through the event loop. In short, it depends on whether you add columns or rows.

在您的示例中,如果您在检查 的可见性后 insertColumn 而不是 insertRow(并在 setItem 中切换参数)horizo​​ntalScrollBar 你会马上得到正确的结果.

In your example, if you insertColumn instead of insertRow (and switch the arguments in setItem) after checking the visibility of horizontalScrollBar you will get the proper result right away.

我可以通过子类化 QTableWidget 并覆盖 event 方法来确认这一点.它表明添加列时执行以下事件:MetaCall(调用调用)和LayoutRequest.另一方面,当添加行时,第一个传递的事件是 Timer.

I could confirm this by subclassing the QTableWidget and overriding event method. It shows that when adding columns following events are executed: MetaCall (invoke call) and LayoutRequest. On the other hand, when adding rows first event passed is Timer.

我不是 Qt 实施者,所以我不确定区别的目的是什么.但是,此信息有助于以更优雅的方式解决您的问题.

I'm not Qt implementer so I'm not sure what is the purpose the difference. However, this info helps solving your problem in a more elegant way.

您可以实现覆盖 event 方法的 MyTableWidget.

You can implement MyTableWidget which overrides the event method.

class MyTableWidget: public QTableWidget
{
    Q_OBJECT
public:
    bool event(QEvent *e) override
    {
        const bool result = QTableWidget::event(e);
        if (e->type() == QEvent::LayoutRequest)
        {
            // call what you need here
            // or emit layoutUpdated(); and connect some slots which perform
            // processing dependent on scrollbar visibility
        }
        return result;
    }

signals:
    void layoutUpdated();
}

但是,此类事件可能会在其他情况下被调用,而不仅仅是在由于模型数据更新而需要更新视图时.

However, such event might get called in other situations not only when the view needs to be updated due to model data updates.

另一种解决方案是避免覆盖 event 方法,而是创建自己的方法来触发所需的更新.例如:

Another solution would be to avoid overriding the event method but creating your own method to trigger the required updates. For example:

void MyTableWidget::updateLayout()
{
    QEvent ev{QEvent::LayoutRequest};
    QTableWidget::updateGeometries();
    QTableWidget::event(&ev);
}

这将直接调用 updateGeometries,它重新计算滚动条的最小值/最大值,并为 LayoutRequest 执行直接的 event 方法调用(不通过 eventloop 进行处理)).如果我是正确的,间接更新滚动条的可见性.

This would call directly updateGeometries which recalculates scrollbar min/max values and perform a direct event method call for LayoutRequest (without processing through eventloop). Which if I'm correct indirectly updates scrollbar visibility.

在检查可见性之前调用此方法也应该可以解决您的问题.

Calling this method before checking the visibility should also fix your problem.

ui->myTableWidget->updateLayout();
qDebug() << "VerticalScrollBar : " << ui->myTableWidget->verticalScrollBar()->isVisible();
// prints "VerticalScrollBar :  true   false"

这篇关于如何知道 VerticalScrollBar 何时显示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆