项目简介

  • 开发平台

    • win10
    • Qt6.6
    • msvc2022
  • 简介

    微信上有一些好玩的游戏, 找不同一种比较轻松有趣的游戏,也曾经在街机上被坑过N币, 玩了几次后,发现还是太难了,于是开始截屏放大,慢慢找,再然后就发展到截图发送到QQ的我的电脑里,用程序查找标记

    看效果:

    • 截屏的图

FindDiff_Qt找不同项目-LMLPHP

FindDiff_Qt找不同项目-LMLPHP

  • FindDiff_Qt Qt 版本的找不同
    • 交互性强点
    • 用 ps 2019 切片比较方便
    • 默认 qq的 “我的电脑”的目录并自动监视该目录,当有新的文件出现时,会自动加载并查找不同处,而且每次对比前会自动删除该目录下的其他jpg图片,需要注意

源代码

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 = "E:/Users/Administrator/Documents/Tencent Files/273135482/FileRecv/MobileFile";


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

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

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

    QFile file("D:/Project/qtdemos/32_opencv/FindDiff_Qt/找不同.json");  // 数据文件路径
    if(file.open(QFile::ReadOnly)) {
        auto byte = file.readAll();
        QJsonParseError JsonParseError ;
        QJsonDocument doc = QJsonDocument::fromJson(byte, &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());
    //    找不同
    //    src = srcImg.copy(16,294,1096,729);
    //    dst = srcImg.copy(16,1055,1096,729);
    //    小花找不同
    //    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(&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()  // 红色
                  ||qAbs( (qGreen(srcPix)-qGreen(dstPix) ) )  > ui->spinBox->value()  // 绿色
                  ||qAbs( (qBlue (srcPix)-qBlue (dstPix) ) )  > ui->spinBox->value() ) // 蓝色
                )
            {
                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>找不同             p1(16,293)   p2(16,1055)  1096 x 729</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>小花找不同      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\xxx保密需要xxx\FileRecv\MobileFile</string>
           </property>
          </widget>
         </item>
         <item>
          <layout class="QHBoxLayout" name="horizontalLayout">
           <item>
            <widget class="QLabel" name="label_6">
             <property name="text">
              <string>色差</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>颜色</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>开始</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>

配置文件

找不同.json

[
	{
		"title":"找不同",
		"x1":16,
		"y1":294,
		"x2":16,
		"y2":1055,
		"w":1096,
		"h":729
	},
	{
		"title":"小花找不同-横向",
		"x1":53,
		"y1":441,
		"x2":53,
		"y2":1107,
		"w":1020,
		"h":636
	},
	{
		"title":"小花找不同-竖向",
		"x1":119,
		"y1":452,
		"x2":588,
		"y2":452,
		"w":465,
		"h":1057
	}
]
10-28 14:39