How to interact with checkbox actions ? (QTableView with QStandardItemModel)
Asked Answered
W

4

3

I'm using QTableView and QStandardItemModel to show some data.

For each row, there is a column which has a check Box, this check box is inserted by setItem, the code is as follows:

int rowNum;
QStandardItemModel *tableModel;
QStandardItem* __tmpItem = new QStandardItem();

__tmpItem->setCheckable(true);
__tmpItem->setCheckState(Qt::Unchecked);

tableModel->setItem(rowNum,0,__tmpItem);

Now I want to interact with the check box. If a check box changes its state by user (from checked to unchecked or vice versa), I want to do something on the corresponding data row.

I know I can use signal-slot to catch the change of checkbox, but since there are lots of data row, I don't want to connect each row one by one.

Is there anyway to interact with the check action more effectively? Thanks :)

Whimsy answered 7/5, 2010 at 0:27 Comment(0)
H
3

handle the click event, there you will get the modelindex, get the data and modify the same

if you are going to insert more than one text or icon, then you need to set the delegate for your listview

Hedonism answered 7/5, 2010 at 4:14 Comment(1)
Thanks a lot, It works without using QItemDelegate!!! :D I just need to add a slot and everything works find, it' great!!Whimsy
A
4

I don't deal with QTableView+QStandardItemModel, but may be example below will help you:

1). table.h file:

#ifndef TABLE__H
#define TABLE__H

#include <QtGui>

class ItemDelegate : public QItemDelegate
{
public:
    ItemDelegate(QObject *parent = 0)
        : QItemDelegate(parent)
    {
    }
    virtual void drawCheck(QPainter *painter, const QStyleOptionViewItem &option,
        const QRect &, Qt::CheckState state) const
    {
        const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;

        QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
            check(option, option.rect, Qt::Checked).size(),
            QRect(option.rect.x() + textMargin, option.rect.y(),
            option.rect.width() - (textMargin * 2), option.rect.height()));
        QItemDelegate::drawCheck(painter, option, checkRect, state);
    }
    virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
        const QModelIndex &index)
    {
        Q_ASSERT(event);
        Q_ASSERT(model);

        // make sure that the item is checkable
        Qt::ItemFlags flags = model->flags(index);
        if (!(flags & Qt::ItemIsUserCheckable) || !(flags & Qt::ItemIsEnabled))
            return false;
        // make sure that we have a check state
        QVariant value = index.data(Qt::CheckStateRole);
        if (!value.isValid())
            return false;
        // make sure that we have the right event type
        if (event->type() == QEvent::MouseButtonRelease) {
            const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
            QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
                check(option, option.rect, Qt::Checked).size(),
                QRect(option.rect.x() + textMargin, option.rect.y(),
                option.rect.width() - (2 * textMargin), option.rect.height()));
            if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
                return false;
        } else if (event->type() == QEvent::KeyPress) {
            if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
                && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
                return false;
        } else {
            return false;
        }
        Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
            ? Qt::Unchecked : Qt::Checked);

        QMessageBox::information(0,
            QString((state == Qt::Checked) ? "Qt::Checked" : "Qt::Unchecked"),
            QString("[%1/%2]").arg(index.row()).arg(index.column()));

        return model->setData(index, state, Qt::CheckStateRole);
    }
    virtual void drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const
    {
        QItemDelegate::drawFocus(painter, option, option.rect);
    }
};


static int ROWS = 3;
static int COLS = 1;
class Table : public QTableWidget
{
    Q_OBJECT
public:
    Table(QWidget *parent = 0)
        : QTableWidget(ROWS, COLS, parent)
    {
        setItemDelegate(new ItemDelegate(this));
        QTableWidgetItem *item = 0;
        for (int i=0; i<rowCount(); ++i) {
            for (int j=0; j<columnCount(); ++j) {
                setItem(i, j, item = new QTableWidgetItem);
                item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsUserCheckable);
                item->setCheckState((i+j) % 2 == 0 ? Qt::Checked : Qt::Unchecked);
            }
        }
    }
};

#endif

2). main.cpp file:

#include <QApplication>

#include "table.h"

int main(int argc, char **argv)
{
    QApplication a(argc, argv);
    Table w;
    w.show();
    return a.exec();
}

Good luck.

PS: here is the original text.

Armelda answered 7/5, 2010 at 7:29 Comment(2)
Thanks a lot !!! It does works :D~\n However, by this way, every element in the tableview will contain a check box, if I just want the checkbox appears in some specific columns, which part I need to modify ?? Thank you again,, this example is really helpful :DWhimsy
@Claire Huang You may edit Table class to gain ability set checkboxes just in one selected column, example: for (...) for (...) { setItem(...); if (j == mySelectedColumn) item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsUserCheckable); else item->setFlags(Qt::ItemIsEnabled); } ... etc I think something like that. :)Armelda
H
3

handle the click event, there you will get the modelindex, get the data and modify the same

if you are going to insert more than one text or icon, then you need to set the delegate for your listview

Hedonism answered 7/5, 2010 at 4:14 Comment(1)
Thanks a lot, It works without using QItemDelegate!!! :D I just need to add a slot and everything works find, it' great!!Whimsy
B
1

Here is another similar idea of the example suggested by mosg using a QStyleItemDelegate instead. http://developer.qt.nokia.com/faq/answer/how_can_i_align_the_checkboxes_in_a_view

Baffle answered 15/12, 2010 at 15:2 Comment(0)
I
0

Use on clicked slot and index.data(Qt::CheckStateRole) :

void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
    if(index.column() == 2){
        if(index.data(Qt::CheckStateRole) == Qt::Checked){
             //your code 
        }else if(index.data(Qt::CheckStateRole) == Qt::Unchecked){
             //your code
        }
    }
    //get other infos
    QVariant value = index.sibling(index.row(),0).data();
    QString selectedMessageName = value.toString();
}
Ichnology answered 1/7, 2021 at 7:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.