c++ 带标签的Qt表视图复选框

disho6za  于 2023-01-10  发布在  其他
关注(0)|答案(1)|浏览(141)

我需要在表格视图单元格中显示带有标签的复选框,用当前代码它显示复选框状态而不是标签。我已经创建了自定义委托和模型。下面是完成的代码。
The result I got look like this

表格视图委托.h

#include <QObject>
#include <QStyledItemDelegate>
#include "QSpinBox"
#include "QDoubleSpinBox"
#include "QCheckBox"
#include "QApplication"
#include "QStyle"
class table_view_delegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
     table_view_delegate(QObject *parent = nullptr);
     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
     void setEditorData(QWidget *editor, const QModelIndex &index) const override;
     void setModelData(QWidget *editor, QAbstractItemModel *model,  const QModelIndex &index) const override;
     void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;

signals:

};

表格视图委托.cpp

#include "table_view_delegate.h"
#include "QMouseEvent"
#include "QAbstractItemModel"
#include "QCheckBox"
#include "QSpinBox"

table_view_delegate::table_view_delegate(QObject *parent)  : QStyledItemDelegate{parent}
{

}

QWidget *table_view_delegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option , const QModelIndex & index ) const
{
    int c= index.column();
    if(c == 0 ){
         QCheckBox* check = new QCheckBox("Lable",parent);
         return check;
    }
    else  if(c == 1 ){
        QSpinBox *editor = new QSpinBox(parent);
        return editor;
    }
    else {
        return NULL;
    }

}

void table_view_delegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    int c= index.column();
   if(c == 0 ){
        int value = index.model()->data(index, Qt::CheckStateRole).toInt();
        QCheckBox* check = static_cast<QCheckBox*>(editor);
        if(value==0)
            check->setChecked(false);
        else
            check->setChecked(true);

        check->setText("test");
    }
    else if(c==1){
       QString val_str = index.model()->data(index, Qt::EditRole).toString();
       float value = val_str.toFloat();
       QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
       spinBox->setValue(value);
   }

}

void table_view_delegate::setModelData(QWidget *editor, QAbstractItemModel *model,  const QModelIndex &index) const
{
    int c= index.column();
    if(c == 0 ){
        QCheckBox* check = static_cast<QCheckBox*>(editor);
        check->setText("test");
        QString value =QString::number(check->isChecked());//check->isChecked();
        model->setData(index, value, Qt::EditRole);

    }
    else if(c ==1){
        QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
        spinBox->interpretText();
        QString value = QString::number(spinBox->value(), 'f', 2);
        model->setData(index, value, Qt::EditRole);
    }

}

void table_view_delegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,  const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

void table_view_delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{

    QStyledItemDelegate::paint(painter, option, index);
}

表格视图模型.h

#include <QObject>
#include <QAbstractTableModel>

class table_view_model : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit table_view_model(QObject *parent = nullptr);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    void setDataList(QList <QStringList> alog_data_list);
    QVariant headerData(int section, Qt::Orientation ,   int role) const override;

private:
    QList <QStringList> model_data_list;
    int col_count = 3;
    QStringList header={"CheckBox","SpinBox","String"};

signals:

};

表格视图模型.cpp

#include "table_view_model.h"

table_view_model::table_view_model(QObject *parent) : QAbstractTableModel{parent}
{

}

int table_view_model::rowCount(const QModelIndex & /*parent*/) const
{
   return model_data_list.length();
}

int table_view_model::columnCount(const QModelIndex & /*parent*/) const
{
    return col_count;
}

QVariant table_view_model::data(const QModelIndex &index, int role) const
{
    int r = index.row();
    int c = index.column();

    if(model_data_list.length()==0)
           return QVariant();

     if (!index.isValid())
           return QVariant();

     if( c==0){
         if (role == Qt::CheckStateRole&& c==0 ){
            int checked = model_data_list[r][c].toInt();
            if (checked)
                return Qt::Checked;
            else
               return Qt::Unchecked;
        }
        else if(role == Qt::EditRole){
              return  model_data_list[r][c];
         }
        else if (role == Qt::DisplayRole)
              return  model_data_list[r][c];

     }
     else{
       if (role == Qt::DisplayRole)
            return  model_data_list[r][c];
     }

      return QVariant();

}

bool table_view_model::setData(const QModelIndex &index, const QVariant &value, int role)
{
     int c=index.column();
     if(  c==1){
            if (role == Qt::EditRole) {
                if (!checkIndex(index))
                    return false;
                return true;
            }

    }
    else if (role == Qt::CheckStateRole&&c==0)
    {

         model_data_list[index.row()][index.column()] = value.toString();

         if ((Qt::CheckState)value.toInt() == Qt::Checked)
         {
             //user has checked item
             return true;
         }
         else
         {
             //user has unchecked item
             return true;
         }

    }
    return false;
}

void table_view_model::setDataList(QList <QStringList> model_data_listTmp){
    table_view_model::beginResetModel();

    model_data_list.clear();
    for(int i=0;i<model_data_listTmp.length();i++){
        model_data_list.push_back(model_data_listTmp[i]);
    }

    table_view_model::endResetModel();
}

Qt::ItemFlags table_view_model::flags(const QModelIndex &index) const
{
    int c=index.column();
    //Editable column
    if(c==1)
        return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
    else if(c==0)
       return Qt::ItemIsUserCheckable | QAbstractTableModel::flags(index);
    else
        return QAbstractTableModel::flags(index);
}

QVariant table_view_model::headerData(int section, Qt::Orientation orientation,   int role) const
{
    if (role != Qt::DisplayRole){
        return QVariant();
    }
    if (orientation == Qt::Horizontal)
            return header.at(section);
        else
            return QString::number(section);

}

在MainWindow.cpp中,我初始化表格视图,如下所示。

table_view_model *model = new table_view_model();
   //QSqlQueryModel *algo_model  = db_conn->getAlgoTableData();
    ui->tableView->setModel(model);
    ui->tableView->horizontalHeader()->setStretchLastSection(true);
    table_view_delegate *delgate = new table_view_delegate() ;
    ui->tableView->setItemDelegate(delgate);

    QList <QStringList> data_list;
    QStringList r1;
    r1.append("0");
    r1.append("100");
    r1.append("Str1");
    data_list.append(r1);

    QStringList r2;
    r2.append("1");
    r2.append("200");
    r2.append("Str2");
    data_list.append(r2);

     model->setDataList(data_list);
s6fujrry

s6fujrry1#

你对角色有很多困惑。
你的模型似乎需要3个角色。用我的话简单描述一下。一定要检查文档中我没有描述的角色。

  • Qt::DisplayRole:屏幕上显示的内容,例如带千位分隔符的格式化数字(实际类型QString)。
  • Qt::EditRole:显示的底层数据,例如模型的实际编号。这是您希望在代理编辑器中使用的数据。但是,在许多情况下,Qt::EditRole的数据与Qt::DisplayRole的数据相同。

同样,你可以选择实现一个接受在Qt::EditRoleQt::DisplayRole中被编辑的模型,区别实际上是关于屏幕显示的格式。

  • Qt::CheckStateRole:索引处的Checkstate(类型Qt::CheckState)。默认情况下,它为空值QVariant,表示视图将不显示复选框。

但是,您可以实现一个在所有情况下都显示复选框的委托(或者相反,让一个委托不显示复选框,即使应该有一个复选框)
在您的模型中,所有内容都存储在QList <QStringList> model_data_list;
data方法中的样品:

if( c==0){
     if (role == Qt::CheckStateRole && c==0){
        int checked = model_data_list[r][c].toInt(); //here, used for Qt::CheckStateRole
        [...]
    }
    else if(role == Qt::EditRole){
          return  model_data_list[r][c]; //here, used for Qt::EditRole
     }
    else if (role == Qt::DisplayRole)
          return  model_data_list[r][c]; //here, used for Qt::DisplayRole

 }

那么你不应该对显示的文本和检查状态相同感到惊讶。你必须在角色之间创建超级清晰的边界,以免遇到这种混乱。
一个简单的解决方案是在类中添加一个新成员来存储检查状态,然后在datasetData方法中使用它,当你使用它时,改变另一个成员的类型,没有必要在QStringQVariant之间不断地转换。
在标题中:

QList <QVariantList> model_data_list; //QVariant is more suitable than QString to store your model's data.
QList<Qt::CheckState> model_checkstate_list; //1-dimensional list as only column 0 has checkstates.

经过一些认真的重构,源文件变成了:

QVariant table_view_model::data(const QModelIndex &index, int role) const {
    if (!index.isValid())
        return QVariant();

    //Try to use auto to get the row and column of index.
    //With any luck, Qt will some day change the return value to be qsizetype of similar.
    //auto will make sure you benefit the change when it happens.
    auto r = index.row(), c = index.column();

    switch (role) {
    case Qt::CheckStateRole: {
        if (c == 0)
            return model_checkstate_list[r];
        else
            return QVariant();
    }
    case Qt::DisplayRole: //We treat Display and Edit roles identically.
    case Qt::EditRole: return value;
    default: return QVariant();
    }
}

bool table_view_model::setData(const QModelIndex &index, const QVariant &value, int role) {
    if (!index.isValid())
        return QVariant();

    auto r = index.row(), c = index.column();
    switch (role) {
    case Qt::CheckStateRole: {
        if (c == 0) {
            model_checkstate_list[r] = value.value<Qt::CheckState>();
            return true;
        }
        else
            return false;
    }
    case Qt::DisplayRole: //We treat Display and Edit roles identically.
    case Qt::EditRole: {
        model_data_list[r][c] = value;
        return true;
    }
    default: return false;
    }
}

我不打算向代表发表讲话,因为这不是导致您的显示问题的原因,在我在评论中指出这一点之后,我假设您已经更正了setModelData,但我重申,您应该认真考虑为视图的每一列使用不同的委托。这将删除所有if (c == 0),并允许在视图/中使用委托。column 0中没有复选框的型号。

相关问题