我想实现一个QTableView
使用 QAbstractModel 创建的用户可编辑复选框。我可以分配一个选中和未选中的复选框,但无法使其可编辑。标志设置为QItemIsUserCheckable
。
4 回答
setData()
您可以通过像这样实现模型的方法来轻松地做到这一点:
bool yourModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
if (role == Qt::CheckStateRole)
{
if ((Qt::CheckState)value.toInt() == Qt::Checked)
{
//user has checked item
return true;
}
else
{
//user has unchecked item
return true;
}
}
return false;
}
并且不要忘记模型的data()
方法:
QVariant ProxyModelSubobjects::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::CheckStateRole && index.column() == COLUMN_WITH_CHECKBOX)
{
//return Qt::Checked or Qt::Unchecked here
}
//...
}
第一件事。
仅当您创建树模型时,QAbstractItemModel 才是模型的不错选择,而在大多数其他情况下,最好使用 QAbstractTableModel 甚至 QAbstractListModel,因为它们为您节省了实现特定虚拟方法的工作模型类型(表格或列表)。
这些模型的文档非常详尽,并告诉您要实现哪些功能以使模型可编辑。对于这个简短的解释,我将使用表格模型。主要功能有:
- QVariant data(index, role) : 返回当前索引 & 角色的 QVariant 值
- bool setData(index, value, role) : 返回传递的值是否写入索引
- QItemFlags flags() : 返回传递索引的 QItemFlags 值
对于这种情况,我将忽略其他人。
所有 Qt 视图都以相同的方式工作 - 当它们显示时,它们会根据 flags() 为其索引返回的值使用模型中的数据填充它们自己,它们的元素是可编辑/可选择的等。当它们被编辑时,值通过 setData() 函数传递给模型。
您似乎缺少的是 flags() 方法中的 Qt::ItemIsEditable 标志。
您要实现的是自定义委托。查看QAbstractItemDelegate类以获取有关实际实现的更多信息。
在我浏览了一堆论坛试图弄清楚如何做到这一点但没有任何效果之后,我最终在 http://doc.qt.io/qt-4.8/modelview.html中找到了一个注释
在 2.2 使用角色扩展只读示例的末尾,文本注释“现在我们需要确定使用分离模型如何影响应用程序的性能,所以让我们跟踪视图调用 data() 方法的频率。为了跟踪如何经常视图调用模型,我们在data()方法中放了一个debug语句,它会记录到错误输出流中。在我们的小例子中,data()会被调用42次。每次将光标悬停在字段,data() 将被再次调用 - 每个单元格 7 次。这就是为什么在调用 data() 并缓存昂贵的查找操作时确保您的数据可用很重要的原因。
这让我意识到“yourModal::data()”是连续调用的,但是,为了额外的更新,我在设置中添加了一个时间来运行检查选择。我的有点棘手,因为我实际上是从我的 MainWindow 打开一个 groupBox 弹出窗口,享受额外的代码。
所以基本上这是我想出的代码,它运行得很好:
#ifndef ADD_PARAMETERS_GROUPBOX
#define ADD_PARAMETERS_GROUPBOX
#include <QGroupBox>
#include <QAbstractTableModel>
namespace Ui {
class AdditionalParameters;
}
class AdditionalParameters : public QGroupBox
{
Q_OBJECT
public:
explicit AdditionalParameters(QWidget *parent = 0);
~AdditionalParameters();
private:
Ui::AdditionalParameters *ui;
signals:
void stateChanged(int state);
private slots:
void PARAMTER_SEL(QModelIndex box);
};
#endif // ADD_PARAMETERS_GROUPBOX
#ifndef ADD_PARAMETERS_SELECTION_TABLE
#define ADD_PARAMETERS_SELECTION_TABLE
#include <QAbstractTableModel>
#include <QString>
class MainWindow;
const int ROWS = 63;
const int COLS = 5;
class ParametersTable : public QAbstractTableModel
{
Q_OBJECT
public:
ParametersTable(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const ;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
//bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::CheckStateRole);
Qt::ItemFlags flags(const QModelIndex & index) const;
private:
//QString m_gridData[ROWS][COLS]; //holds text entered into QTableView
//bool m_gridData[ROWS][COLS]; //holds state entered into QTableView
signals:
void editCompleted(const QString &);
void stateChanged(int state);
private slots:
//void updateTable();
//void PARAMTER_SEL(QModelIndex box);
};
#include "add_parameters_groupbox.h"
#include "ui_add_parameters_groupbox.h"
#include "add_parameters_selection_table.h"
#include <QTableView>
#include <QAbstractTableModel>
#include <QList>
#include <QTimer>
#include <QDebug>
#include <qcheckbox.h>
QStringList paraHold;
QStringList paraSymbols;
QString Parameters[500][5];
QAbstractTableModel *paraTable;
QItemSelectionModel *selectionModel;
bool m_gridData[ROWS][COLS];
AdditionalParameters::AdditionalParameters(QWidget *parent) :
QGroupBox(parent),
ui(new Ui::AdditionalParameters)
{
ui->setupUi(this);
paraTable = new ParametersTable(this);
ui->AddPara_tableView->setModel(paraTable);
connect(ui->AddPara_tableView,SIGNAL(clicked(QModelIndex)),
this, SLOT(PARAMTER_SEL(QModelIndex)));
paraHold
<< "60 xxxx"
<< "lines"
<< "of strings";
paraSymbols
<< "60+/-"
<< "lines"
<< "of strings";
for(int i = 0; i<(paraHold.size()); i++)
{
Parameters[i][0] = paraHold.at(i);
m_gridData[i][0] = false;
// qDebug() << "m_gridData[i][0]:" << m_gridData[i][0];
if((!Parameters[i][0].contains("T",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("FET",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("NT",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("LT",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("TAT",Qt::CaseInsensitive))){
Parameters[i][1] = "Current/Voltage";
m_gridData[i][1] = true;
// qDebug() << "m_gridData[i][1]:" << m_gridData[i][1];
}
if(!((Parameters[i][0].contains("V",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("I_",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("cell",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("FET",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("NT",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("LT",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("_SCD",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("_CFA",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("_OWD",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("_CHG",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("_DSG",Qt::CaseInsensitive))
|| (Parameters[i][0].contains("OC",Qt::CaseInsensitive)))){
Parameters[i][2] = "Tempurature";
m_gridData[i][2] = true;
// qDebug() << "m_gridData[i][2]:" << m_gridData[i][2];
}
Parameters[i][3] = paraSymbols.at(i);
}
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), ui->AddPara_tableView, SLOT(doItemsLayout()));
// connect(timer, SIGNAL(timeout()), ui->AddPara_tableView, SLOT(resizeColumnsToContents()));
// QTimer::singleShot(20000, ui->AddPara_tableView, SLOT(doItemsLayout()));
QTimer::singleShot(1000, ui->AddPara_tableView, SLOT(resizeColumnsToContents()));
timer->start(1000);
}
AdditionalParameters::~AdditionalParameters()
{
delete ui;
}
ParametersTable::ParametersTable(QObject *parent)
:QAbstractTableModel(parent)
{
}
int ParametersTable::rowCount(const QModelIndex & /*parent*/) const
{
//int pararow = Parameters.size();
//return pararow;
return 62;
}
int ParametersTable::columnCount(const QModelIndex & /*parent*/) const
{
//int paracol;
return 5;
}
QVariant ParametersTable::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole)
{
if (orientation == Qt::Horizontal) {
switch (section)
{
case 0:
return QString("Parameter");
case 1:
return QString("Current/Voltage Chart");
case 2:
return QString("Tempurature Chart");
case 3:
return QString("Symbol");
case 4:
return QString("Color");
}
}
}
return QVariant();
}
QVariant ParametersTable::data(const QModelIndex &index, int role) const
{
int row = index.row();
int col = index.column();
switch(role){
case Qt::DisplayRole:
return QString("%1")
.arg(Parameters[row][col]);
break;
case Qt::FontRole:
if (Parameters[row][col] != "_")
{
QFont boldFont;
boldFont.setBold(true);
return boldFont;
}
break;
case Qt::BackgroundRole:
if(col == 4)
{
if (Parameters[row][0].contains("cell1",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::blue);
return redBackground;
}
if (Parameters[row][0].contains("cell2",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::cyan);
return redBackground;
}
if (Parameters[row][0].contains("cell3",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::magenta);
return redBackground;
}
if (Parameters[row][0].contains("cell4",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::yellow);
return redBackground;
}
if (Parameters[row][0].contains("cell5",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::darkGray);
return redBackground;
}
if (Parameters[row][0].contains("cell6",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::red);
return redBackground;
}
if (Parameters[row][0].contains("cell7",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::darkGreen);
return redBackground;
}
if (Parameters[row][0].contains("I_",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::green);
return redBackground;
}
if ((Parameters[row][0].contains("CH",Qt::CaseInsensitive))
|| (Parameters[row][3].contains("+",Qt::CaseInsensitive)))
{
QBrush redBackground(Qt::green);
return redBackground;
}
if ((Parameters[row][0].contains("DS",Qt::CaseInsensitive))
|| (Parameters[row][3].contains("-",Qt::CaseInsensitive)))
{
QBrush redBackground(Qt::red);
return redBackground;
}
if (Parameters[row][0].contains("V_Pack",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::darkRed);
return redBackground;
}
if (Parameters[row][0].contains("T_ISL",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::darkMagenta);
return redBackground;
}
if (Parameters[row][0].contains("T_HS",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::darkYellow);
return redBackground;
}
if (Parameters[row][0].contains("T_LS",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::darkCyan);
return redBackground;
}
if (Parameters[row][0].contains("T_B",Qt::CaseInsensitive))
{
QBrush redBackground(Qt::darkBlue);
return redBackground;
}
}
break;
case Qt::TextAlignmentRole:
if (col == 3) //change text alignment only for colum 3
{
return Qt::AlignCenter;//+ Qt::AlignVCenter;
}
break;
case Qt::CheckStateRole:
if((col == 0) && (m_gridData[row][0] == false)){ //add a checkbox to all rows in colum 0
// qDebug() << "m_gridData[" << row << "][0]:" << m_gridData[row][0];
return Qt::Unchecked;
}
else if((col == 0) && (m_gridData[row][0] == true)){
// qDebug() << "m_gridData[" << row << "][0]:" << m_gridData[row][0];
return Qt::Checked;
}
if((Parameters[row][1].contains("Current/Voltage",Qt::CaseSensitive)
&& (col == 1)) && (m_gridData[row][1] == true)){
// qDebug() << "m_gridData[" << row << "][1]:" << m_gridData[row][1];
return Qt::Checked;
}
else if((Parameters[row][1].contains("Current/Voltage",Qt::CaseSensitive) && (col == 1))
&& (m_gridData[row][1] == false)){
// qDebug() << "m_gridData[" << row << "][1]:" << m_gridData[row][1];
return Qt::Unchecked;
}
if(Parameters[row][2].contains("Tempurature",Qt::CaseSensitive)
&& (col == 2) && (m_gridData[row][2] == true)){
// qDebug() << "m_gridData[" << row << "][2]:" << m_gridData[row][2];
return Qt::Checked;
}
else if((Parameters[row][2].contains("Tempurature",Qt::CaseSensitive)
&& (col == 2)) && (m_gridData[row][2] == false)){
// qDebug() << "m_gridData[" << row << "][2]:" << m_gridData[row][2];
return Qt::Unchecked;
}
}
return QVariant();
}
Qt::ItemFlags ParametersTable::flags(const QModelIndex & /*index*/) const
{
return Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
}
void AdditionalParameters::PARAMTER_SEL(QModelIndex Box)
{
int row = Box.row();
int col = Box.column();
if(!Parameters[row][col].isEmpty()){
m_gridData[row][col] = (!(m_gridData[row][col]));
qDebug() << "PARA_SEL @ m_gridData[row][col]:(" << row << "," << col << "):" << m_gridData[row][col];
}
emit stateChanged(m_gridData[row][col]);
}