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?
Forum Updated to NodeBB v4.3 + New Features

Resizing verticalHeader in QTableView doesn't refresh?

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 3 Posters 1.6k 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