2016-12-21 17 views
-1

Мне нужно знать, когда отображается verticalScrollBar моего QTableWidget. настоящее время я использую следующую инструкцию:Как узнать, когда отображается VerticalScrollBar?

Заголовок:

#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

Ваши ожидания неверны. Возвращаемые значения верны. Это все. Когда вы запрашиваете виджет, он либо еще не отображается, либо еще не скрыт. Вы должны изменить свой код на запрос в соответствующее время или остановиться в зависимости от поведения, которое нигде не задокументировано так, как вы ожидаете. –

+0

Это не полный пример. Полный пример был бы одним файлом, минимальным фрагментом кода, который любой может скопировать-вставить в 'main.cpp', скомпилировать и запустить. Наиболее критично, вы не показываете **, когда ** вы вызываете запросы. Вы просто говорите нам, что ожидаете чего-то другого, но нет никакого способа узнать, чего вы ожидаете, и почему, не видя кода, не имея необходимости вторгаться в вещи. –

+0

На самом деле, я не могу разделить весь код, и у меня нет много времени, чтобы написать полный пример, который показывает всю «ситуацию». Спасибо, в любом случае. – KelvinS

ответ

1

В общем коде вы используете, должны работать - проверено на Qt 5.3.0.

Однако вы должны быть уверены, что когда вы делаете звонок, видна сама QTableWidget.

Например, если вы звоните внутри конструктора MainWindow, вы обязательно получите ответ false. Только после отображения формы вызов isVisible() на определенной полосе прокрутки вернет правильное значение.

EDIT:

С кодом вставил я был в состоянии воспроизвести проблему. Мне нужно немного пройти через 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" 
+0

Спасибо, @Dusteh. Я вызываю вызов внутри функции после заполнения TableWidget. Я обновил вопрос с полным примером. – KelvinS

+0

Является ли 'MyClass'' QWidget' (похоже, так)? Пожалуйста, дополнительно проверьте и распечатайте 'qDebug() << isVisible();' - прямо под проверкой видимости полосы прокрутки. Сообщите нам, что вы получаете. – Dusteh

+0

Да, это так. Я обновил вопрос. Визуализация 'QTableWidget' обновляется каждый раз, когда мы называем' insertRow' или 'setItem'? Если нет, возможно, визуализация 'QTableWidget' еще не обновляется, когда я вызываю функцию verticalScrollBar() -> isVisible()'. – KelvinS