【Python】通过第三方库wxauto自动化操作微信电脑客户端

news2024/12/24 8:18:20

文章目录

  • 一.简介
  • 二.wxauto提供的函数
    • 1.WxUtils类功能函数:
    • 2.WeChat类主要函数:
  • 三.使用
  • 四.遇到的问题

一.简介

wxauto是一个Python第三方库,用于自动化操作微信电脑客户端通过wxauto,我们可以使用Python编写脚本,实现以下功能

  • 获取微信好友列表、群组列表、聊天记录等信息。
  • 在微信中发送文本、图片、语音等信息给好友或群组。
  • 自动回复好友或群组的消息。
  • 自动加入或退出群组。
  • 自动发送文件给好友或群组。
  • 自动发送红包给好友或群组。
  • 其他自定义的自动化操作。

使用wxauto需要先安装其库文件,可以使用pip命令进行安装

pip install wxauto

二.wxauto提供的函数

wxauto目前有WxParam、WxUtils、WeChat三个类:

  • 其中WxParam设置基本参数设置。

1.WxUtils类功能函数:

  • SetClipboard(data, dtype=‘text’) 复制文本信息或图片到剪贴板data : 要复制的内容,str 或 Image 图像;
  • Screenshot(hwnd, to_clipboard=True) 为句柄为hwnd的窗口程序截图;hwnd : 句柄;to_clipboard : 是否复制到剪贴板;
  • SavePic(savepath=None, filename=None) 保存截图;savepath:文件保存位置;filename:文件名字;
  • ControlSize(control) 获取控制窗口大小;
  • ClipboardFormats(unit=0, *units) 获取剪切板格式 ;
  • CopyDict()

2.WeChat类主要函数:

  • GetSessionList(self, reset=False) 获取当前会话列表,更新会话列表
  • Search(self, keyword) 查找微信好友或关键词;keywords: 要查找的关键词,最好完整匹配,不完全匹配只会选取搜索框第一个;
  • ChatWith(self, who, RollTimes=None) 打开某个聊天框;who : 要打开聊天框的好友名,最好完整匹配,不完全匹配只会选取搜索框第一个;RollTimes : 默认向下滚动次数,再进行搜索;
  • SendMsg(self, msg, clear=True) 向当前窗口发送消息;msg : 要发送的消息;
  • SendFiles(self, *filepath, not_exists=‘ignore’) 向当前聊天窗口发送文件;not_exists: 如果未找到指定文件,继续或终止程序;*filepath: 要复制文件的绝对路径;
  • SendClipboard(self) 向当前聊天页面发送剪贴板复制的内容;
  • GetAllMessage(self) 获取当前窗口中加载的所有聊天记录;
  • GetLastMessage(self) 获取当前窗口中最后一条聊天记录
  • LoadMoreMessage(self, n=0.1) 定位到当前聊天页面,并往上滚动鼠标滚轮,加载更多聊天记录到内存发送某个桌面程序的截图,如:微信、记事本;name : 要发送的桌面程序名字;classname : 要发送的桌面程序类别名;
  • SendScreenshot(self, name=None, classname=None) 发送某个桌面程序的截图,如:微信、记事本;name : 要发送的桌面程序名字;classname : 要发送的桌面程序类别名;

三.使用

from wxauto import *


# 获取当前微信客户端
wx = WeChat()


# 获取会话列表
wx.GetSessionList()


# 输出当前聊天窗口聊天消息
msgs = wx.GetAllMessage
for msg in msgs:
    print('%s : %s'%(msg[0], msg[1]))
## 获取更多聊天记录
wx.LoadMoreMessage()
msgs = wx.GetAllMessage
for msg in msgs:
    print('%s : %s'%(msg[0], msg[1]))


# 向某人发送消息(以`文件传输助手`为例)
msg = '你好~'
who = '文件传输助手'
wx.ChatWith(who)  # 打开`文件传输助手`聊天窗口
wx.SendMsg(msg)  # 向`文件传输助手`发送消息:你好~

## 发送换行消息(最近很多人问换行消息如何发送,新增说明一下)
msg = '''你好
这是第二行
这是第三行
这是第四行'''
who = '文件传输助手'
WxUtils.SetClipboard(msg)    # 将内容复制到剪贴板,类似于Ctrl + C
wx.ChatWith(who)  # 打开`文件传输助手`聊天窗口
wx.SendClipboard()   # 发送剪贴板的内容,类似于Ctrl + V


# 向某人发送文件(以`文件传输助手`为例,发送三个不同类型文件)
file1 = 'D:/test/wxauto.py'
file2 = 'D:/test/pic.png'
file3 = 'D:/test/files.rar'
who = '文件传输助手'
wx.ChatWith(who)  # 打开`文件传输助手`聊天窗口
wx.SendFiles(file1, file2, file3)  # 向`文件传输助手`发送上述三个文件
# 注:为保证发送文件稳定性,首次发送文件可能花费时间较长,后续调用会缩短发送时间


# 向某人发送程序截图(以`文件传输助手`为例,发送微信截图)
name = '微信'
classname = 'WeChatMainWndForPC'
wx.ChatWith(who)  # 打开`文件传输助手`聊天窗口
wx.SendScreenshot(name, classname)  # 发送微信窗口的截图给文件传输助手
注:为保证发送文件稳定性,首次发送文件可能花费时间较长,后续调用会缩短发送时间

四.遇到的问题

由于部分版本的微信可能由于UI界面不同从而无法使用,截至2022-06-10最新版本可用

  • 因此在代码运行的时候,会发现图片无法发送、消息无法发送的报错情况 LookupError: Find Control Timeout(10s): {Name: '输入', ControlType: EditControl},这是因为pip 下载的wxauto第三方库无法匹配微信客户端3.7的版本

  • 如果有遇到,可以通过Github的方式下载源码,直接修改源码
    在这里插入图片描述

    wxauto库信息:
    Author: tikic@qq.com
    Source: https://github.com/cluic/wxauto
    Version: 3.3.5.3
    

微信最新版本需要重新适配,需修改 wxauto.py 代码

1.在 wxauto.py 的文件中找到 WeChat 的类,并添加下述方法
    def ChangeWindow(self, window_title):
        self.EditMsg = self.UiaAPI.EditControl(Name=f'{window_title}')	
        
2.之后在 ChatWith 方法中加入如下代码
    def ChatWith(self, who, RollTimes=None):
        '''
        打开某个聊天框
        who : 要打开的聊天框好友名,str;  * 最好完整匹配,不完全匹配只会选取搜索框第一个
        RollTimes : 默认向下滚动多少次,再进行搜索
        '''
        self.UiaAPI.SwitchToThisWindow()
        self.ChangeWindow(who)  # [2] 加入如下方法,在每次更改聊天对象时调用 ChangeWindow 方法
        ... ...

wxauto.py完整代码

#!python3
# -*- coding: utf-8 -*-
"""
Author: tikic@qq.com
Source: https://github.com/cluic/wxauto
License: MIT License
Version: 3.9.0.28
"""
import uiautomation as uia
import win32gui, win32con
import win32clipboard as wc
import time
import os

AUTHOR_EMAIL = 'tikic@qq.com'
UPDATE = '2023-02-25'
VERSION = '3.9.0.28'


class WxParam:
    SYS_TEXT_HEIGHT = 33
    TIME_TEXT_HEIGHT = 34
    RECALL_TEXT_HEIGHT = 45
    CHAT_TEXT_HEIGHT = 52
    CHAT_IMG_HEIGHT = 117
    SpecialTypes = ['[文件]', '[图片]', '[视频]', '[音乐]', '[链接]']


class WxUtils:
    def GetMessageInfos(Item, msglist=None):
        msglist = msglist if msglist is not None else list()
        if len(Item.GetChildren()) == 0:
            msglist.append(Item.Name)
        else:
            for i in Item.GetChildren():
                WxUtils.GetMessageInfos(i, msglist)
        return [i for i in msglist if i]

    def SplitMessage(MsgItem):
        uia.SetGlobalSearchTimeout(0)
        MessageInfos = WxUtils.GetMessageInfos(MsgItem)
        MsgItemName = MsgItem.Name
        if MsgItem.BoundingRectangle.height() == WxParam.SYS_TEXT_HEIGHT:
            Msg = ('SYS', MsgItemName, MessageInfos)
        elif MsgItem.BoundingRectangle.height() == WxParam.TIME_TEXT_HEIGHT:
            Msg = ('Time', MsgItemName, MessageInfos)
        elif MsgItem.BoundingRectangle.height() == WxParam.RECALL_TEXT_HEIGHT:
            if '撤回' in MsgItemName:
                Msg = ('Recall', MsgItemName, MessageInfos)
            else:
                Msg = ('SYS', MsgItemName, MessageInfos)
        else:
            Index = 1
            User = MsgItem.ButtonControl(foundIndex=Index)
            try:
                while True:
                    if User.Name == '':
                        Index += 1
                        User = MsgItem.ButtonControl(foundIndex=Index)
                    else:
                        break
                Msg = (User.Name, MsgItemName, MessageInfos)
            except:
                Msg = ('SYS', MsgItemName, MessageInfos)
        uia.SetGlobalSearchTimeout(10.0)
        return Msg

    def SetClipboard(data, dtype='text'):
        '''复制文本信息或图片到剪贴板
        data : 要复制的内容,str 或 Image 图像'''
        if dtype.upper() == 'TEXT':
            type_data = win32con.CF_UNICODETEXT
        elif dtype.upper() == 'IMAGE':
            from io import BytesIO
            type_data = win32con.CF_DIB
            output = BytesIO()
            data.save(output, 'BMP')
            data = output.getvalue()[14:]
        else:
            raise ValueError('param (dtype) only "text" or "image" supported')
        wc.OpenClipboard()
        wc.EmptyClipboard()
        wc.SetClipboardData(type_data, data)
        wc.CloseClipboard()

    def Screenshot(hwnd, to_clipboard=True):
        '''为句柄为hwnd的窗口程序截图
        hwnd : 句柄
        to_clipboard : 是否复制到剪贴板
        '''
        import pyscreenshot as shot
        bbox = win32gui.GetWindowRect(hwnd)
        win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0, 0, 0, 0, \
                              win32con.SWP_SHOWWINDOW | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
        win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, \
                              win32con.SWP_SHOWWINDOW | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
        win32gui.BringWindowToTop(hwnd)
        im = shot.grab(bbox)
        if to_clipboard:
            WxUtils.SetClipboard(im, 'image')
        return im

    def SavePic(savepath=None, filename=None):
        Pic = uia.WindowControl(ClassName='ImagePreviewWnd', Name='图片查看')
        Pic.SendKeys('{Ctrl}s')
        SaveAs = Pic.WindowControl(ClassName='#32770', Name='另存为...')
        SaveAsEdit = SaveAs.EditControl(ClassName='Edit', Name='文件名:')
        SaveButton = Pic.ButtonControl(ClassName='Button', Name='保存(S)')
        PicName, Ex = os.path.splitext(SaveAsEdit.GetValuePattern().Value)
        if not savepath:
            savepath = os.getcwd()
        if not filename:
            filename = PicName
        FilePath = os.path.realpath(os.path.join(savepath, filename + Ex))
        SaveAsEdit.SendKeys(FilePath)
        SaveButton.Click()
        Pic.SendKeys('{Esc}')

    def ControlSize(control):
        locate = control.BoundingRectangle
        size = (locate.width(), locate.height())
        return size

    def ClipboardFormats(unit=0, *units):
        units = list(units)
        wc.OpenClipboard()
        u = wc.EnumClipboardFormats(unit)
        wc.CloseClipboard()
        units.append(u)
        if u:
            units = WxUtils.ClipboardFormats(u, *units)
        return units

    def CopyDict():
        Dict = {}
        for i in WxUtils.ClipboardFormats():
            if i == 0:
                continue
            wc.OpenClipboard()
            try:
                content = wc.GetClipboardData(i)
                wc.CloseClipboard()
            except:
                wc.CloseClipboard()
                raise ValueError
            if len(str(i)) >= 4:
                Dict[str(i)] = content
        return Dict


class WeChat:
    def __init__(self):
        self.UiaAPI = uia.WindowControl(ClassName='WeChatMainWndForPC')
        self.SessionList = self.UiaAPI.ListControl(Name='会话')
        self.EditMsg = self.UiaAPI.EditControl(Name='输入')
        self.SearchBox = self.UiaAPI.EditControl(Name='搜索')
        self.MsgList = self.UiaAPI.ListControl(Name='消息')
        self.SessionItemList = []

    def ChangeWindow(self, window_title):
        self.EditMsg = self.UiaAPI.EditControl(Name=f'{window_title}')

    def GetSessionList(self, reset=False):
        '''获取当前会话列表,更新会话列表'''
        self.SessionItem = self.SessionList.ListItemControl()
        SessionList = []
        if reset:
            self.SessionItemList = []
        for i in range(100):
            try:
                name = self.SessionItem.Name
            except:
                break
            if name not in self.SessionItemList:
                self.SessionItemList.append(name)
            if name not in SessionList:
                SessionList.append(name)
            self.SessionItem = self.SessionItem.GetNextSiblingControl()
        return SessionList

    def Search(self, keyword):
        '''
        查找微信好友或关键词
        keywords: 要查找的关键词,str   * 最好完整匹配,不完全匹配只会选取搜索框第一个
        '''
        self.UiaAPI.SetFocus()
        time.sleep(0.2)
        self.UiaAPI.SendKeys('{Ctrl}f', waitTime=1)
        self.SearchBox.SendKeys(keyword, waitTime=1.5)
        self.SearchBox.SendKeys('{Enter}')

    def ChatWith(self, who, RollTimes=None):
        '''
        打开某个聊天框
        who : 要打开的聊天框好友名,str;  * 最好完整匹配,不完全匹配只会选取搜索框第一个
        RollTimes : 默认向下滚动多少次,再进行搜索
        '''
        self.UiaAPI.SwitchToThisWindow()
        self.ChangeWindow(who)  # [2] 加入如下方法,在每次更改聊天对象时调用 ChangeWindow 方法
        RollTimes = 10 if not RollTimes else RollTimes

        def roll_to(who=who, RollTimes=RollTimes):
            for i in range(RollTimes):
                if who not in self.GetSessionList()[:-1]:
                    self.SessionList.WheelDown(wheelTimes=3, waitTime=0.1 * i)
                else:
                    time.sleep(0.5)
                    self.SessionList.ListItemControl(Name=who).Click(simulateMove=False)
                    return 1
            return 0

        rollresult = roll_to()
        if rollresult:
            return 1
        else:
            self.Search(who)
            return roll_to(RollTimes=1)

    def SendMsg(self, msg, clear=True):
        '''向当前窗口发送消息
        msg : 要发送的消息
        clear : 是否清除当前已编辑内容
        '''
        self.UiaAPI.SwitchToThisWindow()
        if clear:
            self.EditMsg.SendKeys('{Ctrl}a', waitTime=0)
        self.EditMsg.SendKeys(msg, waitTime=0)
        self.EditMsg.SendKeys('{Enter}', waitTime=0)

    def SendFiles(self, *filepath, not_exists='ignore'):
        """向当前聊天窗口发送文件
        not_exists: 如果未找到指定文件,继续或终止程序
        filepath (list): 要复制文件的绝对路径"""
        key = ''
        for file in filepath:
            file = os.path.realpath(file)
            if not os.path.exists(file):
                if not_exists.upper() == 'IGNORE':
                    print('File not exists:', file)
                    continue
                elif not_exists.upper() == 'RAISE':
                    raise FileExistsError('File Not Exists: %s' % file)
                else:
                    raise ValueError('param not_exists only "ignore" or "raise" supported')
            key += '<EditElement type="3" filepath="%s" shortcut="" />' % file

        self.EditMsg.SendKeys(' ', waitTime=0)
        self.EditMsg.SendKeys('{Ctrl}a', waitTime=0)
        self.EditMsg.SendKeys('{Ctrl}c', waitTime=0)
        self.EditMsg.SendKeys('{Delete}', waitTime=0)
        while True:
            try:
                data = WxUtils.CopyDict()
                break
            except:
                pass

        for i in data:
            data[i] = data[i].replace(b'<EditElement type="0"><![CDATA[ ]]></EditElement>', key.encode())

        data1 = {
            '13': '',
            '16': b'\x04\x08\x00\x00',
            '1': b'',
            '7': b''
        }
        data.update(data1)

        wc.OpenClipboard()
        wc.EmptyClipboard()
        for k, v in data.items():
            wc.SetClipboardData(int(k), v)
        wc.CloseClipboard()
        self.SendClipboard()
        return 1

    def SendClipboard(self):
        '''向当前聊天页面发送剪贴板复制的内容'''
        self.SendMsg('{Ctrl}v')

    @property
    def GetAllMessage(self):
        '''获取当前窗口中加载的所有聊天记录'''
        MsgDocker = []
        MsgItems = self.MsgList.GetChildren()
        for MsgItem in MsgItems:
            MsgDocker.append(WxUtils.SplitMessage(MsgItem))
        return MsgDocker

    @property
    def GetLastMessage(self):
        '''获取当前窗口中最后一条聊天记录'''
        uia.SetGlobalSearchTimeout(1.0)
        MsgItem = self.MsgList.GetChildren()[-1]
        Msg = WxUtils.SplitMessage(MsgItem)
        uia.SetGlobalSearchTimeout(10.0)
        return Msg

    def LoadMoreMessage(self, n=0.1):
        '''定位到当前聊天页面,并往上滚动鼠标滚轮,加载更多聊天记录到内存'''
        n = 0.1 if n < 0.1 else 1 if n > 1 else n
        self.MsgList.WheelUp(wheelTimes=int(500 * n), waitTime=0.1)

    def SendScreenshot(self, name=None, classname=None):
        '''发送某个桌面程序的截图,如:微信、记事本...
        name : 要发送的桌面程序名字,如:微信
        classname : 要发送的桌面程序类别名,一般配合 spy 小工具使用,以获取类名,如:微信的类名为 WeChatMainWndForPC'''
        if name and classname:
            return 0
        else:
            hwnd = win32gui.FindWindow(classname, name)
        if hwnd:
            WxUtils.Screenshot(hwnd)
            self.SendClipboard()
            return 1
        else:
            return 0

wxautoapi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/772833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何自学网络安全(黑客)

自学网络安全&#xff08;黑客&#xff09;需要掌握一系列的技能和知识&#xff0c;以下是一些学习网络安全的步骤&#xff1a; 基础知识&#xff1a;首先&#xff0c;你需要对计算机网络和操作系统有基本的了解。学习计算机网络的基本原理、网络协议和网络安全的基本概念。同时…

攻防世界-web-easytornado

题目描述&#xff1a;Tornado 框架。打开链接是一个简单的界面 1. 思路分析 看到有个/flag.txt&#xff0c;我们点击进去看下 发现传入了两个参数&#xff0c;一个是filename&#xff0c;还有一个是filehash 看到里面的内容&#xff0c;提示我们真正的flag在 /flllllllllllla…

报错 The server socket has failed to bind to [::] Pytorch中DDP中断训练报错

Pytorch中DDP &#xff1a;The server socket has failed to bind to [::]:29500 (errno: 98 - Address already in use&#xff09;_cv_lhp的博客-CSDN博客 报错如下 The server socket has failed to bind to [::]:999 (errno: 98 - Address already in use) 这个错误是因为…

虚拟机挂载USB设备/USB serial 连接开发板

虚拟机挂载USB设备 1、添加USB设备 2、终端输入&#xff1a;sudo fdisk -l 查看Device设备&#xff1a; 3、创建挂载目录&#xff1a;mkdir /mnt/usb 4、执行挂载命令&#xff1a;sudo mount /dev/sdb1 /mnt/usb ,查看/mnt/usb目录下是否存在U盘中的数据&#xff1a; 5、用…

构建产品帮助中心时要避免的 8 个最常见错误

构建帮助中心是提供给客户和用户有价值信息的重要途径&#xff0c;但在建设过程中&#xff0c;有一些常见的错误需要避免。本文将介绍构建帮助中心时要避免的8个最常见错误&#xff0c;帮助您打造一个更优秀的帮助中心。 1. 以老式方式进行&#xff08;FAQ/Q&A 页面样式&am…

【uni-app】1、分页组件z-paging介绍与使用

1、z-paging 介绍 1、一个 uni-app &#xff08;opens new window&#xff09;分页组件。 2、全平台兼容&#xff0c;支持自定义下拉刷新、上拉加载更多&#xff0c;支持虚拟列表&#xff0c;支持自动管理空数据图、点击返回顶部&#xff0c;支持聊天分页、本地分页&#xff0c…

AI对话+AI绘画,提高你的生产力

智心AI平台 使用 Nestjs 和 Vue3 搭建的 AIGC 生态社区 在线使用&#xff1a;用户端体验 当前特色支持功能 GPT3/4模型支持与控制联网对话支持思维导图生成支持openai DALL-E2绘画支持Midjourney绘画支持全套卡密系统支持在线支付支持完善的后台管理系统支持 源码购买或者…

Unity---Spine动画

目录 1.介绍 2.优点 3.spine导出的unity资源 4.导入 5.导入报错的解决方案 6.使用 7.代码示例 1.加载Spine骨骼动画&#xff1a; 2.控制Spine动画的播放&#xff1a; 3.暂停和恢复动画播放&#xff1a; 4.监听动画事件&#xff1a; 5.切换皮肤&#xff08;换装&…

Rsync(二十七)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 二、特性 三、应用场景 四、数据的同步方式 五、rsync传输模式 六、rsync应用 七、rsync 命令 1. 格式 1.1 作为远程命令 1. 2 作为rsync服务 2. 选项 3.…

​通达信量比捉牛股指标源码​_通达信公式

JL5:MA(V,5); LB:DYNAINFO(17); 历史量比:IF(DYNAINFO(4)OANDDYNAINFO(5)HANDDYNAINFO(6)LANDDYNAINFO(7) C,DYNAINFO(17),V/JL5),LINETHICK,COLORYELLOW; STICKLINE(历史量比>1,历史量比,0,3,1)COLORRED; STICKLINE(历史量比<1,历史量比,0,3,0)COLO…

Debug调试的使用(IDEA 基础篇 喂奶级教程)

引言 在编程中&#xff0c;Debug&#xff08;调试&#xff09;是指在程序运行时&#xff0c;通过一系列的工具和技术&#xff0c;对程序进行逐行调试和分析&#xff0c;从而发现和修复程序中的错误和问题。Debug 功能是程序开发中非常重要的一个环节&#xff0c;它可以帮助开发…

JSON对象的stringify()和parse()方法使用

JSON对象的stringify和parse方法使用 JSON 格式JSON 对象JSON.stringify()1.JSON.stringify(value)2.JSON.stringify(value,replace)3.JSON.stringify(value,replace,space)4.注意的点 JSON.parse() JSON 格式 JSON 格式&#xff08;JavaScript Object Notation 的缩写&#xf…

一文读懂【TypeScript】的发展设计理念

导语&#xff1a; 在了解 TypeScript 之前&#xff0c;我们需要了解 什么是强类型语言和什么是弱类型语言&#xff0c;以及什么是静态类型&#xff0c;什么又是动态类型。 强类型不允许任意的隐式类型转换&#xff0c;而 弱类型 允许静态类型&#xff1a;一个变量声明时它的类型…

STM32使用高级定时器输出互补pwm波

STM32使用高级定时器输出互补pwm波 前言硬件和软件cubemx新建工程打开Debug模式配置时钟源六大时钟的作用选择Crystal/Ceramic Resonator&#xff0c;即使用外部晶振作为HSE的时钟源。 配置时钟配置高级定时器TIM8和通用定时器TIM3这里大概解释一下配置pwm输出用到的几个参数我…

ASEMI快恢复二极管MUR20100CTR在电子工程中的应用

编辑-Z 随着电子技术的日益发展&#xff0c;各种电子元件的使用场景与需求也在逐步扩大。今天&#xff0c;我们将聚焦于一款广泛应用于各类电路的二极管——MUR20100CTR&#xff0c;来详细解读其性能特征及应用。 一、MUR20100CTR二极管的主要特性 MUR20100CTR是一款极高性能的…

03 QT对象树

Tips: QT通过对象树机制&#xff0c;能够自动、有效的组织和管理继承自QObject的Qt对象&#xff0c;不需要用户手动回收资源&#xff0c;系统自动调用析构函数。 验证对象树功能&#xff1a; 新建C文件 继承自QPushButton&#xff0c;但没有QPushButton&#xff0c;但有其父类…

简单高效的交易系统,只需这种行情分析工具

行情分析的意义在于&#xff0c;首先它给我们不得不做出的方向性选择提供一些技术的支持。其次&#xff0c;它可以给我们提出一个入市点&#xff0c;一个理想的盈利点&#xff0c;一个认输的失败点。无论你用什么办法进行行情预测或指导&#xff0c;只要你的分析结果中有这样三…

Vue中的侦听器:数据变化的秘密揭示

一、侦听器&#xff1a;vue中想监听数据的变化 &#x1f680;&#xff08;一&#xff09;侦听器watch 如何侦听到某个变量值改变呢&#xff1f;使用watch配置项&#x1f6a7;&#x1f6a7;&#x1f6a7;watch&#xff1a;可以侦听到data/computed属性值的改变。语法&#xff…

C++入门学习(2)

思维导图&#xff1a; 一&#xff0c;缺省参数 如何理解缺省参数呢&#xff1f;简单来说&#xff0c;缺省参数就是一个会找备胎的参数&#xff01;为什么这样子说呢&#xff1f;来看一个缺省参数就知道了&#xff01;代码如下&#xff1a; #include<iostream> using std…

商城-学习整理-基础-环境搭建(二)

目录 一、环境搭建1、安装linux虚拟机1&#xff09;下载&安装 VirtualBox https://www.virtualbox.org/&#xff0c;要开启 CPU 虚拟化2&#xff09;虚拟机的网络设置3&#xff09;虚拟机允许使用账号密码登录4&#xff09;VirtualBox冲突5&#xff09;修改 linux 的 yum 源…