Important: Please read the Qt Code of Conduct -

Resizing verticalHeader in QTableView doesn't refresh?

  • Hi everyone,

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

    So I call:


    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:


    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?

  • Lifetime Qt Champion


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

  • 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 \
    HEADERS  += mainwindow.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;;
        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
        explicit MainWindow(QWidget *parent = 0);
    public slots:
        void changeHeaderSize();
        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):

    #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{
        TableModel(QObject *parent = 0) : QAbstractTableModel(parent) {}
        ~TableModel(){ for (auto i: _itemList) delete i;}
        // Functions reimplemented as required in
        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());
        QList<QTableWidgetItem*> _itemList;


    #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
     * @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
            // 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
        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) :
        ui(new Ui::MainWindow)
        _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);
        // 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);
        delete ui;
    void MainWindow::changeHeaderSize() {
        // De-commenting the follwoing lines forces the update and "fixes" the issue.

    Thanks for your attention.

  • Qt Champions 2019

    I can reproduce the issue (and have an idea how to fix it):

    /edit: fix will be in 5.12 :)

Log in to reply