如何知道VerticalScrollBar何时显示?

时间:2016-12-21 20:27:25

标签: c++ qt qtablewidget

我需要知道我verticalScrollBar QTableWidget的显示时间。 我目前正在使用以下说明:

部首:

#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)始终可见。

我还有其他办法吗?

我正在使用Qt版本5.3.2

2 个答案:

答案 0 :(得分:1)

通常,您使用的代码应该可以工作 - 在Qt 5.3.0上查看。

但是,您必须确保在拨打电话时QTableWidget本身可见。

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

修改

粘贴代码后,我能够重现这个问题。我需要仔细阅读Qt代码才能看到最新情况。基本上,事实证明,QTableViewQTableWidget的父类,滚动条值会通过updateGeometries更新(请勿将其与常规updateGeometry混淆。提到的是protected)。在内部,此方法可以直接调用,也可以通过事件循环处理事件。简而言之,这取决于您是添加列还是行。

在您的示例中,如果您在检查insertColumn的可见性后insertRow而不是setItem(并在horizontalScrollBar中切换参数),您将获得正确的结果程。

我可以通过继承QTableWidget和覆盖event方法来确认这一点。它显示在执行事件后添加列时:MetaCall(调用调用)和LayoutRequest。另一方面,当添加行时,首先传递的事件是Timer

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

您可以实施覆盖MyTableWidget方法的event

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

但是,在其他情况下,可能会因为模型数据更新而需要更新视图时调用此类事件。

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

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

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

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

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

答案 1 :(得分:0)

我想在QScrollBar可见时通过信号得到通知。我在这里写这个答案,因为这是我得到的第一个Google结果,没有一个结果能给出正确的答案。

首先,没有可见性改变的信号,因此我们将使用valueChanged

现在,您可以添加一个功能来检查滚动条isVisible()是否正确。
问题:它行不通(而且对Qt有更多了解的人可能可以解释为什么,我很遗憾不能这样做)。

诀窍是使用QTimer(Python代码):

self.horizontalScrollBar().valueChanged.connect(lambda x: QTimer.singleShot(0, some_func))