提交 904cc4d9 编写于 作者: mahuifa's avatar mahuifa

Merge branch 'Dev'

......@@ -13,7 +13,8 @@
| UseQThreadPool | Qt使用线程池QThreadPool示例 |
| RunFunction | QtConcurent::run使用示例,在另一个线程中运行一个函数。 |
| Map | QtConcurrent::map使用示例,可以在多线程环境下高效地处理大量数据,<br>并且可以返回一个QFuture对象,可以使用它来跟踪数据处理的进度。 |
| | |
| Mapped | QtConcurrent::mapped使用示例,与 map() 类似,<br/>不同之处在于它返回了一个包含返回值的新容器。 |
| MappedReduced | QtConcurrent::mappedReduced使用示例,与mapped()类型,<br/>相当于将mapped()的结果放入到一个单线程函数中进行计算 |
......@@ -78,3 +79,23 @@
> 2. 使用QtConcurrent::map()在多线程环境下批量执行成员函数。
![image-20230226215928039](ConcurrentExamples.assets/image-20230226215928039.png)
### 1.7 Mapped
> QtConcurrent::mapped使用示例,与 map() 类似,不同之处在于它返回了一个包含返回值的新容器。
>
> 在mapped中异步计算多个0~n的数的和,并通过返回值传递出来。
![image-20230309210116047](ConcurrentExamples.assets/image-20230309210116047.png)
### 1.8 MappedReduced
> QtConcurrent::mappedReduced使用示例;
>
> 将数组通过参数1传入,在参数2的函数中多线程并行计算,然后将参数2的函数的返回值传入参数3的函数中,在参数3的函数中单线程计算。
![image-20230312113522409](ConcurrentExamples.assets/image-20230312113522409.png)
#---------------------------------------------------------------------------------------
# @功能: QtConcurrent::mapped使用示例,与 map() 类似,不同之处在于它返回了一个包含返回值的新容器。
# @编译器: Desktop Qt 5.12.5 MSVC2017 64bit(也支持其它编译器)
# @Qt IDE D:/Qt/Qt5.12.5/Tools/QtCreator/share/qtcreator
#
# @开发者 mhf
# @邮箱 1603291350@qq.com
# @时间 2023-03-08 19:56:37
# @备注 mapped中异步计算多个0~n的数的和,并通过返回值传递出来。
#---------------------------------------------------------------------------------------
QT += core gui concurrent
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
widget.cpp
HEADERS += widget.h
FORMS += widget.ui
# 定义程序版本号
VERSION = 1.0.0
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
contains(QT_ARCH, i386){ # 使用32位编译器
DESTDIR = $$PWD/../bin # 程序输出路径
}else{
DESTDIR = $$PWD/../bin64 # 使用64位编译器
}
# msvc >= 2017 编译器使用utf-8编码
msvc {
greaterThan(QMAKE_MSC_VER, 1900){ # msvc编译器版本大于2015
QMAKE_CFLAGS += /utf-8
QMAKE_CXXFLAGS += /utf-8
}else{
message(msvc2015及以下版本在代码中使用pragma execution_character_set("utf-8")】指定编码)
}
}
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "widget.h"
#include "ui_widget.h"
#include <qthread.h>
#include <qtconcurrentmap.h>
#include <qthread.h>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle(QString("QtConcurrent::mapped使用示例--V%1").arg(APP_VERSION));
for(int i = 10; i < 20; i++)
{
m_maxs.append(i);
}
connect(&m_futureWatcher, &QFutureWatcher<quint64>::started, [](){qDebug() << "开始监测";});
connect(&m_futureWatcher, &QFutureWatcher<quint64>::finished, [&]()
{
qDebug() << "执行完成";
});
connect(&m_futureWatcher, &QFutureWatcher<quint64>::progressRangeChanged, [](int minimum, int maximum) // 进度范围改变时触发信号
{
qDebug() << QString("进度范围[%1,%2]").arg(minimum).arg(maximum);
});
connect(&m_futureWatcher, &QFutureWatcher<quint64>::progressValueChanged, ui->progressBar, &QProgressBar::setValue); // 进度改变时触发信号(会限制进度信号发射速率,可能无法接收到所有进度)
connect(&m_futureWatcher, &QFutureWatcher<quint64>::progressRangeChanged, ui->progressBar, &QProgressBar::setRange);
connect(&m_futureWatcher, &QFutureWatcher<quint64>::resultReadyAt, this, &Widget::on_resultReadyAt); // 当有返回值时触发这个信号
}
Widget::~Widget()
{
delete ui;
}
/**
* @brief 在线程中异步计算数据,并返回计算的结果
* @param max
* @return
*/
quint64 sum(int max)
{
qDebug() << QString("开始计算从0~%1的和,线程:").arg(max) << QThread::currentThreadId();
quint64 sum = 0;
for(int i = 0; i < max; i++)
{
sum += i;
QThread::msleep(100);
}
return sum;
}
/**
* @brief 获取异步计算的返回值
* @param resultIndex
*/
void Widget::on_resultReadyAt(int resultIndex)
{
QString str = QString("计算0~%1的和:%2").arg(m_maxs.at(resultIndex)).arg(m_futureWatcher.resultAt(resultIndex));
ui->textEdit->append(str);
}
/**
* @brief 开始在线程中异步计算数据
*/
void Widget::on_pushButton_clicked()
{
if(m_futureWatcher.isRunning()) // 判断是否正在运行
{
m_futureWatcher.cancel(); // 取消还没开始的异步任务,已经开始的不会发送进度和结果就绪信号
m_futureWatcher.waitForFinished(); // 等待已经开始的异步任务完成
return;
}
m_futureWatcher.setFuture(QtConcurrent::mapped(m_maxs, sum));
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <qfuturewatcher.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_resultReadyAt(int resultIndex);
void on_pushButton_clicked();
private:
Ui::Widget *ui;
QFutureWatcher<quint64> m_futureWatcher;
QList<int> m_maxs;
};
#endif // WIDGET_H
<?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>487</width>
<height>362</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTextEdit" name="textEdit">
<property name="font">
<font>
<family>黑体</family>
<pointsize>14</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#---------------------------------------------------------------------------------------
# @功能: QtConcurrent::mappedReduced使用示例
# @编译器: Desktop Qt 5.12.5 MSVC2017 64bit(也支持其它编译器)
# @Qt IDE D:/Qt/Qt5.12.5/Tools/QtCreator/share/qtcreator
#
# @开发者 mhf
# @邮箱 1603291350@qq.com
# @时间 2023-03-12 09:21:10
# @备注 将参数1数组传入,在参数2的函数中多线程并行计算,然后将参数2的函数的返回值传入参数3的函数中,在参数3的函数中单线程计算
#---------------------------------------------------------------------------------------
QT -= gui
QT += concurrent
CONFIG += c++11 console
CONFIG -= app_bundle
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += main.cpp
# 定义程序版本号
VERSION = 1.0.0
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
contains(QT_ARCH, i386){ # 使用32位编译器
DESTDIR = $$PWD/../bin # 程序输出路径
}else{
DESTDIR = $$PWD/../bin64 # 使用64位编译器
}
# msvc >= 2017 编译器使用utf-8编码
msvc {
greaterThan(QMAKE_MSC_VER, 1900){ # msvc编译器版本大于2015
QMAKE_CFLAGS += /utf-8
QMAKE_CXXFLAGS += /utf-8
}else{
message(msvc2015及以下版本在代码中使用pragma execution_character_set("utf-8")】指定编码)
}
}
#include <QCoreApplication>
#include <qtconcurrentmap.h>
#include <qthread.h>
#include <QDebug>
using namespace QtConcurrent;
/**
* @brief sum()函数每次返回结果,reduce函数将被调用一次,并且应该将中间值合并到结果变量中。(单线程执行)
* QtConcurrent::mappedReduced()保证一次只有一个线程会调用reduce,因此不需要使用互斥锁来锁定结果变量。
* QtConcurrent::ReduceOptions枚举提供了一种控制减少顺序的方法。
* 如果使用QtConcurrent::UnorderReduce(默认值),则顺序未定义,而QtConcCurrent::OrderedReduce则确保按原始序列的顺序进行缩减。
* @param arr sum()函数的返回值
* @param value result()函数的返回值,将当前函数中的结果通过这个值返回出去
*/
void result1(quint64& arr, quint64 value)
{
qDebug() << QString("同步计算,线程:")<< QThread::currentThreadId();
arr += value;
QThread::msleep(500);
}
void result2(QList<quint64>& arr, quint64 value)
{
qDebug() << QString("同步计算,线程:")<< QThread::currentThreadId();
arr.push_back(value + 10000);
QThread::msleep(500);
}
/**
* @brief 在线程中异步计算数据,并返回计算的结果(并行)
* @param max
* @return
*/
quint64 sum(quint64 max)
{
qDebug() << QString("开始计算从0~%1的和,线程:").arg(max) << QThread::currentThreadId();
quint64 sum = 0;
for(quint64 i = 0; i < max; i++)
{
sum += i;
}
qDebug() << QString("完成计算从0~%1的和为:%1,线程:").arg(sum) << QThread::currentThreadId();
return sum;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<quint64> arr = {10, 15, 20, 25};
#if 1
quint64 collage = mappedReduced(arr, sum, result1);
qDebug() << "计算完成" << collage;
#else
QList<quint64> collage = mappedReduced(arr, sum, result2); // 返回值类型和result()函数第一个参数相同
qDebug() << "计算完成" ;
for(auto v : collage)
{
qDebug() << v;
}
#endif
return a.exec();
}
......@@ -14,3 +14,5 @@ TEMPLATE = subdirs
SUBDIRS += RunFunction # QtConcurrent::run使用示例,在另一个线程中运行一个函数。
SUBDIRS += Map # QtConcurrent::map使用示例,可以在多线程环境下高效地处理大量数据,并且可以返回一个QFuture对象,可以使用它来跟踪数据处理的进度。
SUBDIRS += Mapped # QtConcurrent::mapped使用示例,与 map() 类似,不同之处在于它返回了一个包含返回值的新容器。
SUBDIRS += MappedReduced # QtConcurrent::mappedReduced使用示例,与mapped()类型,相当于将mapped()的结果放入到一个单线程函数中进行计算
......@@ -9,10 +9,11 @@
static HHOOK g_hook = nullptr;
/**
* @brief 处理鼠标事件的回调函数,由于这不是一个成员函数,所以需要通过中间单例类GlobalMouseEvent将鼠标信号传递出来
* @brief 处理鼠标事件的回调函数,由于这不是一个成员函数,所以需要通过中间单例类mouseEvent将鼠标信号传递出来
* 具体内容看https://learn.microsoft.com/zh-cn/previous-versions/windows/desktop/legacy/ms644986(v=vs.85)
* @param nCode 挂钩过程用于确定如何处理消息的代码。如果nCode小于零,则挂钩过程必须将消息传递给 CallNextHookEx 函数而不进行进一步处理,并且应返回CallNextHookEx返回的值
* @param wParam 信号类型:WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE、WM_MOUSEWHEEL、WM_MOUSEHWHEEL、WM_RBUTTONDOWN 或WM_RBUTTONUP(鼠标中键点击和拓展按还没找到怎么弄)。
* @param wParam 信号类型:WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE、WM_MOUSEWHEEL、WM_MOUSEHWHEEL、WM_RBUTTONDOWN 或WM_RBUTTONUP。
* 其它扩展按键可以看https://learn.microsoft.com/en-us/windows/win32/inputdev/mouse-input
* @param lParam MSLLHOOKSTRUCT结构体指针
* @return
*/
......@@ -44,6 +45,42 @@ LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
emit GlobalMouseEvent::getInstance()->wheelEvent(new QWheelEvent(point, delta, Qt::MiddleButton, Qt::NoModifier));
break;
}
case WM_MBUTTONUP: // 鼠标中键释放
emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::MiddleButton, Qt::MiddleButton, Qt::NoModifier));
break;
case WM_MBUTTONDOWN: // 鼠标中键按下
emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::MiddleButton, Qt::MiddleButton, Qt::NoModifier));
break;
case WM_XBUTTONDOWN: // 鼠标功能键按下
{
MSLLHOOKSTRUCT * msll = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
int Button = GET_XBUTTON_WPARAM (msll->mouseData);
switch (Button)
{
case XBUTTON1: // 后退
emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::XButton1, Qt::XButton1, Qt::NoModifier));
break;
case XBUTTON2: // 前进
emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::XButton2, Qt::XButton2, Qt::NoModifier));
break;
}
break;
}
case WM_XBUTTONUP: // 鼠标功能键释放
{
MSLLHOOKSTRUCT * msll = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
int Button = GET_XBUTTON_WPARAM (msll->mouseData);
switch (Button)
{
case XBUTTON1:
emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::XButton1, Qt::XButton1, Qt::NoModifier));
break;
case XBUTTON2:
emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::XButton2, Qt::XButton2, Qt::NoModifier));
break;
}
break;
}
default:
break;
}
......
......@@ -30,7 +30,7 @@ include($$PWD/GlobalMouseKey/GlobalMouseKey.pri)
INCLUDEPATH += $$PWD/GlobalMouseKey
# 定义程序版本号
VERSION = 1.6.2
VERSION = 1.8.0
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
contains(QT_ARCH, i386){ # 使用32位编译器
......
......@@ -54,6 +54,16 @@ void Widget::on_mouseEvent(QMouseEvent* event)
but = "中键";
break;
}
case Qt::XButton1:
{
but = "功能键【后退】";
break;
}
case Qt::XButton2:
{
but = "功能键【前进】";
break;
}
default:
{
but = "未知";
......@@ -70,7 +80,7 @@ void Widget::on_mouseEvent(QMouseEvent* event)
ui->textEdit->append(str);
break;
}
case QEvent::MouseButtonRelease: // 鼠标右键抬起
case QEvent::MouseButtonRelease: // 鼠标抬起
{
QString but;
switch (event->button())
......@@ -90,6 +100,16 @@ void Widget::on_mouseEvent(QMouseEvent* event)
but = "中键";
break;
}
case Qt::XButton1:
{
but = "功能键【后退】";
break;
}
case Qt::XButton2:
{
but = "功能键【前进】";
break;
}
default:
{
but = "未知";
......@@ -106,6 +126,7 @@ void Widget::on_mouseEvent(QMouseEvent* event)
delete event; // 使用完成后记得delete
}
/**
* @brief 全局鼠标滚轮事件
* @param event
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册