标准型模型
一.前言
书接上回,我们已经实现了导入文件,添加行,插入行,删除行,接下来,我们开始实现接下来的功能。
二.预览数据
1.获取表头
cpp
void MainWindow::on_actionSee_triggered()
{
ui->plainTextEdit->clear();//把上次显示的清空
QString str;
for(int i=0;i<colCount;i++)
{
auto item=model->horizontalHeaderItem(i);//拿到表头的每项数据
str+=item->text()+"\t\t";//将每项的内容加到字符串中
}
ui->plainTextEdit->appendPlainText(str);//添加到文本编辑器里
}
运行结果:
2.获取数据项
接下来就是拿到数据项了,表格类似于二维数组,所有我们可以用两次for循环来拿。
cpp
for(int i=0;i<model->rowCount();i++)
{
str="";//每一行都从空字符串相加
for(int j=0;j<colCount-1;j++)//最一列单独处理
{
auto item=model->item(i,j);
str+=item->text()+"\t\t";
}
auto item=model->item(i,colCount-1);//最后一列
if(item->checkState()==Qt::Checked)//根据是否勾选来选择
{
str+="是";
}
else
{
str+="否";
}
ui->plainTextEdit->appendPlainText(str);//会自动换行
}
运行结果:
三.保存文件
1.文件对话框获取保存文件名
cpp
//获取保存文件名
QString fileName=QFileDialog::getSaveFileName(this,"保存文件",QCoreApplication::applicationDirPath());
防御性编程:
cpp
if(fileName.isEmpty())//如果文件名为空,就直接返回
{
return;
}
2.用文件名初始化文件对象
cpp
QFile qFile(fileName);
3.打开文件对象
用读写和文本和截断的方式打开,截断就是打开时里面有文件就清空
cpp
if(!qFile.open(QIODevice::ReadWrite|QIODevice::Text|QIODevice::Truncate))//通过打不开文件直接返回
{
return;
}
4.用文件对象初始化文本流
cpp
QTextStream stream(&qFile);
5.写入数据
其实就跟刚刚预览数据的时候一样,只是这里是往文件里面进行添加
cpp
QString str;
for(int i=0;i<colCount;i++)
{
auto item=model->horizontalHeaderItem(i);//拿到表头的每项数据
str+=item->text()+"\t\t";//将每项的内容加到字符串中
}
stream<<str<<"\n";//写入文件中
for(int i=0;i<model->rowCount();i++)
{
str="";//每一行都从空字符串相加
for(int j=0;j<colCount-1;j++)//最一列单独处理
{
auto item=model->item(i,j);
str+=item->text()+"\t\t";
}
auto item=model->item(i,colCount-1);
if(item->checkState()==Qt::Checked)
{
str+="是";
}
else
{
str+="否";
}
stream<<str<<"\n";//写入文件中
运行结果保存的文:
四.格式
1.居右
默认单元格内容居左,所以我们先来实现居右的功能
cpp
void MainWindow::on_actionRight_triggered()
{
if(!selectionModel->hasSelection())//没有选择就直接退出
{
return;
}
auto indexs=selectionModel->selectedIndexes();//通过选择模型可以获取选择的多个单元格的模型索引
for(int i=0;i<indexs.count();i++)
{
QStandardItem * item=model->itemFromIndex(indexs[i]);//通过模型索引获取项
item->setTextAlignment(Qt::AlignVCenter|Qt::AlignRight);//设置文本对其方式为右对其,垂直居中
}
}
注释我写的很详细我就不讲了,auto是我偷懒的写法,如果你们要写具体的类型可以点进函数看。
2.居中
同理,只是文本对齐参数不一样
cpp
void MainWindow::on_actionMiddle_triggered()
{
if(!selectionModel->hasSelection())//没有选择就直接退出
{
return;
}
auto indexs=selectionModel->selectedIndexes();//通过选择模型可以获取选择的多个单元格的模型索引
for(int i=0;i<indexs.count();i++)
{
QStandardItem * item=model->itemFromIndex(indexs[i]);//通过模型索引获取项
item->setTextAlignment(Qt::AlignVCenter|Qt::AlignHCenter);//只是这里参数不一样
}
}
运行结果:
3.居左
cpp
void MainWindow::on_actionLeft_triggered()
{
if(!selectionModel->hasSelection())//没有选择就直接退出
{
return;
}
auto indexs=selectionModel->selectedIndexes();//通过选择模型可以获取选择的多个单元格的模型索引
for(int i=0;i<indexs.count();i++)
{
QStandardItem * item=model->itemFromIndex(indexs[i]);//通过模型索引获取项
item->setTextAlignment(Qt::AlignVCenter|Qt::AlignLeft);
}
}
4.粗体
粗体action是复选框,用这个信号
cpp
void MainWindow::on_actionBold_triggered(bool checked)
{
if(!selectionModel->hasSelection())//没有选择就直接退出
{
return;
}
auto indexs=selectionModel->selectedIndexes();//通过选择模型可以获取选择的多个单元格的模型索引
for(int i=0;i<indexs.count();i++)
{
QStandardItem * item=model->itemFromIndex(indexs[i]);//通过模型索引获取项
QFont font=item->font();
font.setBold(true);
item->setFont(font);
}
}
运行结果:
五.模型的信号
1.解决粗体action问题
但是现在有一个问题,那就是我点粗体action之后,他不会变化,当我选择另外一个单元格的时候,他还是一直选中的,明显不合理,我明明就没有粗体。
就像这样,不是粗体但是复选框也是打开的。
这个时候我们就需要动态的来控制粗体按钮的开与关了。
当我们选择另一个单元格的时候,选择模型就可以发出信号,所以我们来使用选择模型的信号。
因为模型不是ui界面所以只能我们手动关联,和写槽函数。
选信号可以到选择模型里面去找。
槽函数:
cpp
void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
信号槽关联:
cpp
connect(selectionModel,SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this,SLOT(on_currentChanged(const QModelIndex &, const QModelIndex &)));
槽函数的实现:
cpp
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
if(current.isValid())//如果当前点击的单元格是有效的。
{
auto item=model->itemFromIndex(current);//通过当前模型索引获取单元格
ui->actionBold->setChecked(item->font().bold());//如果是粗体就打开,不是就关闭
}
}
就很nice可以去玩玩。
2.状态栏显示信息
cpp
statusBar()->addWidget(labelInfo);//状态栏添加一个标签
还是在选择变化的槽函数里面
cpp
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
if(current.isValid())//如果当前点击的单元格是有效的。
{
auto item=model->itemFromIndex(current);//通过当前模型索引获取单元格
ui->actionBold->setChecked(item->font().bold());//如果是粗体就打开,不是就关闭
labelInfo->setText(QString::asprintf("单元格信息:行:%d 列:%d",current.row(),current.column())+" 内容:"+item->text());
}
}
运行结果:
六.总结
对于这些功能的处理,拿到item,可以通过行和列坐标,可以通过模型索引。对于上节的内容,我们主要是设置item。所以对于我们学过的东西一定要找相似点,要总结一下。
好了,标准项模型和选择模型就讲到这里了。
慌了,你就慢下来,还慌,你就停下来!