2023-11-13 到 2023-11-19
2023-11-13
qt案例
完成任务
-
做出一个qtDemo案例
-
解决翻译问题
完成一个图像处理小工具
代码如下
//MainWindow.h #pragma once #include <QMainWindow> #include <QPushButton> #include <QTranslator> #include <QApplication> #include <QComboBox> #include <QPlainTextEdit> #include <QToolButton> #include <QLineEdit> #include <QWidget> #include <QPixmap> #include <QPainter> #include <QColor> #include <QImage> #include <QFileDialog> #include <QHBoxLayout> #include <QVBoxLayout> #include <QPushButton> #include <QLabel> #include <QSlider> /*! @brief 主界面类,可在此添加界面相关的内容 *@details */ class OMainWindow : public QMainWindow { Q_OBJECT public: OMainWindow(QApplication *pApp); ~OMainWindow(void); private: void createMainFrame(); private slots: void apply(); void ok(); void cancel(); void about(); void write(); private: void paintEvent(QPaintEvent *event) override; //重写绘图事件 bool isTransparent(const QColor &color); //判断是否透明 bool isBackGround(const QColor &color); //是否编译背景颜色 private: void InitLayout(); //布局初始化 void InitObj(); //对象初始化 void ReLayout(); //布局再次排列 void InitSlots(); //槽函数初始化 void processImage(); //处理图片 QPixmap originalImage; QPixmap processedImage; QPushButton *_btnOpenImg; QLineEdit *_lineEditInputRgb; QPushButton *_btnProcessImg; QLineEdit *_lineEditInputReplaceRgb; QPushButton *_btnReplaceImg; QPushButton *_btnSaveImg; QPushButton *_btnExchangeImg; QLabel *_labelOriImg; QLabel *_labelResImg; QSlider *slider; QLabel *_labelSliderNum; QColor backgroundColor; QColor replaceColor; bool hasResult = false; int colorDifferenceThreshold = 1; bool isCut = false; bool isReplace = false; //--------------略--------------- QPushButton* okbutton; QPushButton* cancelbutton; QPushButton* applybutton; QTranslator translator_dtTool; QComboBox* comboBox; QPlainTextEdit* textedit; QToolButton* toolbutton; };
//MainWindow.cpp #include "MainWindow.h" #include <QtCore/QDebug> #include <QtCore//QFile> #include <QMessageBox> #include <QMenu> #include <QMenuBar> #include <QStatusBar> #include <QVBoxLayout> #include <QDialogButtonBox> OMainWindow::OMainWindow(QApplication *pApp) { // 加载翻译文件 translator_dtTool.load(":/languages/EXEDemo_zh_CN.qm"); qApp->installTranslator(&translator_dtTool); InitObj(); InitLayout(); ReLayout(); InitSlots(); // 菜单栏 QMenu *configMenu = new QMenu(tr("File"), this); menuBar()->addMenu(configMenu); configMenu->addAction(tr("Soft Config"), this, SLOT(on_softConfig())); QMenu *helpMenu = new QMenu(tr("Help"), this); menuBar()->addMenu(helpMenu); helpMenu->addAction(tr("About EXEDemo"), this, SLOT(about())); setAutoFillBackground(false); //状态栏 QStatusBar *pSBar = statusBar(); pSBar->setFixedHeight(20); statusBar()->showMessage(tr("Ready")); //窗口标题 this->setWindowTitle(tr("ExeDemo")); /* // 创建窗口控件 //createMainFrame(); setFixedSize(470, 380); QStringList arguments = pApp->arguments(); */ } /*! 析构函数 */ OMainWindow::~OMainWindow(void) { } void OMainWindow::paintEvent(QPaintEvent * event) { Q_UNUSED(event); } void OMainWindow::InitLayout() { //左侧图片栏 _labelOriImg = new QLabel; _labelResImg = new QLabel; //右侧按钮区域垂直 QHBoxLayout *mainBox = new QHBoxLayout; QVBoxLayout *btnBox = new QVBoxLayout; //主要放按钮 mainBox->addWidget(_labelOriImg); mainBox->addWidget(_labelResImg); mainBox->addLayout(btnBox); //在水平布局里加入垂直布局 btnBox->addStretch(5); btnBox->addWidget(_btnOpenImg); btnBox->addWidget(_lineEditInputRgb); btnBox->addWidget(_btnProcessImg); btnBox->addWidget(_lineEditInputReplaceRgb); btnBox->addWidget(_btnReplaceImg); btnBox->addWidget(_btnSaveImg); btnBox->addStretch(5); btnBox->setSpacing(20); slider = new QSlider(Qt::Horizontal); _labelSliderNum = new QLabel; QHBoxLayout *sliderHLayout = new QHBoxLayout; sliderHLayout->addWidget(slider); sliderHLayout->addSpacing(10); sliderHLayout->addWidget(_labelSliderNum); sliderHLayout->addSpacing(15); sliderHLayout->addWidget(_btnExchangeImg); sliderHLayout->addSpacing(30); QVBoxLayout *mainVBox = new QVBoxLayout; mainVBox->addLayout(mainBox); mainVBox->addLayout(sliderHLayout); mainVBox->addSpacing(100); QWidget* pCentralBox = new QWidget(this); this->setCentralWidget(pCentralBox); //两种都可以 this->setLayout(mainVBox); //centralWidget()->setLayout(mainVBox); pCentralBox->setLayout(mainVBox); pCentralBox->setFixedSize(806, 600); } void OMainWindow::InitObj() { _btnOpenImg = new QPushButton(); _btnProcessImg = new QPushButton; _btnReplaceImg = new QPushButton; _btnSaveImg = new QPushButton; _btnExchangeImg = new QPushButton; _lineEditInputRgb = new QLineEdit; _lineEditInputReplaceRgb = new QLineEdit; } void OMainWindow::ReLayout() { //左侧图片栏 _labelOriImg->setFixedSize(260, 260); _labelResImg->setFixedSize(260, 260); //右侧功能栏 _btnOpenImg->setFixedSize(60, 25); _btnOpenImg->setText(tr("Upload...")); _btnOpenImg->setStyleSheet("QPushButton{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3498db, stop:1 #2980b9);" "border:2px solid #2980b9;" "color: #ecf0f1;" "border-radius: 5px;" "}" "QPushButton:hover{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #2980b9, stop:1 #2477a8);" "color: #ecf0f1" "border:2px solid #2477a8;" "}"); _lineEditInputRgb->setPlaceholderText("输入RGB参数,255,255,255"); _lineEditInputRgb->setFixedSize(200, 30); _btnProcessImg->setFixedSize(60, 25); _btnProcessImg->setText(tr("开始抠图")); _btnProcessImg->setDisabled(true); _btnProcessImg->setStyleSheet("QPushButton{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3498db, stop:1 #2980b9);" "border:2px solid #2980b9;" "color: #ecf0f1;" "border-radius: 5px;" "}" "QPushButton:hover{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #2980b9, stop:1 #2477a8);" "color: #ecf0f1" "border:2px solid #2477a8;" "}"); _lineEditInputReplaceRgb->setPlaceholderText("输入要替换的RGB参数,255,255,255"); _lineEditInputReplaceRgb->setFixedSize(200, 30); _btnReplaceImg->setFixedSize(60, 25); _btnReplaceImg->setText("开始替换"); _btnReplaceImg->setDisabled(true); _btnReplaceImg->setStyleSheet("QPushButton{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3498db, stop:1 #2980b9);" "border:2px solid #2980b9;" "color: #ecf0f1;" "border-radius:5px;" "}" "QPushButton:hover{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #2980b9, stop:1 #2477a8);" "color: #ecf0f1" "border:2px solid #2477a8;" "}"); _btnSaveImg->setFixedSize(60, 25); _btnSaveImg->setText("保存图片"); _btnSaveImg->setStyleSheet("QPushButton{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3498db, stop:1 #2980b9);" "border:2px solid #2980b9;" "color: #ecf0f1;" "border-radius: 5px;" "}" "QPushButton:hover{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #2980b9, stop:1 #2477a8);" "color: #ecf0f1" "border:2px solid #2477a8;" "}"); _btnExchangeImg->setFixedSize(60, 25); _btnExchangeImg->setText("继续处理"); _btnExchangeImg->setDisabled(true); _btnExchangeImg->setStyleSheet("QPushButton{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3498db, stop:1 #2980b9);" "border:2px solid #2980b9;" "color: #ecf0f1;" "border-radius: 5px;" "}" "QPushButton:hover{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #2980b9, stop:1 #2477a8);" "color: #ecf0f1" "border:2px solid #2477a8;" "}"); _labelOriImg->setText("请上传待处理的图片"); _labelOriImg->setStyleSheet( "QLabel{" "border: 2px dashed #808080;" "background-color: #e0e0e0;" "color: #000000;" "font-size:18px;" "border-radius:5px;" "text-align:center;" "}"); _labelResImg->setText("下方滑动选择色差阈值范围"); _labelResImg->setStyleSheet( "QLabel{" "border: 2px dashed #808080;" "background-color: #e0e0e0;" "color: #000000;" "font-size:18px;" "border-radius:5px;" "text-align:center;" "}"); slider->setRange(0, 300); slider->setValue(0); slider->setStyleSheet("QSlider::groove:horizontal{" "border:1px solid #999999;" "height:10px;" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1CCB9, stop:1 #ebeae4);" "margin:2px 0;}" "QSlider::handle:horizontal{" "background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #45AAB4, stop:1 #77D9E0);" "border:1px solid #5c5c5c;" "width:18px;" "margin:-8px 0;" "border-radius:9px;" "}"); slider->setFixedWidth(500); _labelSliderNum->setFixedSize(50, 25); _labelSliderNum->setText("0"); _labelSliderNum->setAlignment(Qt::AlignCenter); _labelSliderNum->setStyleSheet("background-color:lightgray;border:1px solid gray;" "padding:5px;" "border - radius:5px;" ); this->setStyleSheet("" "QWidget{" "background-color:#80C7E2;" "border: 2px solid #447799;" "border-radius:10px;" "padding:2px;" "color:2D3D4D;" "}" "QWidget:hover{" "background-color:#A6D1E8;" "border:2px solid #6699CC;" "}" "QWidget:pressed{" "background-color:#6699CC;" "border:2px solid #447799;" "}"); } void OMainWindow::InitSlots() { //抠图 connect(_btnProcessImg, &QPushButton::clicked, [=]() { if (_lineEditInputRgb->text().trimmed() != "") { isCut = true; isReplace = false; processImage(); hasResult = true; _btnExchangeImg->setDisabled(false); } else { QMessageBox::information(this, "提示", "请先填写需要扣掉的RGB参数!"); } }); //替换 connect(_btnReplaceImg, &QPushButton::clicked, [=]() { if (_lineEditInputReplaceRgb->text().trimmed() != "") { isCut = false; isReplace = true; processImage(); hasResult = true; _btnExchangeImg->setDisabled(false); } else { QMessageBox::information(this, "提示", "请先填写需要替换的RGB参数!"); } }); //上传图片 connect(_btnOpenImg, &QPushButton::clicked, [=]() { hasResult = false; _labelResImg->setPixmap(QPixmap()); QString filePath = QFileDialog::getOpenFileName(this, "选择图片","", "图像文件(*.png *.jpg *.jpeg *.bmp)"); if (!filePath.isEmpty()) { //读取选定文件 QPixmap pixmap(filePath); //图片缩放处理 _labelOriImg->setPixmap(pixmap.scaled(250, 250, Qt::KeepAspectRatio, Qt::SmoothTransformation)); //保持图片不失真 } _btnProcessImg->setDisabled(false); _btnReplaceImg->setDisabled(false); }); //保存处理好的图片 connect(_btnSaveImg, &QPushButton::clicked, [=]() { if (hasResult) { QString resultPath = QFileDialog::getSaveFileName(this, "选择图片", "", "(*.png)"); if (!resultPath.isEmpty()) { processedImage.save(resultPath); } } else { QMessageBox::information(this, "保存文件", "请先进行图片处理"); } }); //加不加this是否都可?? //继续处理 connect(_btnExchangeImg, &QPushButton::clicked, [=]() { _labelOriImg->setPixmap(processedImage.scaled(250, 250, Qt::KeepAspectRatio, Qt::SmoothTransformation)); _labelResImg->setPixmap(QPixmap()); }); //滑动条拖动 connect(slider, &QSlider::valueChanged, this, [=]() { colorDifferenceThreshold = slider->value(); _labelSliderNum->setText(QString::number(colorDifferenceThreshold)); }); //滑动条释放 connect(slider, &QSlider::sliderReleased, this, [=]() { if (_lineEditInputRgb->text().trimmed() != "") { processImage(); hasResult = true; _btnExchangeImg->setDisabled(false); } else { QMessageBox::information(this, "提示", "请先填写需要扣掉的RGB参数!"); } }); } //图片处理 void OMainWindow::processImage() { QString rgbNum = _lineEditInputRgb->text(); //被替换的rgb色 // 使用正则获取目标RGB参数 QRegularExpression regex("(\\d+),(\\d+),(\\d+)"); QRegularExpressionMatch match = regex.match(rgbNum); if(match.hasMatch()) { //提取参数 int red = match.captured(1).toInt(); int green = match.captured(2).toInt(); int blue = match.captured(3).toInt(); //定义背景颜色(122,122,202) backgroundColor.setRgb(red, green, blue); } // 要替换的颜色 QString replaceNum = _lineEditInputReplaceRgb->text(); // 使用正则获取目标RGB参数 QRegularExpression regexReplace("(\\d+),(\\d+),(\\d+)"); QRegularExpressionMatch matchReplace = regexReplace.match(replaceNum); if (matchReplace.hasMatch()) { //提取参数 int red = matchReplace.captured(1).toInt(); int green = matchReplace.captured(2).toInt(); int blue = matchReplace.captured(3).toInt(); //定义背景颜色(122,122,202) replaceColor.setRgb(red, green, blue); } QImage img = _labelOriImg->pixmap()->toImage(); int width = img.width(); int height = img.height(); QImage resultImg(width, height, QImage::Format_ARGB32); //创建一个带有alpha通道的图片 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { QColor pixelColor = QColor(img.pixel(x, y)); //获取当前像素点颜色值 if (isTransparent(pixelColor)) { //如果是透明像素,保持透明 resultImg.setPixel(x, y, qRgba(0, 0, 0, 0)); } else if (isBackGround(pixelColor)) { if (isCut && !isReplace) { //如果 当前像素点颜色与背景色匹配或者接近,设置alpha通道为0:完全透明 resultImg.setPixel(x, y, qRgba(pixelColor.red(), pixelColor.green(), pixelColor.blue(), 0)); } else if (!isCut && isReplace) { //如果 当前像素点颜色与背景色匹配或者接近,替换为目标颜色 resultImg.setPixel(x, y, qRgba(replaceColor.red(), replaceColor.green(), replaceColor.blue(), 255)); } } else { //保留当前颜色 resultImg.setPixel(x, y, qRgba(pixelColor.red(), pixelColor.green(), pixelColor.blue(), 255)); } } } processedImage = QPixmap::fromImage(resultImg); _labelResImg->setPixmap(processedImage); } bool OMainWindow::isTransparent(const QColor & color) { return color.alpha() == 0; } bool OMainWindow::isBackGround(const QColor & color) { // 计算颜色值差异 int colorDifference = std::abs(color.red() - backgroundColor.red()) + std::abs(color.green() - backgroundColor.green()) + std::abs(color.blue() - backgroundColor.blue()); return colorDifference < colorDifferenceThreshold; } //-------------------略-------------------------------- //----------------------------------------------------------------------------------- void OMainWindow::about() { QMessageBox::about(this, tr("About"), tr("ExeDemo")); } //----------------------------------------------------------------------------------- void OMainWindow::createMainFrame() { QWidget* pCentralBox = new QWidget(this); QVBoxLayout*pCentralBoxLayout = new QVBoxLayout(pCentralBox); pCentralBoxLayout->setMargin(0); pCentralBox->setLayout(pCentralBoxLayout); setCentralWidget(pCentralBox); //窗口按钮:确定取消应用 QDialogButtonBox* hbuttonbox = new QDialogButtonBox; okbutton = hbuttonbox->addButton(tr("OK"), QDialogButtonBox::AcceptRole); cancelbutton = hbuttonbox->addButton(tr("Cancel"), QDialogButtonBox::NoRole); applybutton = hbuttonbox->addButton(tr("Apply"), QDialogButtonBox::ApplyRole); hbuttonbox->setCenterButtons(true); pCentralBoxLayout->addWidget(hbuttonbox); pCentralBoxLayout->addSpacing(5); // signal and slot connect(okbutton, SIGNAL(clicked()), this, SLOT(ok())); connect(cancelbutton, SIGNAL(clicked()), this, SLOT(cancel())); connect(applybutton, SIGNAL(clicked()), this, SLOT(apply())); } //------------------------------------------------------------------------------------------------ void OMainWindow::apply() { } //-------------------------------------------------------------------------------------------------- void OMainWindow::ok() { this->apply(); this->close(); } //-------------------------------------------------------------------------------------------------- void OMainWindow::cancel() { this->close(); } void OMainWindow::write() { textedit->appendHtml("1"); }
注意点
setstylesheet里面不要忘记加封号
待解决问题:
-
中文乱码
-
阅读开发规范
-
解决英文翻译中文问题
2023-11-14
问题1:英文翻译中文问题
进入qt的bin目录,打开cmd
调用命令:lupdate –verbose xxx.pro
lupdate -verbose E:\360MoveData\Users\13228\Desktop\qt项目\ConfigDemo\ExeDemoTr.pro
随后双击bin目录下的linguist.exe
打开对应的xxx.ts文件进行编辑
若生成不了则记得在项目中的xxx.pro中添加配置文件
问题2:往项目中添加新文件以后编译失败
问题原因为缺少moc_xxx.cpp文件
1>PictureWidget.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall PictureWidget::metaObject(void)const " (?metaObject@PictureWidget@@UBEPBUQMetaObject@@XZ)
解决方案
编译添加头文件的属性
-
将原先的General->Item Type中的C/C++ header改为Custom Build Tool
-
点击应用
-
在新出现的Custom Build Tool 中进行设置
Command Line $(QTDIR)\bin\moc.exe %(Filename).h -o tmp\moc\moc_%(Filename).cpp
Description Moc%27ing %(Filename).h ...
Outputs tmp\moc\moc_%(Filename).cpp;%(Outputs)
Additional Dependencies $(QTDIR)\bin\moc.exe;%(Filename).h;%(AdditionalInputs)
-
点击应用,确定。
-
随后右击xxx.h文件点击Compile进行编译
-
随后右击项目->add->Exist Item
-
添加文件进入项目后将其拖拽到moc文件夹下
-
整个项目重新编译即可成功
完成任务
-
搭建qt基础界面
-
解决项目添加问题
-
将stack窗口写到一个单独的类中
2023-11-15
问题1:不同页面间数据的传输问题
解决方案:
//定义signals //在发送数据页面定义信号 signals: void sendData(QString &); //发送数据时的信号 //在.cpp文件中设置connect,在设置connect之前先创建接受页面的实例对象 //接受页面在.h文件中写为StackWindow* stackWindow; stackWindow = new StackWindow(); connect(this, SIGNAL(sendData(QString &)), stackWindow, SLOT(receiveData(QString &))); //定义private slots //在接受数据页面定义槽函数 private slots: void receiveData(QString &); //接收传递过来的数据的槽 //定义槽函数 void StackWindow::receiveData(QString &str) { configFilePath = str; configFilePath.replace("/", "\\\\"); //QMessageBox::information(this, "repeat", configFilePath); }
问题2:如何在页面创建后触发信号,因为要在接受到别的页面数据后再使用该数据设置页面信息
解决方案:在Qt中,当一个窗口(如QMainWindow或者QDialog)创建成功后,会触发showEvent
。showEvent
是QWidget的一个事件,当窗口被显示时会触发该事件。你可以重写showEvent
函数来处理窗口显示后的逻辑。
protected: //重写ShowEvent信号,使其在窗口显示时发送一个信号 void showEvent(QShowEvent *event) override { emit buildOverSignal(); initSetConfigration(); QWidget::showEvent(event); }
问题3:QSettings读取文件路径问题
解决方案:使用英文路径
将所有的“/”替换为"\ \ "
configFilePath.replace("/", "\\\\");
问题4:ini文件在contains中的路径
[common] dataserver=11.11 [config] autologin_ch=true
allKeyList.contains("common/dataserver")
问题5:.h在.cpp文件中创建的函数找不到在.h文件中的函数
解决方案:因为函数中使用了foreach,应该是新特性。换为for(xxx xxx : xxx)即可
完成任务
-
完成从不同页面数据传输到使用QSetings读取到ini文件的功能
-
封装ini读写类
待解决问题
-
继续完善ini读写类
2023-11-16
问题1:QSetting写入配置文件后注释消失
解决方案:
引入windows原生api WritePrivateProfileString
函数用于向INI文件中写入配置项的值
void IniFile::writeToIniFile(const QString& filePath, const QString& group, const QString& key, const QString& value) { LPCWSTR filePathW = reinterpret_cast<LPCWSTR>(filePath.utf16()); LPCWSTR groupW = reinterpret_cast<LPCWSTR>(group.utf16()); LPCWSTR keyW = reinterpret_cast<LPCWSTR>(key.utf16()); LPCWSTR valueW = reinterpret_cast<LPCWSTR>(value.utf16()); // 使用 WritePrivateProfileString 函数写入配置项值 /* 其中各参数的意义: LPCTSTR groupW 是INI文件中的一个字段名. LPCTSTR keyW 是lpAppName下的一个键名,通俗讲就是变量名. LPCTSTR valueW 是键值,也就是变量的值,不过必须为LPCTSTR型或CString型的. LPCTSTR filePathW 是完整的INI文件名. */ WritePrivateProfileString(groupW, keyW, valueW, filePathW); }
待解决问题
-
调整程序基本逻辑
-
悬浮显示ini文件中文注释
-
分类所有配置数据,设计新ui界面
完成任务
-
能够在启动时读取ini信息到界面
-
完成正则表达式
-
使用信号机制同步配置界面与配置文件
2023-11-17
问题1:Some bytes have been replaced with the Unicode substitution character while loading file.
解决方案,使用QTextStream和QTextCodec进行输入输出处理,示例代码如下:
//优化了读取和写入效率 //输入String void IniFile::saveValue(const QString & filePath, const QString & targetKey, const QString& value) { QFile file(filePath); QString newValue = value; if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { qDebug() << "Failed to open" << filePath; return; } //创建文本流 QTextStream in(&file); QTextCodec *codec = QTextCodec::codecForName("UTF-8"); in.setCodec(codec); QStringList fileLines; qint64 targetPosition = 0; //用于记录目标键值对的位置 while (!in.atEnd()) { QString line = in.readLine().trimmed(); if (line.contains('=')) { QStringList parts = line.split('='); if (parts.size() == 2) { QString key = parts[0].trimmed(); QString value = parts[1].trimmed(); if (key == targetKey) { targetPosition = in.pos() - line.length() - 2; break; } } } fileLines.append(line); } //定位到特定位置以刷新内容 if (targetPosition > 0) { file.seek(targetPosition); QTextStream out(&file); out.setCodec("UTF-8"); out << targetKey << "=" << newValue << endl; out.flush(); file.close(); }
问题2:the line endings in the following file are not consistent.
详见csdn,待补充
完成任务
-
显示注释功能完成
-
因为要部署到多种平台所以弃用Windows原生API来写入ini配置文件,改为使用QFile写入
-
读入配置文件功能封装为了一个独立的类,代码如下:
//IniFile.h #pragma once #include <QString> #include <QStringList> #include <QDebug> #include <QSettings> #include <QtCore/QStringList> #include <QtCore/QDebug> #include <QtCore> #include "windows.h" #include "tchar.h" #include <iostream> #include <string> #include <QCoreApplication> #include <QTextCodec> class IniFile { public: IniFile(QString fileName); ~IniFile() { delete iniSetting; } //获得值 //返回group的key下的value QVariant getValue(const QString&, const QString&) const; //返回所有key QStringList getAllKey() const; //返回group的所有key QStringList getKey(const QString&) const; //返回所有group QStringList getGroup() const; //返回当前ini文件的路径 QString getFilePath() const; //返回当前值的注释 QString getComment(const QString& filePath, const QString& targetKey); //在group的key下写入value void saveValue(const QString& filePath, const QString& targetKey, const QString& value); void saveValue(const QString& filePath, const QString& targetKey, const bool& value); void saveValue(const QString& filePath, const QString& targetKey, const int& value); //使用QSettings修改配置文件,注释会消失 //void saveValue(const QString&, const QString&, const QStringList&); //QVariant saveValue(const QString&, const QString&, const bool&); //QVariant saveValue(const QString&, const QString&, const int&); //QVariant saveValue(const QString&, const QString&, const QString&); //打印信息 //打印所有组 void printAllGroup() const; //打印所有key void printAllKey() const; //打印group下的所有key void printKey(const QString&) const; //打印group的key下的所有value void printAllValue(const QString&, const QString&) const; //打印所有group的全部信息 void printAllInfo() const; //删除操作 //删除所有group void clear(); //移除group下的key void remove(const QString&, const QString&); //移除group void remove(const QString&); //判断当前group下是否有key bool hasKey(const QString&, const QString&) const; bool hasGroup(const QString&) const; bool hasValue(const QString&, const QString&, const QString&) const; //打开或关闭写入和原值不重复的value void onInsertDeduplication(); void offInsertDeduplication(); //打开或关闭对即将写的value去重 void onValueDeduplication(); void offValueDeduplication(); //打开或关闭覆盖写入value void onCoverWrite(); void offCoverWrite(); private: QSettings* iniSetting;//指向QSettings对象的指针 bool isCoverWrite;//是否覆盖写入value bool isInsertDeduplication;//是否插入重复的value bool isValueDeduplication;//对即将插入的值去重复 //不允许复制操作 //IniFile(const IniFile&);//复制操作符函数 //IniFile& operator=(const IniFile&);//赋值操作符函数 };
//IniFile.cpp #include "IniFile.h" #include <QVariant> #include <QDebug> #include <QFileInfo> IniFile::IniFile(QString fileName) { isInsertDeduplication = false; isValueDeduplication = false; isCoverWrite = true; iniSetting = new QSettings(fileName, QSettings::IniFormat); iniSetting->setIniCodec(QTextCodec::codecForName("utf-8")); //读写ini文件中的中文 } //获取注释 QString IniFile::getComment(const QString& filePath, const QString& targetKey) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Failed to open" << filePath; return -1; } QTextStream in(&file); //QTextCodec *codec = QTextCodec::codecForName("UTF-8"); //in.setCodec(codec); in.setCodec("UTF-8"); //解决中文乱码问题 QString targetComment; while (!in.atEnd()) { QString line = in.readLine().trimmed(); if (line.startsWith(';')) { targetComment = line.mid(1).trimmed(); } else if (line.startsWith('[') && line.endsWith(']')) { targetComment.clear(); } else if (line.contains('=')) { QStringList parts = line.split('='); if (parts.size() == 2) { QString key = parts[0].trimmed(); QString value = parts[1].trimmed(); if (key == targetKey) { qDebug().noquote() << "Key:" << key; if (!targetComment.isEmpty()) { return targetComment; } } } } } return ""; file.close(); } //优化了读取和写入效率 //输入String void IniFile::saveValue(const QString & filePath, const QString & targetKey, const QString& value) { QFile file(filePath); QString newValue = value; if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { qDebug() << "Failed to open" << filePath; return; } //创建文本流 QTextStream in(&file); QTextCodec *codec = QTextCodec::codecForName("UTF-8"); in.setCodec(codec); //in.setCodec("UTF-8"); //解决中文乱码问题 QStringList fileLines; qint64 targetPosition = 0; //用于记录目标键值对的位置 while (!in.atEnd()) { QString line = in.readLine().trimmed(); if (line.contains('=')) { QStringList parts = line.split('='); if (parts.size() == 2) { QString key = parts[0].trimmed(); QString value = parts[1].trimmed(); if (key == targetKey) { targetPosition = in.pos() - line.length() - 2; break; } } } fileLines.append(line); } //定位到特定位置以刷新内容 if (targetPosition > 0) { file.seek(targetPosition); QTextStream out(&file); out.setCodec("UTF-8"); out << targetKey << "=" << newValue << endl; out.flush(); //file.write((targetKey + " = " + newValue + "\n").toLocal8Bit()); } file.close(); //定位到特定位置以刷新内容 /* if (targetPosition > 0) { file.seek(targetPosition); file.write((targetKey + " = " + newValue + "\n").toLocal8Bit()); } file.close(); */ } //输入bool void IniFile::saveValue(const QString & filePath, const QString & targetKey, const bool& value) { QFile file(filePath); QString newValue = value ? "true" : "false"; if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { qDebug() << "Failed to open" << filePath; return; } //创建文本流 QTextStream in(&file); QTextCodec *codec = QTextCodec::codecForName("UTF-8"); in.setCodec(codec); //in.setCodec("UTF-8"); //解决中文乱码问题 QStringList fileLines; qint64 targetPosition = 0; //用于记录目标键值对的位置 while (!in.atEnd()) { QString line = in.readLine().trimmed(); if (line.contains('=')) { QStringList parts = line.split('='); if (parts.size() == 2) { QString key = parts[0].trimmed(); QString value = parts[1].trimmed(); if (key == targetKey) { targetPosition = in.pos() - line.length() - 2; break; } } } fileLines.append(line); } //定位到特定位置以刷新内容 if (targetPosition > 0) { file.seek(targetPosition); QTextStream out(&file); out.setCodec("UTF-8"); out << targetKey << "=" << newValue << endl; out.flush(); //file.write((targetKey + " = " + newValue + "\n").toLocal8Bit()); } file.close(); } //输入int void IniFile::saveValue(const QString & filePath, const QString & targetKey, const int& value) { QFile file(filePath); QString newValue = QString::number(value); if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { qDebug() << "Failed to open" << filePath; return; } //创建文本流 QTextStream in(&file); QTextCodec *codec = QTextCodec::codecForName("UTF-8"); in.setCodec(codec); //in.setCodec("UTF-8"); //解决中文乱码问题 QStringList fileLines; qint64 targetPosition = 0; //用于记录目标键值对的位置 while (!in.atEnd()) { QString line = in.readLine().trimmed(); if (line.contains('=')) { QStringList parts = line.split('='); if (parts.size() == 2) { QString key = parts[0].trimmed(); QString value = parts[1].trimmed(); if (key == targetKey) { targetPosition = in.pos() - line.length() - 2; break; } } } fileLines.append(line); } //定位到特定位置以刷新内容 if (targetPosition > 0) { file.seek(targetPosition); QTextStream out(&file); out.setCodec("UTF-8"); out << targetKey << "=" << newValue << endl; out.flush(); //file.write((targetKey + " = " + newValue + "\n").toLocal8Bit()); } file.close(); } //返回group的key下的value QVariant IniFile::getValue(const QString& group, const QString& key) const { QVariant variant = iniSetting->value(QString(group + "/" + key)); //QStringList value = variant.value<QStringList>(); //qDebug() << "value:" << value; return variant; } QStringList IniFile::getAllKey() const { return iniSetting->allKeys(); } QStringList IniFile::getKey(const QString &group) const { iniSetting->beginGroup(group); QStringList keyList = iniSetting->childKeys(); iniSetting->endGroup(); return keyList; } QStringList IniFile::getGroup() const { QStringList groupList = iniSetting->childGroups(); return groupList; } /* 弃用,修改文件后注释消失 void IniFile::saveValue(const QString& group, const QString& key, const QStringList& values) { //结构 * {isValue:1 isCover-> {noValue:2 //Cover-> [isInsert:3 {isValue-> [noInsert:4 noCover-> [isInsert:5 {noValue [noInsert:6 /// \brief resVariant QVariant resVariant; iniSetting->beginGroup(group); if (isCoverWrite) {//如果覆盖写入,则直接写入 if (isValueDeduplication) {//即将插入的值去重 QStringList resValues;//新建QStringList去重 for (int i = 0; i < values.size(); i++) { if (resValues.indexOf(values.at(i)) == -1) { resValues.push_back(values.at(i)); } } resVariant.setValue(resValues); //qDebug()<<"test1"; } else {//即将插入的值不去重复 resVariant.setValue(values); //qDebug()<<"test2"; } } else //不覆盖写入 { QVariant variant = iniSetting->value(key); QStringList originalValue = variant.value<QStringList>(); if (isValueDeduplication) {//即将插入的值去重 if (isInsertDeduplication) {//即将插入和原有值不同的值 //foreach(QString tempValue, values) { for(QString tempValue : values){ if (originalValue.indexOf(tempValue) == -1) { originalValue.push_back(tempValue); } } qDebug() << "test3"; } else {//即将插入的值和原有值的值可以相同 QStringList resValues;//新建QStringList对即将插入的值去重 for (int i = 0; i < values.size(); i++) { if (resValues.indexOf(values.at(i)) == -1) { resValues.push_back(values.at(i)); } } //foreach(QString tempValue, resValues) { for (QString tempValue : resValues) { originalValue.push_back(tempValue); } } qDebug() << "test4"; } else {//即将插入的值不去重 if (isInsertDeduplication) {//即将插入和原有值不同的值 QStringList resValues; //foreach(QString tempValue, values) { for (QString tempValue : values) { if (originalValue.indexOf(tempValue) == -1) { resValues.push_back(tempValue); } } //foreach(QString tempValue, resValues) { for (QString tempValue : resValues) { originalValue.push_back(tempValue); } qDebug() << "test5"; } else {//即将插入的值和原有值可以相同 //foreach(QString tempValue, values) { for (QString tempValue : values) { originalValue.push_back(tempValue); } qDebug() << "test6"; } } resVariant.setValue(originalValue); } iniSetting->setValue(key, resVariant); iniSetting->endGroup(); //在原有的基础上进行去重复 // for(int i = 0; i < values.size() ;i++){ // for(int j = i + 1; j < values.size(); j++){ // int indexFind = values.indexOf(values.at(i), j); // if(indexFind != -1){ // values.removeAt(indexFind); // } // } // } } */ void IniFile::printAllGroup() const { QStringList groupList = iniSetting->childGroups(); for (QString group : groupList) { qDebug() << "group:" << group; } //foreach(QString group, groupList) { // qDebug() << "group:" << group; //} } void IniFile::printAllKey() const { qDebug() << iniSetting->allKeys(); } void IniFile::printKey(const QString& group) const { iniSetting->beginGroup(group); QStringList keyList = iniSetting->childKeys(); qDebug() << "allKeys : " << keyList << endl; iniSetting->endGroup(); } void IniFile::printAllValue(const QString& group, const QString& key) const { iniSetting->beginGroup(group); QVariant variant = iniSetting->value(key); QStringList valueList = variant.value<QStringList>(); qDebug() << "values size:" << valueList.size(); qDebug() << "allValues:" << valueList; iniSetting->endGroup(); } void IniFile::printAllInfo() const { QStringList groupList = iniSetting->childGroups(); //foreach(QString group, groupList) { for (QString group : groupList) { qDebug() << "group:" << group << endl; iniSetting->beginGroup(group); QStringList keys = iniSetting->childKeys(); qDebug() << "Keys : " << keys << endl; //foreach(QString key, keys) for (QString key : keys) { { QVariant variant = iniSetting->value(key); QStringList values = variant.value<QStringList>(); qDebug() << "values size:" << values.size() << endl; qDebug() << "allValues:" << values << endl; } iniSetting->endGroup(); } } } void IniFile::clear() { iniSetting->clear(); } QString IniFile::getFilePath() const { return iniSetting->fileName(); } void IniFile::onInsertDeduplication() { isInsertDeduplication = true; } void IniFile::offInsertDeduplication() { isInsertDeduplication = false; } void IniFile::onCoverWrite() { isCoverWrite = true; } void IniFile::offCoverWrite() { isCoverWrite = false; } void IniFile::remove(const QString& group, const QString& key) { iniSetting->beginGroup(group); iniSetting->remove(key); iniSetting->endGroup(); } void IniFile::remove(const QString& group) { iniSetting->beginGroup(group); iniSetting->remove(""); iniSetting->endGroup(); } //判断当前group下是否有key bool IniFile::hasKey(const QString &group, const QString &key) const { bool res; iniSetting->beginGroup(group); res = iniSetting->contains(key); iniSetting->endGroup(); return res; } //判断是否有group bool IniFile::hasGroup(const QString& group) const { QStringList groupList = iniSetting->childGroups(); // qDebug()<<"groupList:"<<groupList; if (groupList.indexOf(group) == -1) { return false; } else { return true; } } //判断当前group下的key是否有vlaue bool IniFile::hasValue(const QString& group, const QString& key, const QString& value) const { bool res; iniSetting->beginGroup(group); QVariant variant = iniSetting->value(key); QStringList valueList = variant.value<QStringList>(); if (valueList.indexOf(value) == -1) { res = false; } else { res = true; } iniSetting->endGroup(); return res; } void IniFile::onValueDeduplication() { isValueDeduplication = true; } void IniFile::offValueDeduplication() { isValueDeduplication = false; }
待解决问题
-
图像UI界面设计
-
LineEdit基本逻辑修改
-
画出程序运行基本逻辑图
2023-11-18
问题1:SIGNAL(editingFinished()信号按下回车后触发两次
bool flagServerAddressEnter = false; //解决按下回车后触发两次信号问题 void StackWindow::isTrueServerAddress() { if (serverAddressLineEdit->hasFocus()) { flagServerAddressEnter = true; isServerAddress(); } else if (!serverAddressLineEdit->hasFocus() && !flagServerAddressEnter) { //解决按下回车后触发两次信号问题 flagServerAddressEnter = true; isServerAddress(); } else if (!serverAddressLineEdit->hasFocus() && flagServerAddressEnter) { flagServerAddressEnter = false; } }
悬浮注释功能只需显示字符“-”后方的文字