今天来写一下经常用的Qt表格代理,很多时候用到了属性表格。当然,Qt其实内置的QtPropertyBrowser功能已经很强大了,我在这里介绍的只是自定义的属性表格,实现比较简单,代理使用的是Qt的默认代理类QItemDelegate,只是为了说明问题,很多复杂的代理或者自定义的代理在此不赘述了。
先上一张效果图:
左侧表格表示属性表格,右侧表示表格显示的输出,表格属性修改后,会输出新的属性内容。
表格属性对应的是一个测试类TestMyObj,代码如下:
#ifndef TESTMYOBJ_H
#define TESTMYOBJ_H
#include <QObject>
#include <QVariant>
#include <QVector>
class PropertyInfo{
public:
PropertyInfo(const QString& propertyName,
const QString& displayName, QVariant::Type type)
: m_propertyName(propertyName),
m_displayName(displayName),
m_type(type){}
PropertyInfo():m_type(QVariant::Invalid){}
public:
QString m_propertyName;
QString m_displayName;
QVariant::Type m_type;
};
class TestMyObj : public QObject
{
Q_OBJECT
Q_PROPERTY(int ObjId READ getId WRITE setId)
Q_PROPERTY(QString ObjName READ getName WRITE setName)
Q_PROPERTY(bool ObjFlag READ getFlag WRITE setFlag)
public:
TestMyObj(QObject *parent);
~TestMyObj();
int getId() const { return m_id; }
void setId(int val) { m_id = val; }
QString getName() const { return m_name; }
void setName(const QString& val) { m_name = val; }
bool getFlag() const { return m_flag; }
void setFlag(bool val) { m_flag = val; }
virtual const QVector<PropertyInfo>& getPropertyList() const;
private:
void intiProperty();
private:
int m_id;
QString m_name;
bool m_flag;
QVector<PropertyInfo> m_propertys;
};
#endif // TESTMYOBJ_H
其中,PropertyInfo是为了方便在表格中显示属性内容引入的,这样可以方便的遍历Obj的属性列表。对应的cpp:
#include "TestMyObj.h"
TestMyObj::TestMyObj(QObject *parent)
: QObject(parent), m_id(1), m_name("testobj"), m_flag(true)
{
intiProperty();
}
TestMyObj::~TestMyObj()
{
}
const QVector<PropertyInfo>& TestMyObj::getPropertyList() const
{
return m_propertys;
}
void TestMyObj::intiProperty()
{
m_propertys.append(PropertyInfo("ObjId", "ID", QVariant::Int));
m_propertys.append(PropertyInfo("ObjName", "Name", QVariant::String));
m_propertys.append(PropertyInfo("ObjFlag", "Flag", QVariant::Bool));
}
创建属性列表:
void TestDelegateProperty::createProperty()
{
ui.tableWidget->setColumnCount(2);
const QVector<PropertyInfo>& propertys = m_obj->getPropertyList();
for (int i = 0; i < propertys.size(); i++)
{
const PropertyInfo& info = propertys[i];
ui.tableWidget->insertRow(i);
QTableWidgetItem* keyItem = new QTableWidgetItem();
keyItem->setData(Qt::EditRole, info.m_displayName);
keyItem->setFlags(keyItem->flags() & (~Qt::ItemIsEditable));
ui.tableWidget->setItem(i, 0, keyItem);
QTableWidgetItem* valueItem = new QTableWidgetItem();
valueItem->setData(Qt::EditRole, m_obj->property(info.m_propertyName.toStdString().c_str()));
ui.tableWidget->setItem(i, 1, valueItem);
}
}
属性修改对应的处理使用的是QTableWidget的itemChanged信号,对应的槽为:
void TestDelegateProperty::on_tableWidget_itemChanged( QTableWidgetItem * item )
{
if (item->column() == 1)
{
int index = item->row();
m_obj->setProperty(m_obj->getPropertyList().at(index).m_propertyName.toStdString().c_str(),
item->data(Qt::EditRole));
showProperty();
}
}
属性的文本显示:
void TestDelegateProperty::showProperty()
{
ui.plainTextEdit->clear();
QString log;
const QVector<PropertyInfo>& propertys = m_obj->getPropertyList();
for (int i = 0; i < propertys.size(); i++)
{
const PropertyInfo& info = propertys[i];
log += info.m_displayName + ":" + m_obj->property(info.m_propertyName.toStdString().c_str()).toString();
if (i != propertys.size() - 1)
{
log += '\n';
}
}
ui.plainTextEdit->document()->setPlainText(log);
}