Qt-ohjelmointi
QTableView ja QVector

QTableView on Qt:n komponentti, jolla voidaan näyttää taulukkomuotoista dataa. Se toimii Model-View arkkitehtuurin mukaisesti: data on mallissa (model) ja näkymä (view) renderöi sen käyttäjälle.

Tässä esimerkissä käytämme aiemmissa esimerkeissä luotua Book-luokkaa ja QVector<Book>-listaa. Jos et ole vielä luonut Book-luokkaa, katso HTTP-esimerkit osiosta "JSON-datan käsittely C++-olioiden avulla".

QVector:n näyttäminen QTableView:ssä

Oletetaan että olet luonut QVector:in ja lisännyt siihen kirjoja (esim. HTTP GET -pyynnön vastauksesta):

QVector<Book> bookList;  // Jäsenmuuttuja luokassa

Vaihe 1: Lisää QTableView UI:hin

  1. Avaa mainwindow.ui Qt Designer:ssa
  2. Vedä Table View lomakkeelle (Widget Box:sta)
  3. Nimeä se tableBooks

Vaihe 2: Luo Model ja täytä data

Lisää mainwindow.h tiedostoon:

#include <QStandardItemModel>

Kirjoita funktio joka täyttää taulukon (esim. HTTP-vastauksen käsittelyn jälkeen):

void MainWindow::displayBooks()
{
    // Luo model: rivit, sarakkeet, parent
    auto *tableModel = new QStandardItemModel(bookList.size(), 3, this);

    // Aseta sarakkeiden otsikot
    tableModel->setHorizontalHeaderLabels({ tr("ID"), tr("Nimi"), tr("Kirjoittaja") });

    // Täytä taulukko bookList:stä
    for (int row = 0; row < bookList.size(); ++row) {
        const Book &book = bookList[row];
        tableModel->setItem(row, 0, new QStandardItem(QString::number(book.id)));
        tableModel->setItem(row, 1, new QStandardItem(book.name));
        tableModel->setItem(row, 2, new QStandardItem(book.author));
    }

    // Aseta model tableView:lle
    ui->tableBooks->setModel(tableModel);

    // Piilota rivinumerot vasemmalta (optional)
    ui->tableBooks->verticalHeader()->setVisible(false);

    // Sovita sarakkeiden leveys sisällön mukaan
    ui->tableBooks->resizeColumnsToContents();
}
💡 Selitys:
  • QStandardItemModel(rows, columns, parent) - Luo model annetulla määrällä rivejä ja sarakkeita
  • setHorizontalHeaderLabels() - Asettaa sarakkeiden otsikot
  • setItem(row, col, item) - Asettaa yksittäisen solun arvon
  • setModel() - Kytkee modelin tableView:lle
Valitun rivin lukeminen

Kun käyttäjä klikkaa taulukkoa, voit lukea valitun solun arvon seuraavasti:

Vaihe 1: Aseta taulukon valinta-asetukset

  1. Valitse tableBooks Qt Designer:ssa
  2. Property Editor:ssa aseta:
    • selectionMode = SingleSelection (vain yksi valinta kerrallaan)
    • selectionBehavior = SelectRows (valitsee koko rivin) TAI SelectItems (valitsee yksittäisen solun)
⚙️ Valinta-asetukset:
SelectRows Valitsee koko rivin kun solua klikataan
SelectItems Valitsee vain yksittäisen solun

Vaihe 2: Kytkee clicked-signaali slottiin

Lisää mainwindow.h tiedostoon:

private slots:
    void on_tableBooks_clicked(const QModelIndex &index);

Lisää mainwindow.cpp tiedostoon:

void MainWindow::on_tableBooks_clicked(const QModelIndex &index)
{
    // Lue valitun solun arvo
    QVariant value = index.sibling(index.row(), index.column()).data();
    QString selectedValue = value.toString();

    qDebug() << "Klikattu rivi:" << index.row()
             << "sarake:" << index.column()
             << "arvo:" << selectedValue;

    // Näytä esim. labelissa
    ui->labelResult->setText("Valittu: " + selectedValue);

    // Jos haluat lukea koko rivin tiedot:
    int row = index.row();
    QString id = index.sibling(row, 0).data().toString();
    QString name = index.sibling(row, 1).data().toString();
    QString author = index.sibling(row, 2).data().toString();

    qDebug() << "Koko rivi - ID:" << id << "Nimi:" << name << "Tekijä:" << author;
}
💡 QModelIndex selitys:
  • index.row() - Palauttaa rivinumeron (alkaa 0:sta)
  • index.column() - Palauttaa sarakenumeron (alkaa 0:sta)
  • index.data() - Palauttaa solun arvon QVariant-tyyppisenä
  • index.sibling(row, col) - Palauttaa saman taulukon toisen solun indeksin
Täydellinen esimerkki: HTTP GET → QTableView

Tässä täydellinen esimerkki, joka hakee kirjat HTTP:llä ja näyttää ne taulukossa:

// mainwindow.h
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_btnFetchBooks_clicked();
    void on_tableBooks_clicked(const QModelIndex &index);

private:
    Ui::MainWindow *ui;
    QNetworkAccessManager *manager;
    QVector<Book> bookList;

    void displayBooks();  // Apufunktio taulukon täyttämiseen
};
// mainwindow.cpp
void MainWindow::on_btnFetchBooks_clicked()
{
    QString url = "http://localhost:3000/books";
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    QNetworkReply *reply = manager->get(request);
    connect(reply, &QNetworkReply::finished, this, [reply, this]() {
        if (reply->error() == QNetworkReply::NoError) {
            QByteArray data = reply->readAll();
            QJsonDocument doc = QJsonDocument::fromJson(data);
            QJsonArray array = doc.array();

            // Tyhjennä lista ja täytä uusilla kirjoilla
            bookList.clear();
            for (const QJsonValue &value : array) {
                if (value.isObject()) {
                    Book book = Book::mapJson(value.toObject());
                    bookList.append(book);
                }
            }

            // Näytä kirjat taulukossa
            displayBooks();

        } else {
            qWarning() << "Virhe:" << reply->errorString();
        }
        reply->deleteLater();
    });
}

void MainWindow::displayBooks()
{
    auto *tableModel = new QStandardItemModel(bookList.size(), 3, this);
    tableModel->setHorizontalHeaderLabels({ tr("ID"), tr("Nimi"), tr("Kirjoittaja") });

    for (int row = 0; row < bookList.size(); ++row) {
        const Book &book = bookList[row];
        tableModel->setItem(row, 0, new QStandardItem(QString::number(book.id)));
        tableModel->setItem(row, 1, new QStandardItem(book.name));
        tableModel->setItem(row, 2, new QStandardItem(book.author));
    }

    ui->tableBooks->setModel(tableModel);
    ui->tableBooks->verticalHeader()->setVisible(false);
    ui->tableBooks->resizeColumnsToContents();
}

void MainWindow::on_tableBooks_clicked(const QModelIndex &index)
{
    int row = index.row();

    // Lue koko rivin tiedot
    QString id = index.sibling(row, 0).data().toString();
    QString name = index.sibling(row, 1).data().toString();
    QString author = index.sibling(row, 2).data().toString();

    qDebug() << "Valittu kirja - ID:" << id << "Nimi:" << name << "Tekijä:" << author;

    // Voit käyttää bookList[row] suoraan jos tarvitset koko Book-olion
    const Book &selectedBook = bookList[row];
    // ... tee jotain valitulla kirjalla
}
Video-opas

Alla video joka demonstroi QTableView:n käyttöä käytännössä:

Yhteenveto

🎯 Keskeiset asiat QTableView:stä:

  1. Model-View arkkitehtuuri - Data (model) erillään näkymästä (view)
  2. QStandardItemModel - Helpoin tapa luoda model taulukkodatalle
  3. setModel() - Kytkee modelin tableView:lle
  4. QModelIndex - Käytetään solujen lukemiseen ja navigointiin
  5. clicked-signaali - Laukeaa kun käyttäjä klikkaa taulukkoa
  6. QVector - Säilytä alkuperäinen data listassa helpottaaksesi käsittelyä



Toggle Menu