IT Notes

Изображения в таблице Qt

О таблицах в Qt мы уже говорили, когда рассматривали концепцию Модель-Представление в Qt и помещали QProgressBar в QTableView. Теперь убедимся, что добавлять изображения в Qt-таблицы еще проще.

Вот что у нас получится:

qt-table-image-thumbnail

Подготовительный этап

Создадим каркас приложения, состоящего из таблицы QTableWidget и простой командной ссылки. Начинаем с заголовочного файла imagetableviewdemowidget.h:

#ifndef IMAGETABLEVIEWDEMOWIDGET_H
#define IMAGETABLEVIEWDEMOWIDGET_H

#include <QWidget>

class QTableWidget;

class ImageTableViewDemoWidget : public QWidget {
    Q_OBJECT

public:
    ImageTableViewDemoWidget( QWidget* parent = 0 );
    ~ImageTableViewDemoWidget();

private slots:
    void onLinkActivated( const QString& lnk );

private:
    QTableWidget* m_table;
};

#endif // IMAGETABLEVIEWDEMOWIDGET_H

А теперь часть реализации imagetableviewdemowidget.cpp:

#include "imagetableviewdemowidget.h"

#include <QTableWidget>
#include <QBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QFileDialog>

static const QStringList COLUMN_LABELS = QStringList() << "Image Name" << "Image";
static const int IMAGE_VMARGIN = 10;

ImageTableViewDemoWidget::ImageTableViewDemoWidget( QWidget* parent )
    : QWidget( parent ) {
    QBoxLayout* layout = new QVBoxLayout;
    layout->addWidget( m_table = new QTableWidget );
    m_table->setColumnCount( COLUMN_LABELS.size() );
    m_table->setHorizontalHeaderLabels( COLUMN_LABELS );
    m_table->setFocusPolicy( Qt::NoFocus );
    m_table->setSelectionBehavior( QAbstractItemView::SelectRows );
    m_table->horizontalHeader()->setStretchLastSection( true );

    QLabel* lbl = new QLabel( "<a href='#load'>Load Image…</a>" );
    connect( lbl, SIGNAL( linkActivated( QString ) ), SLOT( onLinkActivated( QString ) ) );
    lbl->setAlignment( Qt::AlignRight );
    layout->addWidget( lbl );

    setLayout( layout );
}

ImageTableViewDemoWidget::~ImageTableViewDemoWidget() {
}

void ImageTableViewDemoWidget::onLinkActivated( const QString& lnk ) {
    // До этой функции скоро дойдем…
}

Наша таблица будет включать два столбца: имя файла и изображение. Добавление изображения будет происходить после нажатия на гиперссылку Load Image…, размещенную под таблицей.

Реализация вставки изображения в таблицу

Переходим к основному блюду. Реализация оставленной нами функции:

void ImageTableViewDemoWidget::onLinkActivated( const QString& lnk ) {
    if( lnk == "#load" ) {
        QString fileName = QFileDialog::getOpenFileName(
            this,
            "Load Image",
            QString(),
            "Images (*.jpg *.png *.bmp)"
        );

        QPixmap pix;
        if( pix.load( fileName ) ) {
            int row = m_table->rowCount();
            m_table->insertRow( row );
            QTableWidgetItem* item = new QTableWidgetItem( QFileInfo( fileName ).baseName() );
            item->setFlags( item->flags() ^ Qt::ItemIsEditable );
            m_table->setItem( row, 0, item );

            item = new QTableWidgetItem;
            item->setData( Qt::DecorationRole, pix );
            item->setFlags( item->flags() ^ Qt::ItemIsEditable );
            m_table->setItem( row, 1, item );
            m_table->setRowHeight( row, pix.height() + IMAGE_VMARGIN );
        }
    } else {
        // Unexpected
    }
}

Вставка картинки происходит путем добавления элемента QTableWidgetItem с ролью Qt::DecorationRole. По умолчанию высота строки не подстраивается под размер изображения, поэтому приходится менять ее вручную. Обратите внимание, что для этого мы используем заготовленную константу IMAGE_VMARGIN.

Если требуется использовать архитектуру Модель-Представление, то реализация отличается не намного. В этом случае достаточно организовать корректную обработку запроса данных Модели в перегруженной функции-члене data():

QVariant ImageModel::data( const QModelIndex& index, int role ) const {
    if( index.isValid() && index.row() < rowCount() ) {
        if( role == Qt::DecorationRole && index.column() == 1 ) {
            // Возвращаем изображение для нужного ряда:
            return getPixForRow( index.row() );
        } else {
            // …
        }
    }

    return QVariant();
}

Замечание: Если изображение слишком большое, то оно может некорректно отображаться в ячейке таблицы. Поэтому в реальном приложении необходимо четко контролировать его размер. В таблицу лучше помещать уменьшенную копию исходной картинки - thumbnail. Достигнуть этого можно разными способами. Например, используя QTableWidgetItem с иконкой QIcon. В этом случае размер изображений контролируется централизовано на уровне всей таблицы.

Исходники

 Скачать исходники с примером использования изображений в таблицах Qt

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