О таблицах в Qt мы уже говорили, когда рассматривали концепцию Модель-Представление в Qt и помещали QProgressBar в QTableView. Теперь убедимся, что добавлять изображения в Qt-таблицы еще проще.
Подготовительный этап
Создадим каркас приложения, состоящего из таблицы QTableWidget и простой командной ссылки. Начинаем с заголовочного файла imagetableviewdemowidget.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#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..., размещенную под таблицей.
Реализация вставки изображения в таблицу
Переходим к основному блюду. Реализация оставленной нами функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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():
1 2 3 4 5 6 7 8 9 10 11 12 |
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. В этом случае размер изображений контролируется централизовано на уровне всей таблицы.