Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Resizing verticalHeader in QTableView doesn't refresh?
Qt 6.11 is out! See what's new in the release blog

Resizing verticalHeader in QTableView doesn't refresh?

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 3 Posters 2.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • AndeolA Offline
    AndeolA Offline
    Andeol
    wrote on last edited by
    #1

    Hi everyone,

    I have a QTableView with vertical header, and I need to programatically change the width of this header.

    So I call:

    myQTableView->verticalHeader()->setFixedWidth(newWidth);
    

    Looks simple enough. But nothing happens. The header doesn't change. It seems the new display just needs a kind of refresh.
    After this call, if I just manually minimize my window, and then show it again, for example, then the new width is taken into account.

    I tried calling myQTableView->repaint(), but it has no effect.

    I managed a hack to this issue by calling:

    myQTableView->verticalHeader()->setFixedWidth(newWidth);
    myQTableView->hide();
    myQTableView->show();
    

    This works, but it feels like a dirty hack. Do you have any cleaner solution, or explanations for why the header is not correctly resized in the first place?

    Developer for R++ : https://rplusplus.com/

    1 Reply Last reply
    -1
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      What version of Qt are you using ?
      On what OS ?
      Can you provide a minimal compilable example that shows this behaviour ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • AndeolA Offline
        AndeolA Offline
        Andeol
        wrote on last edited by Andeol
        #3

        I'm using Qt5.6.3 on windows 10.

        Originally, it's from a pretty big project, but I managed to reproduce the issue on something smaller. However, I must have changed something in the process, because it's now slightly different. Now the header is indeed resized, but it hides the first column instead of moving it. I guess in the big project version, the header is resized, but hidden by the first column instead.

        Here is a compilable code that shows the issue (I'd upload the files, but apparently I don't have the rights for that, it requires more reputation in the forum, I guess):

        The .pro file (nothing special):

        #-------------------------------------------------
        #
        # Project created by QtCreator 2018-04-06T08:49:03
        #
        #-------------------------------------------------
        
        QT       += core gui
        
        greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
        
        TARGET = bug_minimal
        TEMPLATE = app
        
        SOURCES += main.cpp\
                mainwindow.cpp \
            tablemodel.cpp
        
        HEADERS  += mainwindow.h \
            tablemodel.h
        
        FORMS    += mainwindow.ui
        
        

        main.cpp (nothing special either):

        #include "mainwindow.h"
        #include <QApplication>
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            MainWindow w;
            w.show();
        
            return a.exec();
        }
        

        mainWindow.h: I tried to reduce to the smallest case, and thus put everything in mainWindow.

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H
        
        #include <QMainWindow>
        #include <QTableView>
        #include <QPushButton>
        #include <QSplitter>
        
        namespace Ui {
        class MainWindow;
        }
        
        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        public:
            explicit MainWindow(QWidget *parent = 0);
            ~MainWindow();
        
        public slots:
            void changeHeaderSize();
        
        private:
            Ui::MainWindow *ui;
            QTableView *myTableView ;
            QSplitter   * _splitter;
            QAbstractTableModel* _model;
            QPushButton *_myButton;
        };
        
        #endif // MAINWINDOW_H
        

        tableModel.h, the model we use for out table (Strongly reduced as well, here a simple subclassing of QAbstractTableModel):

        #ifndef DATAEDITOR_DATAEDITORTABLEMODEL_H_
        #define DATAEDITOR_DATAEDITORTABLEMODEL_H_
        
        #include <QAbstractTableModel>
        #include <QTableWidgetItem>
        
        /**
         * @brief TableModel : models that holds QTableWidgetItem, each representing a column in a dataframe.
         * It has thus only one row
         */
        class TableModel : public QAbstractTableModel{
            Q_OBJECT
        public:
            TableModel(QObject *parent = 0) : QAbstractTableModel(parent) {}
            ~TableModel(){ for (auto i: _itemList) delete i;}
        
            // Functions reimplemented as required in http://doc.qt.io/qt-5/qabstracttablemodel.html#subclassing
            virtual int rowCount(const QModelIndex &parent = QModelIndex()) const {return parent.isValid()?0:1;}   // only one line, we make extensive use of roles
            virtual int columnCount(const QModelIndex &parent = QModelIndex()) const {return parent.isValid()?0:_itemList.size();}
            virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;      // defines the header content
            virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
            virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
            virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex());
        
        
        private:
            QList<QTableWidgetItem*> _itemList;
        
        
        };
        
        #endif /* DATAEDITOR_DATAEDITORTABLEMODEL_H_ */
        

        tableModel.cpp:

        
        #include "tablemodel.h"
        #include <QDebug>
        
        QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const{
        
            if(orientation == Qt::Horizontal) {
                return "horizontal header Name" ;
            }
        
            return QAbstractTableModel::headerData(section,orientation,role);
        }
        
        QVariant TableModel::data(const QModelIndex &index, int role) const{
            if (!index.isValid()) return QVariant();        // if index is invalid, return empty QVariant
            return _itemList.at(index.column())->data(role);
        }
        
        
        /**
         * @brief TableModel::setData modifies the data in the model
         * @param index index if the data to modify
         * @param value value to set
         * @param role role to set
         */
        bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role){
            // if the index corresponds to a valid culumn (less than the number of elements in _itemList, and on the  0th line)
            if (index.isValid() && index.column() < _itemList.size() && index.row() == 0){
                // set the data in the model
                 _itemList[index.column()]->setData(role,value);
        
                // emit the approriate signal (dataChanged)
                emit dataChanged(index,index,QVector<int>(role));
            }
            // return success because we consider it can't fail (todo : take into accout errors)
            return true;
        }
        
        
        // insertColumns :
        // The items in each new column will be children of the item represented by the parent model index.
        // If column is 0, the columns are prepended to any existing columns.
        // If column is columnCount(), the columns are appended to any existing columns.
        // Parents are ignored in our implementation
        // Returns true if the columns were successfully inserted; TO DO: otherwise returns false.
        bool TableModel::insertColumns(int column, int count, const QModelIndex &parent){
            beginInsertColumns(parent,column, column+count-1);  // Mandatory call per Qt framework.
            while (count--){
                // creates new item
                QTableWidgetItem* newCol = new QTableWidgetItem();
                // adds to it a default TrueFalseMap
                _itemList.insert(column,newCol);
            }
            endInsertColumns();  // Mandatory call per Qt framework.
            return true;
        }
        

        And finally mainwindow.cpp, where we can comment or un-comment 2 lines to see the effect of my dirty fix:

        #include "tablemodel.h"
        
        MainWindow::MainWindow(QWidget *parent) :
            QMainWindow(parent),
            ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
        
            _splitter =  new QSplitter(Qt::Vertical,this);
            _splitter->resize(350, 350);
        
            // create a model, and put some random data into it.
            _model = new TableModel();
            _model->insertColumns(0, 2, QModelIndex());
            _model->setData(_model->index(0,0,QModelIndex()), QVariant(42), Qt::EditRole) ;
            _model->setData(_model->index(0,1,QModelIndex()), QVariant(57), Qt::EditRole) ;
        
            // Create the QTableView
            myTableView = new QTableView(this);
            myTableView->setModel(_model);
            myTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        
            // Adds a button to trigger the change in header size.
            _myButton = new QPushButton(this);
            _myButton->setText("Change header size");
            connect(_myButton, &QPushButton::clicked, this, &MainWindow::changeHeaderSize);
        
            _splitter->insertWidget(0,_myButton);
            _splitter->insertWidget(1,myTableView);
        }
        
        MainWindow::~MainWindow()
        {
            delete ui;
        }
        
        void MainWindow::changeHeaderSize() {
            myTableView->verticalHeader()->setFixedWidth(100);
            // De-commenting the follwoing lines forces the update and "fixes" the issue.
            //myTableView->hide();
            //myTableView->show();
        }
        

        Thanks for your attention.

        Developer for R++ : https://rplusplus.com/

        1 Reply Last reply
        0
        • Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by Christian Ehrlicher
          #4

          I can reproduce the issue (and have an idea how to fix it): https://bugreports.qt.io/browse/QTBUG-67532

          /edit: fix will be in 5.12 :)

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          3

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved