IT Notes

QWidget в ячейке таблицы QTableWidget

Мы уже помещали произвольные виджеты в QListWidget. В этот раз разберемся, как добавлять виджеты в Qt-Представления на примере QTableWidget. Сразу замечу, что описанный подход одинаково хорошо работает для любой реализации QAbstractItemView.

Разместим в ячейке таблицы кнопку QPushButton. В результате получится нечто подобное:

qt-view-button-demo

На подготовительном этапе воспользуемся QtDesigner. Создадим простой виджет, на который добавим QTableWidget. Заполним его произвольными данными:

qt-designer-qtablewidget-thumbnail

Обратите внимание, что мы зарезервировали пустой столбец "Действие". В его ячейки мы и добавим кнопки.

Для нумерации столбцов определим перечисление:

enum {
    COLUMN_LAST_NAME,
    COLUMN_FIRST_NAME,
    COLUMN_MIDDLE_NAME,
    COLUMN_ACTION
};

По умолчанию виджет, добавленный в ячейку Представления, занимает всю площадь этой ячейки. Для кнопки это нежелательно, поэтому обернем ее во вспомогательный виджет:

QWidget* ViewButtonDemo::createButtonWidget() const {
    QWidget* wgt = new QWidget;
    QBoxLayout* l = new QHBoxLayout;
    QPushButton* btn = new QPushButton( "Click me!" );
    connect( btn, SIGNAL( clicked( bool ) ), SLOT( onBtnClicked() ) );
    l->setMargin( 0 );
    l->addWidget( btn );
    l->addStretch();
    wgt->setLayout( l );

    return wgt;
}

Кнопку соединяем со слотом onBtnClicked():

void ViewButtonDemo::onBtnClicked() {
    if( QPushButton* btn = qobject_cast< QPushButton* >( sender() ) ) {
        QModelIndex index = ui->tableWidget->indexAt( btn->parentWidget()->pos() );
        qDebug() << index.row() << "x" << index.column();
        QStringList name;
        for( int i = COLUMN_LAST_NAME; i <= COLUMN_MIDDLE_NAME; ++i ) {
            name << ui->tableWidget->model()->data(
                     ui->tableWidget->model()->index( index.row(), i )
                 ).toString();
        }
        QMessageBox::information( this, "The button was clicked", name.join( " " ) );
    }
}

Имея указатель на кнопку-отправителя в onBtnClicked(), мы находим табличный Индекс. Он содержит информацию о номере строки и столбца ячейки, в которой расположена кнопка. По номеру строки запрашиваем данные модели (ФИО), которые затем отображаем в диалоговом окне QMessageBox.

Осталось лишь добавить кнопки в заготовленные для этого ячейки таблицы с помощью setIndexWidget():

ViewButtonDemo::ViewButtonDemo( QWidget* parent ) :
    QWidget( parent ),
    ui( new Ui::ViewButtonDemo ) {
    ui->setupUi( this );

    for( int i = 0; i < ui->tableWidget->rowCount(); ++i ) {
        ui->tableWidget->setIndexWidget(
            ui->tableWidget->model()->index( i, COLUMN_ACTION ),
            createButtonWidget()
        );
    }
}

А теперь все вместе

Заголовочный файл viewbuttondemo.h:

#ifndef VIEWBUTTONDEMO_H
#define VIEWBUTTONDEMO_H

#include <QWidget>

namespace Ui {
class ViewButtonDemo;
}

class ViewButtonDemo : public QWidget {
    Q_OBJECT

public:
    explicit ViewButtonDemo( QWidget* parent = 0 );
    ~ViewButtonDemo();

private slots:
    void onBtnClicked();

private:
    QWidget* createButtonWidget() const;

private:
    Ui::ViewButtonDemo* ui;
};

#endif // VIEWBUTTONDEMO_H

Реализация в viewbuttondemo.cpp:

#include "viewbuttondemo.h"
#include "ui_viewbuttondemo.h"

#include <QPushButton>
#include <QMessageBox>
#include <QDebug>

enum {
    COLUMN_LAST_NAME,
    COLUMN_FIRST_NAME,
    COLUMN_MIDDLE_NAME,
    COLUMN_ACTION
};

ViewButtonDemo::ViewButtonDemo( QWidget* parent ) :
    QWidget( parent ),
    ui( new Ui::ViewButtonDemo ) {
    ui->setupUi( this );

    for( int i = 0; i < ui->tableWidget->rowCount(); ++i ) {
        ui->tableWidget->setIndexWidget(
            ui->tableWidget->model()->index( i, COLUMN_ACTION ),
            createButtonWidget()
        );
    }
}

ViewButtonDemo::~ViewButtonDemo() {
    delete ui;
}

void ViewButtonDemo::onBtnClicked() {
    if( QPushButton* btn = qobject_cast< QPushButton* >( sender() ) ) {
        QModelIndex index = ui->tableWidget->indexAt( btn->parentWidget()->pos() );
        qDebug() << index.row() << "x" << index.column();
        QStringList name;
        for( int i = COLUMN_LAST_NAME; i <= COLUMN_MIDDLE_NAME; ++i ) {
            name << ui->tableWidget->model()->data(
                     ui->tableWidget->model()->index( index.row(), i )
                 ).toString();
        }
        QMessageBox::information( this, "The button was clicked", name.join( " " ) );
    }
}

QWidget* ViewButtonDemo::createButtonWidget() const {
    QWidget* wgt = new QWidget;
    QBoxLayout* l = new QHBoxLayout;
    QPushButton* btn = new QPushButton( "Click me!" );
    connect( btn, SIGNAL( clicked( bool ) ), SLOT( onBtnClicked() ) );
    l->setMargin( 0 );
    l->addWidget( btn );
    l->addStretch();
    wgt->setLayout( l );

    return wgt;
}

Исходники

 Скачать пример добавления виджетов в ячейку таблицы QTableWidget

Похожие публикации