lcikgl
lcikgl

Reputation: 779

How to force resizing of indexWidgets to fit in cells of Qt5 QTableView

I'm running the sample code below with Qt5.11.0 on OSX 10.13.6 (also RHEL 7.6, where the problem also occurs, but not as ugly as on OSX). The test program displays a custom model in a QTableView, with indexWidgets set for several of the columns:

#include <QtCore/QDebug>
#include <QtCore/QAbstractItemModel>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QTableView>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QRadioButton>

class AModel : public QAbstractItemModel
{
    public:
    int            rowCount( const QModelIndex& parent = QModelIndex() ) const override { 
                           return 5;    
                       };
    int            columnCount( const QModelIndex& parent = QModelIndex() ) const override { 
                           return 5;    
                       };
    QModelIndex    parent( const QModelIndex& index ) const override { 
                           return QModelIndex();    
                       };     
    QModelIndex    index( int row, int column, const QModelIndex& parent = QModelIndex() ) const override {
                           if( ( ! parent.isValid() ) &&
                               row >= 0 && row < 5 &&
                               column >= 0 && column < 5 ) {
                               return createIndex( row, column );
                           } else {
                               return QModelIndex();
                           }
                       };
    QVariant       data( const QModelIndex& index, int role = Qt::DisplayRole ) const override {
                           QVariant qval;
                           if( index.column() >= 1 && index.column() < 4 ) { return QVariant(); }
                           switch( role ) {
                           case Qt::DisplayRole:
                               qval = QString( "%1,%2" ).arg( index.row() ).arg( index.column() );
                               break;
                           default:
                               qval = QVariant();
                               break;
                           }
                           return qval;
                       };
};

class AWidget : public QWidget
{
    public:
            AWidget( QWidget* parent ) : QWidget( parent ) {
                    QHBoxLayout* l = new QHBoxLayout();
                    this->setLayout( l );
                    QRadioButton* save = new QRadioButton( "Save" );
                    QRadioButton* del = new QRadioButton( "Delete" );
                    l->addWidget( save );
                    l->addWidget( del );
                };
};

int
main( int argc, char *argv[] ) {
    QApplication   app( argc, argv );
    QMainWindow*   mw = new QMainWindow();
    AModel*        model = new AModel();
    QTableView*    view = new QTableView();

    view->setModel( model );

    // view->verticalHeader()->setDefaultSectionSize( 15 );

    for( int irow = 0; irow < model->rowCount(); irow++ ) {
        QPushButton*   pb = new QPushButton( "Mogrify", mw );
        QRadioButton*  rb = new QRadioButton( "Choose", mw );
        AWidget*       aw = new AWidget( mw );

        QObject::connect( pb, &QPushButton::clicked, [irow](){ qDebug() << "Mogrifying " << irow; } );
        QObject::connect( rb, &QRadioButton::clicked, [irow](){ qDebug() << "Choosing " << irow; } );

        view->setIndexWidget( model->index( irow, 1 ), pb );
        view->setIndexWidget( model->index( irow, 2 ), rb );
        view->setIndexWidget( model->index( irow, 3 ), aw );
    }

    view->resizeColumnsToContents();

    mw->setCentralWidget( view );

    mw->show();

    return app.exec();
}

If I just run this as shown above, the result comes out with all the table-embedded widgets having enough space:

table-embedded widgets sizing properly

If however I uncomment the call to setDefaultSectionSize() in the code above, the table-embedded widgets do not size themselves the way I'd wish. The QPushButton is cut off at the bottom, the QRadioButton is crammed in with little padding, and the custom composite widget doesn't show up at all:

table-embedded widgets sizing improperly

I've tried all manner of QSizeHint experiments, subclassing, and internet searching to get these embedded widgets to size themselves according to the space available in the table cells, so far to no avail. How do I make these embedded indexWidgets paint themselves so they fit into the cell space provided in the QTableView, when I'm telling the QTableView how big its cells should be?

Upvotes: 1

Views: 878

Answers (1)

eyllanesc
eyllanesc

Reputation: 243907

The problem is not in the QTableView but in your custom widget. The custom widget has a layout that must have margins equal to 0.

class AWidget : public QWidget
{
public:
    AWidget( QWidget* parent=nullptr) :
        QWidget( parent )
    {
        QHBoxLayout* l = new QHBoxLayout(this);
        l->setContentsMargins(0, 0, 0, 0);  // <----
        QRadioButton* save = new QRadioButton( "Save" );
        QRadioButton* del = new QRadioButton( "Delete" );
        l->addWidget( save );
        l->addWidget( del );
    };
};

enter image description here

Upvotes: 1

Related Questions