一、 Qt表格&列表 展示效果描述化与数据绑定驱动化
调用及解说如下:
QStringList formats; formats.append("0~股票代码~code~~72~~|"); formats.append("0~股票名称~name~~180~~|"); formats.append("1~现价~AnimalCell~1|3~64~~zjcj|zdf"); formats.append("1~涨跌幅~AnimalCell~0|2|1~72~~zdf|zdf"); formats.append("1~行业力道~AnimalCell~0|2|0|blue~72~~hyld|black"); formats.append("1~涨跌分布~ChangeBar~~128~~up|up5|down|down5"); formats.append("1~短期强弱~RatingBar~~118~~oldhysrps|hysrps"); formats.append("1~状态~ZdBar~~32~~zdf"); formats.append("1~综合~ZhpmBar~~32~~zjcj|hysrps"); formats.append("1~分析师~ZhpmBar2~~42~~hysrps"); formats.append("1~市净率~AnimalCell~0|2|0|black~72~~P/E|black"); formats.append("1~行业力道~AnimalCell~0|2|0|black~72~~P/B|black"); formats.append("1~市现率~AnimalCell~0|2|0|black~72~~P/S|black"); formats.append("1~市销率~AnimalCell~0|2|0|black~72~~P/CF|black"); //ui->tableWidget 表示QTableWidget控件,该控件虽然传统但非常灵活,QTableView虽然可以使用数据模型,但展示需要重绘,意味着要写不少代码且需要编译,这是我选择前者的原因。 //pMRS是数据集,是一个二维表,可以具有任意行列及其数据 //CommonStudio::AutoBindingToDataGrid函数只需要传入QTableWidget、约定数据,描述信息,即可将约定数据按照描述信息来展示。 CommonStudio::AutoBindingToDataGrid(ui->tableWidget, pMRS,formats,this);
如上所图及解说所示,只需要写好描述信息formats,将QTableWidget控件、数据集以及描述信息传入CommonStudio::AutoBindingToDataGrid函数,即可实现上图所展示的效果。进一步讲,请求回来的相同数据集,不同描述信息,展示效果不同。
对于理财产品(终端),或者说所有的应用程序来说,表格是很常见的,可动不动就要写和修改代码并且编译和让用户升级是很累的事情,本文这样的做法,可以将描述信息存在后台(数据库中),这样需求发生更改时,修改数据库中对应描述即可。其二,只要维护一处,处处都可以得到更新,随时控件资源的开发和扩展,展示出来的效果和功能将会更加丰富和强大。
二、传统表格数据装载与展示
//构造函数里初始化表格&列表 MyWidget::MyWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MyWidget) { ui->setupUi(this); this->setObjectName("Module1"); indexTable=new QTableWidget(0,5,this); qsgTable=new QTableWidget(0,5,this); newsTable=new QTableWidget(0,3,this); industryTable=new QTableWidget(0,6,this); zhphTable=new QTableWidget(0,15,this); CommonStudio::InitTableWidget(indexTable,false,true); CommonStudio::InitTableWidget(qsgTable,false,true); CommonStudio::InitTableWidget(newsTable,false,true,false,false); CommonStudio::InitTableWidget(industryTable,true,true); CommonStudio::InitTableWidget(zhphTable,true,true); QStringList header; header<<""<<tr("Name")<<tr("Zjcj")<<tr("Zd")<<tr("Zdf");//QLatin1String indexTable->setHorizontalHeaderLabels(header); header.clear(); header<<""<<tr("Name")<<tr("Zhpf")<<tr("Zjcj")<<tr("Zdf"); qsgTable->setHorizontalHeaderLabels(header); header.clear(); header<<""<<tr("HyName")<<tr("HyZdf")<<tr("Zdfb") << tr("LzName") << tr("LzZdf"); industryTable->setHorizontalHeaderLabels(header); header.clear(); header<<""<<tr("Name") << tr("Code") << tr("Zhpf") << tr("Dqqr") << tr("Cqqr") << tr("Zjcj") << tr("Zdf") << tr("Lb") << tr("Hsl") << tr("Open") << tr("High") << tr("Low") << tr("Volume") << tr("Amount"); zhphTable->setHorizontalHeaderLabels(header); indexTable->setColumnHidden(0,true); indexTable->setColumnWidth(1,66); indexTable->setColumnWidth(2,66); indexTable->setColumnWidth(3,54); indexTable->setColumnWidth(4,54); qsgTable->setColumnHidden(0,true); qsgTable->setColumnWidth(1,66); qsgTable->setColumnWidth(2,66); qsgTable->setColumnWidth(3,54); qsgTable->setColumnWidth(4,54); newsTable->setColumnHidden(0,true); newsTable->setColumnWidth(1,200); newsTable->setColumnWidth(2,40); industryTable->setColumnHidden(0,true); industryTable->setColumnWidth(1,200); industryTable->setColumnWidth(2,54); industryTable->setColumnWidth(3,320); industryTable->setColumnWidth(4,100); industryTable->setColumnWidth(5,54); zhphTable->setColumnHidden(0,true); zhphTable->setColumnWidth(1,88); zhphTable->setColumnWidth(2,64); zhphTable->setColumnWidth(3,64); zhphTable->setColumnWidth(4,114); zhphTable->setColumnWidth(5,114); zhphTable->setColumnWidth(6,88); zhphTable->setColumnWidth(7,88); zhphTable->setColumnWidth(8,88); zhphTable->setColumnWidth(9,88); zhphTable->setColumnWidth(10,88); zhphTable->setColumnWidth(11,88); zhphTable->setColumnWidth(12,88); zhphTable->setColumnWidth(13,88); zhphTable->setColumnWidth(14,88); ..............................................不一一例出 } //数据回调函数,数据回来后,装载或更新到表格&列表 void MyWidget::receiveDataSlot(int vol, ENORecordset **pMRS, QVariant etag) { ETagData realEtag; realEtag = etag.value<ETagData>(); int i=0; int poor; int row= pMRS[0]->RowsAffected(); int column = pMRS[0]->FieldCount(); QString str; if(vol>=1){ QWidget *widget; ZhpmBar *zhpfCtl; ChangeBar *changeCtl; RatingBar *ratingCtl; AnimalCell *animalCtl; QTableWidgetItem *item; pMRS[0]->FetchFirst(); //Index hq list if(realEtag.nMainFunc==31000 && realEtag.nSubFunc==4) { poor = row - indexTable->rowCount(); if(poor>0){ for(int i=0;i<poor;i++) indexTable->insertRow(indexTable->rowCount()); } else if(poor<0){ poor=qAbs(poor); for(int i=poor-1;i>=0;i--) indexTable->removeRow(i); } double zdfD; char code[64],name[64],zjcj[64],zd[64],zdf[64],exchid[64]; while(!pMRS[0]->IsEOF()) { zdfD = pMRS[0]->ToFloat("zdf"); strcpy(code,pMRS[0]->ToString("code")); strcpy(name,pMRS[0]->ToString("name")); strcpy(zjcj,pMRS[0]->ToString("zjcj")); strcpy(zd,pMRS[0]->ToString("zhd")); strcpy(zdf,pMRS[0]->ToString("zdf")); strcpy(exchid,pMRS[0]->ToString("exchid")); TCHAR tchar[64]; ENOUtils::ToWChar(name,tchar,64); //key str.clear(); str.append(code); str.append("."); str.append(exchid); item=new QTableWidgetItem(str); indexTable->setItem(i,0,item); //name item=new QTableWidgetItem(name); indexTable->setItem(i,1,item); ........................这部分代码太多,随时根据需求会改动的,不一一列出来了 i++; pMRS[0]->FetchNext(); } } } }
三、新方式与传统做法的对比
传统方式下,需要不断编写和维护大量代码,新方式下,开发人员只需要编写简单少量的描述信息,管理人员和经理人士无需开发经验即可以通过管理定制模块,傻瓜化的方式下选择需要的列并设置每一列的展示效果(控件类型),以及对应的字段即可,包含展示的中文名称、宽度、控件类型以及颜色等属性(颜色可以是固定的,也可以像现价这样根据涨跌度的正负号来显示红或绿色),就可以实现上图效果。
客户端请求命令不同,就会得到不同的数据结果,新方式下,配和这样的简单描述,基本上可以实现各种复杂表格效果的展示和使用,随时表格的越来越多,新方式的工作量由于傻瓜定制式模块(类似股票选股模块及其操作)变得轻松、简单、快速,而传统方式则要面对大量代码的编写和维护,哪个更有优越不必多说了吧?
注:“管理定制模块”可以录入或选择指定功能号(主子功能及参数),然后就出来字段信息(英文是唯一的,中文则表示默认描述),用户要展示那些就选择那些出来,可以更新要展示时候的描述、描述、类型(比如这一列显示为某个控件),以及该列对应到那些字段等等,操作就简直就如选股,选好了点击确定,还可以请求数据并把展示效果显示出来,之后可以将这些信息保存到指定数据库中位置。
注:就当自己在选股,选好了,作为条件入选的列作为列表的列,数据等同请求回来的内容了,就这么简单。
注:新方式原来是在silverlight下实现过的,但sl下有各种限制,搞得描述信息复杂庞大且有限制,不过到了Qt这儿就非常灵活和好使了,不想写太多枯燥繁杂的代码而创。
四、理财应用表格统计
首页 5个表格&列表 大势.. 2个表格 个股.. 至少3个表格 行业.. 2个表格 机构.. 2个表格(10种展示组合,条件不同,表格展示内容不同) 组织.. 2个表格(5种展示组合,同上) 对冲.. 2个表格 交易决策 N个表格(N表示有点多) 市场雷达 6个表格 事件.. 1表多展示(2*3=6种展示组合) 中山.. 3个表格 智能选股 1个表格(目前选股出来的列都是固定的,有了本文中的利器,就可以把条件包含的列展示出来,而不是每次选股出来的结果列都一样)
如今有了这种新方式,至少在表格这一块,不需要写大量枯燥,让我头发越来越少的代码,爽了很多。