Qt之 QTableWidget 实现会计手账
1、QTableWidget
QTableWidget 比 QTableView 使用起来要方便一点,不需要操心数据模型,不需要设置代理之类的操作。
-
setCellWidget(0, 3, sec); // passing the ownership
-
QWidget* w = cellWidget(row, col); // 获取单元格控件
比如:
void MyTable::setEnableRow(int row, bool enable)
{
this->blockSignals (true);
for (int j = 0; j < columnCount(); ++j) {
if ( enable ) {
item(row, j)->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}else{
item(row, j)->setFlags(Qt::NoItemFlags);
}
QWidget* w = cellWidget(row, j);
if (w)
w->setEnabled(enable);
}
this->blockSignals (false);
}
2、自定义QLineEdit
目的:实现手帐的显示效果。
思路:根据字体大小,绘制不同的竖线,QLineEdit 两端有光标的位置占据,用padding属性调整不了,最好的就是用QWidget重新写一个。目前为了简便,通过调整不同的字体和偏移,来实现按位显示的效果,不算完美。
void MyLineEdit::paintEvent(QPaintEvent* event)
{
QFontMetrics mc = this->fontMetrics ();
charWidth = mc.horizontalAdvance('8');
QLineEdit::paintEvent(event);
QPainter painter(this);
QPen pen;
for (int i = 1; i < 14; ++i) {
pen.setWidth (0);
pen.setColor (QColor(161, 230, 211)); // 浅绿色
if(i%4==0){
pen.setWidth (2);
pen.setColor (Qt::gray); // 灰色
}
if(i == 12){
pen.setColor(QColor(255, 37, 37)); // 红色
}
painter.setPen (pen);
painter.drawLine( i * (charWidth)+2, 0, i * (charWidth)+2, height());
}
}
3、自定义表头
目的:实现手帐效果的进制显示
思路:自定义QWidget,使用QTableWidget的设置表头功能
这个绘制比较简单,为了配合 MyLineEdit ,大小需要一致
QString units= "千百十亿千百十万千百十元角分";
.....
void HeaderSection::paintEvent(QPaintEvent */*event*/)
{
QPainter painter(this);
QRect txtRect = this->fontMetrics ().boundingRect (title);
painter.drawText ( ( width () - txtRect.width () ) /2,
( height()/2 + txtRect.height() ) / 2 ,title);
painter.drawLine (0,25,188,25);
int charWidth = 13;
for (int i = 1; i < 14; ++i) {
painter.setPen(QColor(161, 230, 211)); // 浅绿色
if(i%4==0){
painter.setPen (Qt::gray);
}
if(i == 12){
painter.setPen (QColor(255, 37, 37)); // 红色
}
painter.drawLine( i * (charWidth)+2, 25, i * (charWidth)+2, height());
}
QFont f = font ();
f.setPixelSize (13);
painter.setPen (Qt::black);
painter.setFont (f);
painter.drawText (4,45,units);
}
4、自定义Dialog
- 目的:实现会计科目的对话框提示
- 思路:自定义 QDialog ,提供一个接口 getItemText,获取QTreeWidget的item数据。
QStringList Dialog::getItemText()
{
this->exec ();
return list;
}
然后关联 QTreeWidget 的item双击信号
connect(w, &QTreeWidget::itemDoubleClicked, this, &Dialog::onItemDoubleClicked);
onItemDoubleClicked 槽函数,处理信号,并关闭或者隐藏对话框
void Dialog::onItemDoubleClicked(QTreeWidgetItem* item)
{
if(canBeModified){
item->setFlags (Qt::ItemIsEditable | item->flags () );
} else {
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
if (item->childCount() == 0) {
list.clear();
list << item->text(0) << item->text(1);
while (item->parent()) {
item = item->parent();
list.insert(1, item->text(1));
}
close();
// hide ();
}
}
}
- 使用 xml 用来存储项目的数据
QXmlStreamReader xml;
QXmlStreamWriter xmlw;
XML 和 QTreeXXX 十分相配。
XML的流式读写类,使用起来也十分方便,官档里的案例足够清晰。
- QTreeWidget 设置缩进大小
tree->setIndentation (10); // 调整子节点的缩进大小,让Tree紧凑一些。
5、主界面
主界面QMainWindow用来组装各个类,各个功能模块。
程序的状态数据,可以使用 QJsonDocument 来存储。Qt对 QJsonDocument 的使用十分友好,
- 加载json文档
void loadJsonDoc(AccountingVoucher *av){
QFile file("json/data.json");
file.open (QFile::ReadWrite);
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson (file.readAll (),&error);
file.close ();
av->json = jsonDoc.object (); // 从 QJsonDocument 转 QJsonObject
initJson( av ); // 加载json文档后,需要对比日期是否一致
}
- 保存json文档
void saveJsonDoc(AccountingVoucher *av){
QFile file("json/data.json");
file.open (QFile::ReadWrite);
file.write (QJsonDocument(av->json).toJson ());
file.close ();
}
- 迭代json对象属性
void initJson( AccountingVoucher *av ){
QJsonObject::iterator it =av->json.begin ();
QString date = it.value ().toString ();
QString dyear = date.section ('-',0,0);
QString dmon = date.section ('-',1,1);
.........................
Dout << av->json;
}