学习记录日志 2023-11-13 到 2023-11-19

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

image-20231114210112908

随后双击bin目录下的linguist.exe

打开对应的xxx.ts文件进行编辑

image-20231114210230127

若生成不了则记得在项目中的xxx.pro中添加配置文件

image-20231114212113872

问题2:往项目中添加新文件以后编译失败

问题原因为缺少moc_xxx.cpp文件

image-20231114101014620

1>PictureWidget.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall PictureWidget::metaObject(void)const " (?metaObject@PictureWidget@@UBEPBUQMetaObject@@XZ)

解决方案

编译添加头文件的属性

image-20231114104046368

  • 将原先的General->Item Type中的C/C++ header改为Custom Build Tool

  • 点击应用

  • 在新出现的Custom Build Tool 中进行设置

image-20231114104316883

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

image-20231114104612667

  • 添加文件进入项目后将其拖拽到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)创建成功后,会触发showEventshowEvent是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)即可

image-20231115213642452

完成任务

  • 完成从不同页面数据传输到使用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;
     }
 }

悬浮注释功能只需显示字符“-”后方的文字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值