我需要知道我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
答案 0 :(得分:1)
通常,您使用的代码应该可以工作 - 在Qt 5.3.0上查看。
但是,您必须确保在拨打电话时QTableWidget
本身可见。
例如,如果您在MainWindow
构造函数中进行调用,您肯定会得到false
个答案。只有在显示表单后,在特定滚动条上调用isVisible()才会返回正确的值。
修改强>
粘贴代码后,我能够重现这个问题。我需要仔细阅读Qt代码才能看到最新情况。基本上,事实证明,QTableView
是QTableWidget
的父类,滚动条值会通过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))