c++qtqtableviewqtablewidgetitem

Show image in a column of QTableView from QSqlTableModel


I'm curious about how I can display an image from my database in a QTableView.

Is there something like QTableWidgetItem that I am able to use it in QTableView?

I use QSqlTableModel.


Solution

  • A rough idea is to use QStandardItem::setData to set a QPixmap(transformed into QVariant) on it, then you can set the QStandardItem on the QStandardItemModel.

    Sequence: QImage--->QPixmap--->QVariant--->QStandardItem--->QStandardItemModel

    For example:

    QStandardItemModel *model = new QStandardItemModel;
    QImage image(":/cat/lovers/own/myCat.jpg");
    QStandardItem *item = new QStandardItem();
    item->setData(QVariant(QPixmap::fromImage(image)), Qt::DecorationRole);
    model->setItem(0, 0, item);
    ui->tableView->setModel(model);
    

    enter image description here

    You will have to resize images or cell size, depends on what you need.


    [Edit]

    If you are using QSqlTableModel, just keep using it. All we need to do is make those path strings into QPixmap and set the item role to be Qt::DecorationRole in that column.

    As the document says:

    Each item has a number of data elements associated with it and they can be retrieved by specifying a role (see Qt::ItemDataRole) to the model's data() function.

    To do this, the concept is simple: provide QTableView with QVariant of QPixmap as QTableView render them according to Qt::DecorationRole.

    You may subclass QSqlTableModel and reimplement the virtual function QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) and make the image column return the QPixmap as QVariant, with the decoration role. So do something like this:

    QVariant CustomSqlTableModel::data(const QModelIndex &idx, int role = Qt::DisplayRole) const
    {
         if (idx.column() == imageColumn) {
             QString imgFile = QSqlTableModel::data(idx, Qt::DisplayRole); // get path string
    
            if (role == Qt::DisplayRole) 
                return QString(); // return the path string for display role
    
            QImage image(imgFile);
            /* some modification to the image, maybe */
    
            QPixmap pixmap(imgFile);
            if (role == Qt::DecorationRole)
                return pixmap;   // return QPixmap for decoration role
    
            if (role == Qt::SizeHintRole)
                return pixmap.size(); // in case need the image size
    
         }
         return QSqlTableModel::data( idx, role ); // use original data() outside the imageColumn
    }
    

    Besides, you can also try subclassing QStyledItemDelegate and reimplement paint() function to customize your own delegate, but that will require a more complicated work. An example using delegate can be found here. You can paint whatever you want with delegate, even a button.

    *Sorry the code is not tested, as I don't have a database on hand.