Qt之帕鲁小助手
QTbaleView排序、右键菜单、弹窗和数据传递
功能介绍
好久没写代码了,好久没用QT写代码了,也好久没写博客了,正好,玩幻兽帕鲁需要查询数据,又不想用别人现成的缩短了游戏寿命,就自己写一个用来小工具记录数据并方便查询。在这里记录一下实现,方便以后用到相似功能时好找。目前主要分三个部分,一个是词条库,记录一些有用词条的效果,一个是基因库,记录配对数据,但是因为看了看之后发现有6K种配对方案,果断放弃自己一种种尝试,直接用小黑盒的;最后的是帕鲁库,记录帕鲁的工作适应性、技能、掉落物等等。后面看情况再加不加其他功能,去不去美化界面。看后面还玩不玩。界面截图
部分功能的实现
QTableView的右键菜单
成员定义
创建右键菜单
// 设置词条tableview的右键菜单
ui->wordTableView->setContextMenuPolicy(Qt::CustomContextMenu);
changeAction1 = new QAction("修改", ui->wordTableView);
addAction1 = new QAction("添加", ui->wordTableView);
deleteAction1 = new QAction("删除", ui->wordTableView);
mMenuWord = new QMenu(ui->wordTableView);
mMenuWord->addAction(changeAction1);
mMenuWord->addAction(addAction1);
mMenuWord->addAction(deleteAction1);
// 为右键菜单的三个动作绑定槽函数
connect(changeAction1, &QAction::triggered, this, &Widget::ChangeWordActionTriggered);
connect(addAction1, &QAction::triggered, this, &Widget::AddWordActionTriggered);
connect(deleteAction1, &QAction::triggered, this, &Widget::DeleteWordActionTriggered);
// 将右键菜单绑定到指定的TableView中
connect(ui->wordTableView, &QWidget::customContextMenuRequested, this, &Widget::ShowWordMenu);
ShowWordMenu的函数实现
void Widget::ShowWordMenu(const QPoint &pos)
{
// 显示右键菜单
QModelIndex index = ui->wordTableView->indexAt(pos);//获取鼠标点击位置项的索引
if(index.isValid() || wordTableModel->rowCount() <= 1)//数据项是否有效,空白处点击无菜单,但表中没数据时可以打开菜单
{
mMenuWord->exec(ui->wordTableView->viewport()->mapToGlobal(pos));
}
}
修改函数中获取行信息
void Widget::ChangeWordActionTriggered()
{
// 如果已经打开一个弹窗了,直接返回
if(!ShareData::flag)
{
return;
}
// 表为空则提示
if(wordTableModel->rowCount() <= 1)
{
QMessageBox::information(this, "提示", "词条库中无数据");
return;
}
// 获取选中行信息,打开弹窗,供用户修改
// 获取选中行信息
QModelIndex index = ui->wordTableView->selectionModel()->selectedIndexes().first();
int row = index.row(); //行号,从0开始
QModelIndex index1 =wordTableModel->index(row, 0);
QModelIndex index2 =wordTableModel->index(row, 1);
QModelIndex index3 =wordTableModel->index(row, 2);
QString wordName = wordTableModel->data(index1).toString();
QString wordDetail = wordTableModel->data(index2).toString();
QString wordRecommend = wordTableModel->data(index3).toString();
qDebug() << wordName << " " << wordDetail << " " << wordRecommend
效果展示
弹窗和窗口之间的数据传递
新建一个Widget用于作为修改或添加词条库或者帕鲁库的数据的弹窗,本程序词条库和基因库公用了同一个Widget,具体的弹窗布局如下:
打开弹窗的方式很简单,在主界面的头文件中定义这两个widget的指针并在构造函数中初始化,然后在右键菜单的槽函数中将它显示出来,此处以词条修改函数为例:
// 将数据显示到弹窗中,将推荐作用的编辑框隐藏,显示下拉框
dialogWordAndBreed->mWordAndBreedLineEdit3->setVisible(false);
dialogWordAndBreed->mSelectWordRecommend->setVisible(true);
dialogWordAndBreed->mWordAndBreedLable->setText("修改词条");
dialogWordAndBreed->mWordAndBreedLable1->setText("词条名称");
dialogWordAndBreed->mWordAndBreedLable2->setText("词条效果");
dialogWordAndBreed->mWordAndBreedLable3->setText("推荐作用");
dialogWordAndBreed->mWordAndBreedLineEdit1->setText(wordName);
dialogWordAndBreed->mWordAndBreedLineEdit2->setText(wordDetail);
if(wordRecommend == "战斗")
{
dialogWordAndBreed->mSelectWordRecommend->setCurrentIndex(0);
}
else if(wordRecommend == "骑乘")
{
dialogWordAndBreed->mSelectWordRecommend->setCurrentIndex(1);
}
else
{
dialogWordAndBreed->mSelectWordRecommend->setCurrentIndex(2);
}
dialogWordAndBreed->setWindowFlags(dialogWordAndBreed->windowFlags() | Qt::WindowStaysOnTopHint);
dialogWordAndBreed->show();
ShareData::flag = false;
如上所示,此处的数据传递是直接用的setText,弹窗中的组件是public的,因此可以直接设置,但是传回来的时候却无法直接传,因此为主界面创建了一个槽函数,弹窗发射信号并将数据放到共享缓存中,在主界面的槽函数中根据信号进行处理
主界面处理信号函数的代码实现
void Widget::ReceiveMsg(QString str)
{
if(str == "修改词条")
{
QModelIndex index = ui->wordTableView->selectionModel()->selectedIndexes().first();
int row = index.row();
QModelIndex index1 =wordTableModel->index(row, 0);
QModelIndex index2 =wordTableModel->index(row, 1);
QModelIndex index3 =wordTableModel->index(row, 2);
wordTableModel->setData(index1, ShareData::sWordItem->GetWordName());
wordTableModel->setData(index2, ShareData::sWordItem->GetWordDetail());
wordTableModel->setData(index3, ShareData::WordRecommendTransToStr(ShareData::sWordItem->GetWordRecommend()));
}
else if(str == "添加词条")
{
AddItem(ShareData::sWordItem, TabCategories::WORD);
}
else if(str == "修改配对")
{
QModelIndex index = ui->breedTableView->selectionModel()->selectedIndexes().first();
int row = index.row();
QModelIndex index1 =breedTableModel->index(row, 0);
QModelIndex index2 =breedTableModel->index(row, 1);
QModelIndex index3 =breedTableModel->index(row, 2);
breedTableModel->setData(index1, ShareData::sBreed->GetFatherName());
breedTableModel->setData(index2, ShareData::sBreed->GetMotherName());
breedTableModel->setData(index3, ShareData::sBreed->GetKidName());
}
else if(str == "添加配对")
{
AddItem(ShareData::sBreed, TabCategories::BREED);
}
else if(str == "修改帕鲁")
{
QModelIndex index = ui->palPoolTableView->selectionModel()->selectedIndexes().first();
int row = index.row();
QModelIndex index1 =palTableModel->index(row, 0);
QModelIndex index2 =palTableModel->index(row, 1);
QModelIndex index3 =palTableModel->index(row, 2);
QModelIndex index4 =palTableModel->index(row, 3);
QModelIndex index5 =palTableModel->index(row, 4);
QModelIndex index6 =palTableModel->index(row, 5);
QString no = "NO." + QString::number(ShareData::sPalPool->getPalNumber());
palTableModel->setData(index1, no);
palTableModel->setData(index2, ShareData::sPalPool->getPalName());
palTableModel->setData(index3, ShareData::sPalPool->GetWorkAbility());
palTableModel->setData(index4, ShareData::sPalPool->getSkillName());
palTableModel->setData(index5, ShareData::sPalPool->getSkillDetail());
palTableModel->setData(index6, ShareData::sPalPool->getProduct());
}
else // 添加帕鲁
{
AddItem(ShareData::sPalPool, TabCategories::PAL);
SortPalPoolFromNumber();
}
}
在主界面的初始化函数中绑定两个界面之间的信号与槽函数
connect(dialogWordAndBreed, SIGNAL(SendText(QString)), this, SLOT(ReceiveMsg(QString)));
connect(dialogPal, SIGNAL(SendText(QString)), this, SLOT(ReceiveMsg(QString)));
在弹窗的确定按钮槽函数中发射信号并写入数据
void form12::on_btnEnsure12_clicked()
{
WriteShareData();
if(ui->mWordAndBreedLable->text() == "修改词条")
{
emit SendText("修改词条");
}
else if(ui->mWordAndBreedLable->text() == "添加词条")
{
emit SendText("添加词条");
}
else if(ui->mWordAndBreedLable->text() == "添加配对")
{
emit SendText("添加配对");
}
else
{
emit SendText("修改配对");
}
close();
}
void form12::WriteShareData()
{
// 将数据存入共享数据
// 词条添加、修改
if(ui->mWordAndBreedLable->text().contains("词条"))
{
ShareData::sWordItem->SetWordName(ui->mWordAndBreedLineEdit1->text());
ShareData::sWordItem->SetWordDetail(ui->mWordAndBreedLineEdit2->text());
ShareData::sWordItem->SetWordRecommend(ShareData::StrTransToWordRecommend(ui->selectRecommend->currentText()));
}
// 基因库添加、修改
else
{
ShareData::sBreed->SetFatherName(ui->mWordAndBreedLineEdit1->text());
ShareData::sBreed->SetMotherName(ui->mWordAndBreedLineEdit2->text());
ShareData::sBreed->SetKidName(ui->mWordAndBreedLineEdit3->text());
}
}
QTableView在复选框的筛选之上再进行查找
为了再筛选工作适应性之后再查找或者再查找之后在进行筛选,网上看了一些方法,最后都没有成功,最终用了一个笨办法,那就是在同一个槽函数中进行处理。
首先绑定复选框的勾选信号和搜索框的文本改变信号到一个函数中
// 将帕鲁才库界面复选框放到一个槽函数中处理
connect(ui->checkMakeFire, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkMakeWater, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkPlant, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkMakeElec, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkHandWork, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkTake, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkChopTree, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkMining, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkMakeDrug, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkCoolDown, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkCarry, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->checkFarm, &QCheckBox::toggled, this, &Widget::HandleFind);
connect(ui->palLineEdit, &QLineEdit::textChanged, this, &Widget::HandleFind);
处理函数的具体代码实现,实际就是将不符合条件的行隐藏起来
void Widget::HandleFind()
{
// 处理文本搜索
//获取文本框内容
QString str=ui->palLineEdit->text();
str.remove(QRegExp("\\s"));
for(int i=0; i<palTableModel->rowCount(); i++)
{
// 先设置所有行隐藏
ui->palPoolTableView->setRowHidden(i,true);
if(str.isEmpty())
{
ui->palPoolTableView->setRowHidden(i,false);
continue;
}
QString r = "";
//提取词条信息
QAbstractItemModel *model=ui->palPoolTableView->model();
QModelIndex index;
for(int j=0;j<palTableModel->columnCount();j++)
{
index=model->index(i,j);
r+=model->data(index).toString();
}
r.remove(QRegExp("\\s"));
if(r.contains(str,Qt::CaseSensitive))
{
ui->palPoolTableView->setRowHidden(i,false);
}
}
for(int i=0; i<palTableModel->rowCount(); i++)
{
//ui->palPoolTableView->setRowHidden(i,false);
//提取工作适应性信息
QAbstractItemModel *model=ui->palPoolTableView->model();
QModelIndex index;
index=model->index(i,2);
QString r = model->data(index).toString();
bool check = true;
if(ui->checkMakeFire->isChecked())
{
check = check && r.contains(ui->checkMakeFire->text()); // 生火
}
if(ui->checkMakeWater->isChecked())
{
check = check && r.contains(ui->checkMakeWater->text()); // 浇水
}
if(ui->checkPlant->isChecked())
{
check = check && r.contains(ui->checkPlant->text()); // 播种
}
if(ui->checkMakeElec->isChecked())
{
check = check && r.contains(ui->checkMakeElec->text()); // 发电
}
if(ui->checkHandWork->isChecked())
{
check = check && r.contains(ui->checkHandWork->text()); // 手工
}
if(ui->checkTake->isChecked())
{
check = check && r.contains(ui->checkTake->text()); // 采集
}
if(ui->checkChopTree->isChecked())
{
check = check && r.contains(ui->checkChopTree->text()); // 伐木
}
if(ui->checkMining->isChecked())
{
check = check && r.contains(ui->checkMining->text()); // 采矿
}
if(ui->checkMakeDrug->isChecked())
{
check = check && r.contains(ui->checkMakeDrug->text()); // 制药
}
if(ui->checkCoolDown->isChecked())
{
check = check && r.contains(ui->checkCoolDown->text()); // 冷却
}
if(ui->checkCarry->isChecked())
{
check = check && r.contains(ui->checkCarry->text()); // 搬运
}
if(ui->checkFarm->isChecked())
{
check = check && r.contains(ui->checkFarm->text()); // 牧场
}
if(!check)
{
ui->palPoolTableView->setRowHidden(i,true);
}
}
}
将QTableView中的数据按照某列进行排序
也是在网上找了一堆方法后都失败了,此处想按照图鉴的编号顺序对帕鲁进行排序,最终采用了一个笨办法实现,先获取他们的图鉴编号,也就是第一列"No."后的数字,再对他们进行冒泡排序,当然也可以采用其他排序算法,看个人需求
void Widget::SortPalPoolFromNumber()
{
for(int i=0; i<palTableModel->rowCount()-1; i++)
{
for(int j=i; j<palTableModel->rowCount()-i-1; j++)
{
//qDebug() << palTableModel->data(palTableModel->index(j,0)).toString();
QString str1 = palTableModel->data(palTableModel->index(j,0)).toString().remove("NO.");
QString str2 = palTableModel->data(palTableModel->index(j+1,0)).toString().remove("NO.");
int no1 = str1.toInt();
int no2 = str2.toInt();
if(no1 > no2)
{
SwapRow(palTableModel, j, j+1);
}
}
}
}
inline void SwapRow(QStandardItemModel *model, int row1, int row2)
{
// 获取第一行的数据项
QList<QStandardItem*> items1;
for (int column = 0; column < model->columnCount(); ++column) {
items1.append(model->takeItem(row1, column));
}
// 获取第二行的数据项
QList<QStandardItem*> items2;
for (int column = 0; column < model->columnCount(); ++column) {
items2.append(model->takeItem(row2, column));
}
// 在第二行插入第一行的数据项
for (int column = 0; column < model->columnCount(); ++column) {
model->setItem(row2, column, items1.at(column));
}
// 在第一行插入第二行的数据项
for (int column = 0; column < model->columnCount(); ++column) {
model->setItem(row1, column, items2.at(column));
}
}
然后再每次添加数据或者修改数据和构造函数中调用该函数即可实现排序。
最后,放出代码文件和打包好的exe文件链接,需要的自取。
打包好的exe,存储了一些我自己记录的数据链接
更多推荐
所有评论(0)