-->

A checkbox only column in QTableView

2019-02-19 05:42发布

问题:

I have a table in Sqlite database which I display using QTableview and QSqlQueryModel. The first column needs to have a header which is a checkbox and all the items in the column need to be checkboxes too. I have implemented the first column header as a checkbox and it works perfectly.

Since the checkboxes in the column need to be centered, I used a delegate to paint it. I have painted checkboxes using the following code, but they cannot be checked or unchecked. I do not know how to implement that.

static QRect CheckBoxRect(const QStyleOptionViewItem &view_item_style_options) {
   QStyleOptionButton check_box_style_option;
   QRect check_box_rect = QApplication::style()->subElementRect(
   QStyle::SE_CheckBoxIndicator,
   &check_box_style_option);
   QPoint check_box_point(view_item_style_options.rect.x() +
                     view_item_style_options.rect.width() / 2 -
                     check_box_rect.width() / 2,
                     view_item_style_options.rect.y() +
                     view_item_style_options.rect.height() / 2 -
                     check_box_rect.height() / 2);
   return QRect(check_box_point, check_box_rect.size());
}


CheckBoxDelegate::CheckBoxDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{

}

void CheckBoxDelegate::paint(QPainter *painter,
                         const QStyleOptionViewItem &option,
                         const QModelIndex &index) const {
  bool checked = index.model()->data(index, Qt::DisplayRole).toBool();

  QStyleOptionButton check_box_style_option;
  check_box_style_option.state |= QStyle::State_Enabled;
  if (checked) {
    check_box_style_option.state |= QStyle::State_On;
  } else {
    check_box_style_option.state |= QStyle::State_Off;
  }
  check_box_style_option.rect = CheckBoxRect(option);

  QApplication::style()->drawControl(QStyle::CE_CheckBox,
                                 &check_box_style_option,
                                 painter);
}

The following code shows how I use the QSqlQueryModel for QTableView to load the table from the database.

//Load the tableview with the database table
QSqlQueryModel model = new QSqlQueryModel();

//Initializaton of the query
QSqlQuery *query = new QSqlQuery(dbm->db);

query->prepare("SELECT * FROM UserData");

if(query->exec())
{
    model->setQuery(*query);
    ui->tableView->setModel(model);

    //The header delegate to paint a checkbox on the header
    HeaderDelegate *myHeader = new HeaderDelegate(Qt::Horizontal, ui->tableView);
    ui->tableView->setHorizontalHeader(myHeader);

    int RowCount = model->rowCount();

    qDebug() << RowCount;

    CheckBoxDelegate *myCheckBoxDelegate = new CheckBoxDelegate();

    ui->tableView->setItemDelegateForColumn(0,myCheckBoxDelegate);

    ui->tableView->horizontalHeader()->setClickable(true);

    ui->tableView->setSortingEnabled(true);
}

Could you please tell me how to go about it? Any help is appreciated.

回答1:

I have found this solution that does not uses delegates or anything like that. You will still have a problem centering the checkbox. That is up to you.

The next code snippet will make a column filled with checkboxes:

yourSqlQueryModel = new QSqlQueryModel();
yourTableView = new QtableView();
        yourSqlQueryModel ->setQuery(yourQuery);
        yourSqlQueryModel ->insertColumn(0);//Insert column for checkboxes
        ui->yourTableView ->setModel(yourSqlQueryModel );
        ui->yourTableView ->resizeColumnsToContents();

        int p;
        for(p = 0;p<yourSqlQueryModel ->rowCount();p++)
        {
            ui->yourTableView ->setIndexWidget(yourSqlQueryModel ->index(p,0),new QCheckBox());
        }

Please read carefully, the most important here is the setIndexWidget method, which allows you to insert the widget into the created column.



回答2:

The easiest way for displaying checkable items is using QStandardItemModel as QStandardItem can be set checkable. It is good for prototyping. The drawback however is, you had to fill the model manually.