FindDiff_Qt finds different items

Article directory

  • Project Description
  • source code
    • widget.h
    • widget.cpp
    • widget.ui
    • Configuration file
      • Find the difference.json

Project Introduction

  • Development Platform

    • win10
    • Qt6.6
    • msvc2022
  • Introduction

    There are some fun games on WeChat. I was looking for a more relaxed and interesting game. I was once cheated of N coins in an arcade. After playing it a few times, I found it was still too difficult, so I started to take screenshots and enlarge them, and slowly searched for them. Then it progressed to sending screenshots to my computer on QQ, and using the program to find the mark

    See the effect:

    • screenshot

  • FindDiff_Qt Find differences between Qt versions
    • More interactive
    • It is more convenient to use ps 2019 to slice
    • By default, QQ’s “My Computer” directory is automatically monitored. When a new file appears, it will be automatically loaded and the differences will be found. Other jpg images in this directory will be automatically deleted before each comparison. Please note that

Source code

widget.h

#pragma once

#include <QImage>
#include <QWidget>
#include <QFileSystemWatcher>
#include "ui_widget.h"


namespace Ui {<!-- -->
class Widget;
}

class MWidget : public QWidget
{<!-- -->
    Q_OBJECT

public:
    explicit MWidget(QWidget *parent = nullptr);
    ~MWidget();

private slots:
    void on_pushButton_start_clicked();
    bool loadImage();
    void showImages();
    void findDifferent();

    void setFrameColor(QColor color);

    void on_pushButton_color_clicked();

    void on_spinBox_valueChanged(int arg1);

    void on_horizontalSlider_valueChanged(int value);


    void on_spinBox_x1_valueChanged(int arg1);
    void on_spinBox_y1_valueChanged(int arg1);
    void on_spinBox_x2_valueChanged(int arg1);
    void on_spinBox_y2_valueChanged(int arg1);
    void on_spinBox_w_valueChanged(int arg1);
    void on_spinBox_h_valueChanged(int arg1);

    void on_comboBox_currentIndexChanged(int index);

public:
    Ui::Widget *ui;

private:

    QImage srcImg, src, dst, result;

    int label_src1_height;
    int label_src2_height;
    int label_result_height;

    QColor frameColor = QColor("#55ffff");
    QFileSystemWatcher fwatcher;

    QString workPath;

    // QWidget interface
protected:
    void resizeEvent(QResizeEvent *event);
};

widget.cpp

#include "widget.h"
#include "qout.h"
#include "ui_widget.h"

#include <QColorDialog>
#include <QDir>
#include <QDir>
#include <QFile>
#include <QFileSystemWatcher>
#include <QPainter>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

MWidget::MWidget(QWidget *parent):
    QWidget(parent),
    ui(new Ui::Widget)
{<!-- -->
    ui->setupUi(this);
    ui->label_src1->setAlignment(Qt::AlignCenter);
    ui->label_src2->setAlignment(Qt::AlignCenter);
    ui->label_result->setAlignment(Qt::AlignCenter);
    ui->pushButton_start->setFocusPolicy(Qt::StrongFocus);
    ui->pushButton_start->setFocus(Qt::TabFocusReason);
    ui->pushButton_start->setAutoFillBackground(true);
    ui->pushButton_start->setAutoDefault(true);
    // qout << focusNextChild() << focusWidget();
    // qout << focusNextChild() << focusWidget();
    // qout << focusNextChild() << focusWidget();

    ui->frame->setAutoFillBackground(true);
    ui->frame->setMaximumWidth(200);
    setFrameColor(frameColor);

    workPath = QDir::fromNativeSeparators(ui->lineEdit->text());
    fwatcher.addPath(workPath);

    connect( & amp;fwatcher, & amp;QFileSystemWatcher::fileChanged,this,[](const QString & amp;path){<!-- -->
        qout << path << "fileChanged";
    });

    connect( & amp;fwatcher, & amp;QFileSystemWatcher::directoryChanged,this,[this](const QString & amp;path){<!-- -->
        qout << path << "directoryChanged";
        on_pushButton_start_clicked();
    });

    QFile file("D:/Project/qtdemos/32_opencv/FindDiff_Qt/find the difference.json"); // Data file path
    if(file.open(QFile::ReadOnly)) {<!-- -->
        auto byte = file.readAll();
        QJsonParseError JsonParseError;
        QJsonDocument doc = QJsonDocument::fromJson(byte, & amp;JsonParseError);
        if(JsonParseError.error)
            qout << JsonParseError.errorString();

        QSignalBlocker b(ui->comboBox);
        ui->comboBox->clear();
        QJsonArray docJsonArray = doc.array();

        for (int i = 0; i < docJsonArray.size(); + + i) {<!-- -->
            QJsonObject obj = docJsonArray.at(i).toObject();
            QString title = obj["title"].toString();
            int x1 = obj["x1"].toInt();
            int y1 = obj["y1"].toInt();
            int x2 = obj["x2"].toInt();
            int y2 = obj["y2"].toInt();
            int w = obj["w"].toInt();
            int h = obj["h"].toInt();
            QString itemTxt("%1:\tP1(%2,%3)\tP2(%4,%5)\t%6 x %7");
            itemTxt = itemTxt.arg(title).arg(x1).arg(y1).arg(x2).arg(y2).arg(w).arg(h);
            ui->comboBox->addItem(itemTxt);

            QVariantList list;
            list << x1 << y1 << x2 << y2 << w << h;
            ui->comboBox->setItemData(i,list);
        }
    }

    on_comboBox_currentIndexChanged(0);
}

MWidget::~MWidget()
{<!-- -->
    delete ui;
}

void MWidget::on_pushButton_start_clicked()
{<!-- -->
    auto ok = loadImage();
    if(ok)
        findDifferent();
    showImages();
}

bool MWidget::loadImage()
{<!-- -->

    workPath = QDir::fromNativeSeparators(ui->lineEdit->text());
    qout << workPath;
    QDir dir(workPath);
    if(!dir.exists())
        return false;

    QStringList nameFilters;
    nameFilters << "*.jpg";
    QStringList fileNames = dir.entryList(nameFilters,QDir::Files,QDir::Name);
    qout << fileNames;
    if(fileNames.isEmpty())
        return false;

    QSignalBlocker block(fwatcher);
    for (int i = 0; i < fileNames.size()-1; + + i) {<!-- -->
        dir.remove(fileNames.at(i));
    }


    QString imageFile( dir.absoluteFilePath(fileNames.last()) );
    srcImg.load(imageFile);

    src = srcImg.copy(ui->spinBox_x1->value(),ui->spinBox_y1->value(),
                      ui->spinBox_w ->value(),ui->spinBox_h ->value());
    dst = srcImg.copy(ui->spinBox_x2->value(),ui->spinBox_y2->value(),
                      ui->spinBox_w ->value(),ui->spinBox_h ->value());
    //    find difference
    // src = srcImg.copy(16,294,1096,729);
    // dst = srcImg.copy(16,1055,1096,729);
    //Xiaohua looks for differences
    // src = srcImg.copy(119,452,465,1057);
    // dst = srcImg.copy(588,452,465,1057);
    result = dst;
    return true;
}

void MWidget::showImages()
{<!-- -->
    qout << "showImages";
    if(src.isNull())
        return ;
    ui->label_src1 ->setPixmap(QPixmap::fromImage(src) .scaledToHeight(ui->label_src1 ->height()-ui->label_src1->frameWidth() * 2));
    ui->label_src2 ->setPixmap(QPixmap::fromImage(dst) .scaledToHeight(ui->label_src2 ->height()-ui->label_src1->frameWidth() * 2));
    ui->label_result->setPixmap(QPixmap::fromImage(result) .scaledToHeight(ui->label_result->height()-ui->label_src1->frameWidth() * 2));
}

void MWidget::findDifferent()
{<!-- -->
    qout << "findDifferent";
    if(src.isNull())
        return ;
    QPainter painter;
    result = src;
    result = result.convertToFormat(QImage::Format_Grayscale8);
    result = result.convertToFormat(QImage::Format_RGB32);
    painter.begin( & amp;result);
    painter.setPen(frameColor);
    for (int i = 0; i < src.width(); + + i) {<!-- -->
        for (int j = 0; j < src.height(); + + j) {<!-- -->
            QRgb srcPix = src.pixel(i,j);
            QRgb dstPix = dst.pixel(i,j);
            if ( ( qAbs( (qRed (srcPix) -qRed(dstPix) ) ) > ui->spinBox->value() // red
                  ||qAbs( (qGreen(srcPix)-qGreen(dstPix) ) ) > ui->spinBox->value() // green
                  ||qAbs( (qBlue (srcPix)-qBlue (dstPix) ) ) > ui->spinBox->value() ) // blue
                )
            {<!-- -->
                painter.drawPoint(i,j);
            }
        }
    }
    painter.end();
}

void MWidget::setFrameColor(QColor color)
{<!-- -->
    auto frame = ui->frame;
    QPalette p = frame->palette();
    p.setBrush( QPalette::Window, color);
    frame->setPalette(p);

}

void MWidget::resizeEvent(QResizeEvent */*event*/)
{<!-- -->
    if(src.isNull())
        return;
    showImages();
}


void MWidget::on_pushButton_color_clicked()
{<!-- -->
    auto color = QColorDialog::getColor(QColor(85,255,255));
    frameColor = color;
    setFrameColor(color);
    if(src.isNull()) return;
    findDifferent();
    ui->label_result->setPixmap(QPixmap::fromImage(result) .scaledToHeight(ui->label_result->height()-ui->label_src1->frameWidth() * 2));
}


void MWidget::on_spinBox_valueChanged(int arg1)
{<!-- -->
    ui->horizontalSlider->setValue(arg1);
}


void MWidget::on_horizontalSlider_valueChanged(int value)
{<!-- -->
    ui->spinBox->setValue(value);
    findDifferent();
    ui->label_result->setPixmap(QPixmap::fromImage(result) .scaledToHeight(ui->label_result->height()-ui->label_src1->frameWidth() * 2));
}


void MWidget::on_spinBox_x1_valueChanged(int arg1)
{<!-- -->
    on_pushButton_start_clicked();

}
void MWidget::on_spinBox_x2_valueChanged(int arg1)
{<!-- -->
    on_pushButton_start_clicked();
}
void MWidget::on_spinBox_y1_valueChanged(int arg1)
{<!-- -->
    on_pushButton_start_clicked();
}
void MWidget::on_spinBox_y2_valueChanged(int arg1)
{<!-- -->
    on_pushButton_start_clicked();
}
void MWidget::on_spinBox_w_valueChanged(int arg1)
{<!-- -->
    on_pushButton_start_clicked();
}
void MWidget::on_spinBox_h_valueChanged(int arg1)
{<!-- -->
    on_pushButton_start_clicked();
}


void MWidget::on_comboBox_currentIndexChanged(int index)
{<!-- -->
    auto vars = ui->comboBox->itemData(index).value<QVariantList>();
    qout << "=======" << index << vars;
    QSignalBlocker x1( ui->spinBox_x1 );
    QSignalBlocker y1( ui->spinBox_y1 );
    QSignalBlocker x2( ui->spinBox_x2 );
    QSignalBlocker y2( ui->spinBox_y2 );
    QSignalBlocker w (ui->spinBox_w);
    QSignalBlocker h (ui->spinBox_h);
    ui->spinBox_x1->setValue(vars.at(0).toInt());
    ui->spinBox_y1->setValue(vars.at(1).toInt());
    ui->spinBox_x2->setValue(vars.at(2).toInt());
    ui->spinBox_y2->setValue(vars.at(3).toInt());
    ui->spinBox_w ->setValue(vars.at(4).toInt());
    ui->spinBox_h ->setValue(vars.at(5).toInt());
}

widget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>873</width>
    <height>672</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>0</width>
    <height>300</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QGridLayout" name="gridLayout_3">
   <item row="0" column="0">
    <widget class="QLabel" name="label_src1">
     <property name="sizePolicy">
      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
       <horstretch>0</horstretch>
       <verstretch>0</verstretch>
      </sizepolicy>
     </property>
     <property name="minimumSize">
      <size>
       <width>400</width>
       <height>300</height>
      </size>
     </property>
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <property name="text">
      <string/>
     </property>
     <property name="buddy">
      <cstring>bottomright</cstring>
     </property>
    </widget>
   </item>
   <item row="0" column="1">
    <widget class="QLabel" name="label_result">
     <property name="sizePolicy">
      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
       <horstretch>0</horstretch>
       <verstretch>0</verstretch>
      </sizepolicy>
     </property>
     <property name="minimumSize">
      <size>
       <width>400</width>
       <height>300</height>
      </size>
     </property>
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <property name="text">
      <string/>
     </property>
    </widget>
   </item>
   <item row="1" column="0">
    <widget class="QLabel" name="label_src2">
     <property name="sizePolicy">
      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
       <horstretch>0</horstretch>
       <verstretch>0</verstretch>
      </sizepolicy>
     </property>
     <property name="minimumSize">
      <size>
       <width>400</width>
       <height>300</height>
      </size>
     </property>
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <property name="text">
      <string/>
     </property>
    </widget>
   </item>
   <item row="1" column="1">
    <widget class="QFrame" name="bottomright">
     <property name="minimumSize">
      <size>
       <width>400</width>
       <height>300</height>
      </size>
     </property>
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <widget class="QWidget" name="widget_2" native="true">
        <layout class="QGridLayout" name="gridLayout_2">
         <item row="0" column="0" colspan="4">
          <widget class="QComboBox" name="comboBox">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <item>
            <property name="text">
             <string>Find the difference p1(16,293) p2(16,1055) 1096 x 729</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>Little Flower Find Differences p1(119,452) p2(588,452) 465 x 1057</string>
            </property>
           </item>
          </widget>
         </item>
         <item row="1" column="0">
          <widget class="QLabel" name="label">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="text">
            <string>x1</string>
           </property>
          </widget>
         </item>
         <item row="1" column="1">
          <widget class="QSpinBox" name="spinBox_x1">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="maximum">
            <number>2000</number>
           </property>
           <property name="value">
            <number>119</number>
           </property>
          </widget>
         </item>
         <item row="1" column="2">
          <widget class="QLabel" name="label_7">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="text">
            <string>x2</string>
           </property>
          </widget>
         </item>
         <item row="1" column="3">
          <widget class="QSpinBox" name="spinBox_x2">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="maximum">
            <number>2000</number>
           </property>
           <property name="value">
            <number>588</number>
           </property>
          </widget>
         </item>
         <item row="2" column="0">
          <widget class="QLabel" name="label_2">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="text">
            <string>y1</string>
           </property>
          </widget>
         </item>
         <item row="2" column="1">
          <widget class="QSpinBox" name="spinBox_y1">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="maximum">
            <number>2000</number>
           </property>
           <property name="value">
            <number>452</number>
           </property>
          </widget>
         </item>
         <item row="2" column="2">
          <widget class="QLabel" name="label_5">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="text">
            <string>y2</string>
           </property>
          </widget>
         </item>
         <item row="2" column="3">
          <widget class="QSpinBox" name="spinBox_y2">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="maximum">
            <number>2000</number>
           </property>
           <property name="value">
            <number>452</number>
           </property>
          </widget>
         </item>
         <item row="3" column="0">
          <widget class="QLabel" name="label_3">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="text">
            <string>w</string>
           </property>
          </widget>
         </item>
         <item row="4" column="0">
          <widget class="QLabel" name="label_4">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="text">
            <string>h</string>
           </property>
          </widget>
         </item>
         <item row="3" column="1" colspan="3">
          <widget class="QSpinBox" name="spinBox_w">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="maximum">
            <number>2000</number>
           </property>
           <property name="value">
            <number>465</number>
           </property>
          </widget>
         </item>
         <item row="4" column="1" colspan="3">
          <widget class="QSpinBox" name="spinBox_h">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="maximum">
            <number>2000</number>
           </property>
           <property name="value">
            <number>1057</number>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
      <item>
       <widget class="QFrame" name="frame1">
        <property name="frameShape">
         <enum>QFrame::Box</enum>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout_2">
         <item>
          <widget class="QLineEdit" name="lineEdit">
           <property name="text">
            <string>D:\Users\Administrator\Documents\Tencent Files\xxxConfidentiality requiredxxx\FileRecv\MobileFile</string>
           </property>
          </widget>
         </item>
         <item>
          <layout class="QHBoxLayout" name="horizontalLayout">
           <item>
            <widget class="QLabel" name="label_6">
             <property name="text">
              <string>Color difference</string>
             </property>
             <property name="alignment">
              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QSlider" name="horizontalSlider">
             <property name="value">
              <number>20</number>
             </property>
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QSpinBox" name="spinBox">
             <property name="maximum">
              <number>255</number>
             </property>
             <property name="value">
              <number>40</number>
             </property>
            </widget>
           </item>
          </layout>
         </item>
         <item>
          <layout class="QHBoxLayout" name="horizontalLayout_3">
           <item>
            <spacer name="horizontalSpacer_2">
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
             </property>
             <property name="sizeHint" stdset="0">
              <size>
               <width>153</width>
               <height>20</height>
              </size>
             </property>
            </spacer>
           </item>
           <item>
            <widget class="QFrame" name="frame">
             <property name="minimumSize">
              <size>
               <width>100</width>
               <height>0</height>
              </size>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QPushButton" name="pushButton_color">
             <property name="text">
              <string>Color</string>
             </property>
            </widget>
           </item>
          </layout>
         </item>
         <item>
          <layout class="QHBoxLayout" name="horizontalLayout_4">
           <item>
            <spacer name="horizontalSpacer">
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
             </property>
             <property name="sizeHint" stdset="0">
              <size>
               <width>278</width>
               <height>20</height>
              </size>
             </property>
            </spacer>
           </item>
           <item>
            <widget class="QPushButton" name="pushButton_start">
             <property name="text">
              <string>Start</string>
             </property>
            </widget>
           </item>
          </layout>
         </item>
        </layout>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
  </layout>
 </widget>
 <tabstops>
  <tabstop>lineEdit</tabstop>
  <tabstop>horizontalSlider</tabstop>
  <tabstop>spinBox</tabstop>
  <tabstop>pushButton_color</tabstop>
  <tabstop>pushButton_start</tabstop>
 </tabstops>
 <resources/>
 <connections/>
</ui>

Configuration file

Find the difference.json

[
{<!-- -->
"title":"Find the difference",
"x1":16,
"y1":294,
"x2":16,
"y2":1055,
"w":1096,
"h":729
},
{<!-- -->
"title":"Little Flowers Find Differences-Horizontal",
"x1":53,
"y1":441,
"x2":53,
"y2":1107,
"w":1020,
"h":636
},
{<!-- -->
"title":"Little Flowers Find Differences-Vertical",
"x1":119,
"y1":452,
"x2":588,
"y2":452,
"w":465,
"h":1057
}
]