Как узнать, когда отображается VerticalScrollBar?
Мне нужно знать, когда 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 видим, он возвращает ложь, а когда он не виден, он возвращает истину. Примечание: myTableWidget (QTableWidget
) всегда видно.
Есть ли другой способ, которым я могу сделать это?
Я использую Qt версии 5.3.2
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"
Я хотел получать уведомление через сигнал, когда QScrollBar становится видимым. Я пишу этот ответ здесь, так как это первый результат Google, который я получил, и ни один результат не дал правильного ответа.
Во-первых, нет сигнала об изменении видимости, поэтому воспользуемся valueChanged
.
Теперь вы можете добавить функцию, которая проверяет, есть ли полоса прокрутки isVisible()
или не.
Проблема: это не сработает (и кто-то с большим знанием Qt, вероятно, мог бы объяснить, почему, я, к сожалению, не могу).
Хитрость в том, чтобы использовать QTimer (код Python):
self.horizontalScrollBar().valueChanged.connect(lambda x: QTimer.singleShot(0, some_func))