GitHub·如何用Python一键清理你的微信文件

另外作者的博客主页也找到了,放在下面,很优秀的一位学长,嘿嘿。


二、小罗碎碎念

首先申明,这个项目并不是我开发的,原作的链接已经放上面了,我写这篇文章的目的是想借鉴一下作者的开发思路,方便以后我也设计类似的轻量级应用。

这个项目已经有可以直接使用的APP了,大家点击链接直接下载,解压以后点击这个鼠鼠头像即可直接启动应用。

然后你在回收站就可以看到被删除的文件了,这一步是为了避免个别文件被误删,你找到对应的去恢复就好了。


源码解析

————————————

好的,爱折腾的同学可以接着看下面的内容,可能需要一丢丢代码基础,大家根据自己的情况自行决定。还是那句话,有问题可以随时与我联系。

首先我们从GitHub把源代码下载下来,解压以后会看到这些文件夹。

我们逐个来分析一下。


1、requirements

注意:原则上开始一个项目,第一个要看的文档是readme,但是我已经看过了,并且觉得没啥有价值的信息,所以就跳过了,想看的,直接用记事本打开就行了,不用去折腾专门看markdown文件的APP。

打开这个文本文档,发现里面非常简单。

这些是一些Python库的版本信息:

  • Send2Trash 1.5.0
  • PyQt5 5.13.0
  • python_dateutil 2.7.5

这些库用于不同的用途:

  • Send2Trash是一个用于**将文件或文件夹移动到操作系统回收站**的库。
  • PyQt5是一个用于**创建图形用户界面(GUI)应用程序的库,它是Python绑定Qt框架的一部分**。
  • python_dateutil是一个用于**解析、操作和计算日期和时间的库**,它提供了许多方便的日期和时间处理功能。

如果你需要使用这些库,你可以使用pip命令来安装它们。例如,要安装Send2Trash 1.5.0,可以运行以下命令:

pip install Send2Trash==1.5.0

类似地,你可以使用相应的命令来安装PyQt5和python_dateutil库。请注意,版本号是可选的,如果不指定版本号,pip将会安装最新版本的库


2、main

2-1:前期准备

接下来我们用Pycharm打开我们的main文件,也是看看我们的主程序是如何设计的。这里建议直接将整个项目导入Pycharm,方便后期调用程序。创建新项目的时候,会让你选择编译器,记得选择自己常用的就可以,最好是你之前已经创建好的虚拟环境,不然后续可能会频繁报错。

听不懂上面那段话也没关系,走一步看一步也很好,哈哈,遇到一个问题再一个个去解决就好了。比如我现在就遇到了一个问题,这里的意思是版本过低了,所以我们手动来安装一下。

我们先进入主程序的界面,然后会发现最上方会跳出提示栏。

直接点击安装要求即可进入以下界面。

尽管还是报错,但是我们得到了一个有用的信息。

接下来我们打开Prompt。

需要注意的是,别直接复制Pycharm提供的代码,不然还是会提示你版本不匹配,这里我们直接版本号去掉就行了。


2-2:导入相关的库文件

首先把整体代码贴过来,算了,尝试了一下,还是不了,因为太长了(手动狗头)。我还是分块解释吧。

import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsDropShadowEffect, QListWidgetItem, QListView, QWidget, \ QLabel, QHBoxLayout, QFileDialog from PyQt5.QtCore import Qt, QPropertyAnimation, QEasingCurve, QThread, pyqtSignal, QMutex, QSize, QEvent, QPoint, QTimer from PyQt5.QtGui import QMouseEvent, QCursor, QColor from PyQt5.uic import loadUi

这段代码使用了PyQt5库来创建图形用户界面(GUI)应用程序。它导入了一些PyQt5的模块和类,并使用了一些常用的功能和特性。

其中,import sys 是导入sys模块,它提供了与Python解释器和运行环境交互的功能。

  • from PyQt5.QtWidgets 导入了一些QtWidgets模块中的类,用于创建GUI界面的各种组件,如应用程序、主窗口、标签、布局等。
  • from PyQt5.QtCore 导入了一些QtCore模块中的类,用于处理Qt的核心功能,如事件处理、动画效果、线程等。
  • from PyQt5.QtGui 导入了一些QtGui模块中的类,用于处理GUI界面的图形相关功能,如鼠标事件、光标、颜色等。
  • from PyQt5.uic 导入了loadUi函数,它用于加载UI文件,将设计的GUI界面与代码进行关联。

这段代码中还使用了一些其他的Python模块和函数,如QFileDialog用于打开文件对话框。


from pathlib import Path, PureWindowsPath from dateutil import relativedelta import utils.resources import os, datetime, time, re, math, shutil, json

这段代码导入了一些Python模块和函数:

  • from pathlib import Path, PureWindowsPath 导入了pathlib模块中的PathPureWindowsPath类,用于处理文件路径和操作系统相关的路径操作。
  • from dateutil import relativedelta 导入了dateutil模块中的relativedelta类,用于处理日期和时间的相对差异。
  • import utils.resources 导入了自定义模块utils.resources,其中包含一些资源相关的功能。
  • import os, datetime, time, re, math, shutil, json 导入了一些Python标准库模块,包括操作系统功能、日期和时间处理、正则表达式、数学计算、文件操作和JSON解析等。

这些导入语句使得你可以在代码中使用这些模块和函数的功能。例如,你可以使用Path类来处理文件路径,使用datetime模块来获取当前日期和时间,使用shutil模块来进行文件和文件夹的复制、移动和删除等操作。


from utils.deleteThread import * from utils.multiDeleteThread import multiDeleteThread from utils.selectVersion import * from utils.selectVersion import check_dir, existing_user_config

这段代码导入了一些自定义的模块和函数:

  • from utils.deleteThread import * 导入了utils.deleteThread模块中的所有内容。这个模块包含一个或多个线程类或函数,用于执行删除操作。
  • from utils.multiDeleteThread import multiDeleteThread 导入了utils.multiDeleteThread模块中的multiDeleteThread类。这个类是一个多线程的删除操作的实现。
  • from utils.selectVersion import * 导入了utils.selectVersion模块中的所有内容。这个模块包含一个或多个函数或类,用于选择版本或配置。
  • from utils.selectVersion import check_dir, existing_user_config 导入了utils.selectVersion模块中的check_dir函数和existing_user_config函数。这些函数用于检查目录或现有用户配置的存在。

补充:*是什么意思

在Python中,使用 * 作为导入语句的一部分,可以表示导入模块中的所有内容。当你使用 from module import * 的形式时,它会导入模块中的所有函数、类和变量,使得你可以直接使用它们,而不需要在代码中使用模块名作为前缀。

例如,from utils.deleteThread import * 表示导入utils.deleteThread模块中的所有内容,包括所有的函数、类和变量。这样,你就可以直接在代码中使用这些导入的内容,而无需在前面加上模块名。

使用 * 导入所有内容可能会导致一些命名冲突或不明确性,因为你无法准确知道导入的模块中有哪些内容。这可能会导致代码可读性下降,并且可能引入不必要的命名冲突。因此,一般来说,最好是明确地导入需要使用的函数、类和变量,而不是使用 * 导入所有内容。


2-3:工作目录获取

# determine if application is a script file or frozen exe if getattr(sys, 'frozen', False): working_dir = os.path.dirname(os.path.realpath(sys.executable)) elif __file__: working_dir = os.path.split(os.path.realpath(__file__))[0]

这段代码用于确定应用程序是一个**脚本文件还是一个被冻结(打包)为可执行文件(exe)的文件**。

首先,代码检查 sys.frozen 属性是否为真。sys.frozen 是一个由 PyInstaller 打包工具设置的属性,用于指示应用程序是否被冻结为可执行文件。如果 sys.frozen 为真,表示应用程序是一个被冻结的可执行文件。

如果 sys.frozen 为真,代码使用 sys.executable 获取当前可执行文件的路径,然后使用 os.path.dirname 函数获取该路径的父目录,即工作目录。

如果 sys.frozen 为假,表示应用程序是一个脚本文件。在这种情况下,代码使用 file 获取当前脚本文件的路径,然后使用 os.path.realpath 函数获取该路径的真实路径,再**使用 os.path.split 函数将路径拆分为目录和文件名**,最后取目录部分作为工作目录。

无论是脚本文件还是冻结的可执行文件,最终的工作目录都会被存储在 working_dir 变量中供后续使用。这个工作目录可以用于确定相对路径、读取文件等操作。

补充:什么是脚本文件?

脚本文件是包含一系列可执行命令的文本文件,通常使用脚本语言编写,比如Python、Bash、JavaScript等。脚本文件通常**包含一系列命令、函数和逻辑,用于自动化执行特定任务或实现特定功能**。

与编译型语言相比,脚本语言的脚本文件不需要进行显式的编译过程。它们在运行时由解释器逐行解释和执行。这使得**脚本文件更加灵活和易于编写、调试和修改**。

脚本文件常用于自动化任务、批处理处理、系统管理、数据处理、网站开发等领域。它们可以通过命令行或调用解释器来执行,也可以通过其他程序或工具来调用。

在**Python中,脚本文件通常以 .py 作为文件扩展名,并且可以通过命令行或Python解释器来执行**。例如,你可以使用 python script.py 命令来执行名为 script.py 的Python脚本文件。

脚本文件的优点是灵活性和易用性,可以快速编写和调试。然而,与编译型语言相比,脚本文件的执行速度可能较慢,因为每次执行都需要解释器进行解释


2-4:class Window

先把这一小部分的整体代码放上,首先进行一个全局分析,然后我们再逐个函数进行解释。

class Window(QMainWindow): def mousePressEvent(self, event): # 重写一堆方法使其支持拖动 if event.button() == Qt.LeftButton: self.m_drag = True self.m_DragPosition = event.globalPos() - self.pos() event.accept() # self.setCursor(QCursor(Qt.OpenHandCursor)) def mouseMoveEvent(self, QMouseEvent): try: if Qt.LeftButton and self.m_drag: self.move(QMouseEvent.globalPos() - self.m_DragPosition) QMouseEvent.accept() except: pass def mouseReleaseEvent(self, QMouseEvent): self.m_drag = False # self.setCursor(QCursor(Qt.ArrowCursor)) def _frame(self): # 边框 self.setWindowFlags(Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground, True) # 阴影 effect = QGraphicsDropShadowEffect(blurRadius=12, xOffset=0, yOffset=0) effect.setColor(QColor(25, 25, 25, 170)) self.mainFrame.setGraphicsEffect(effect) def doFadeIn(self): # 动画 self.animation = QPropertyAnimation(self, b'windowOpacity') # 持续时间250ms self.animation.setDuration(250) try: # 尝试先取消动画完成后关闭窗口的信号 self.animation.finished.disconnect(self.close) except: pass self.animation.stop() # 透明度范围从0逐渐增加到1 self.animation.setEasingCurve(QEasingCurve.InOutCubic) self.animation.setStartValue(0) self.animation.setEndValue(1) self.animation.start() def doFadeOut(self): self.animation.stop() # 动画完成则关闭窗口 self.animation.finished.connect(self.close) # 透明度范围从1逐渐减少到0s self.animation.setEasingCurve(QEasingCurve.InOutCubic) self.animation.setStartValue(1) self.animation.setEndValue(0) self.animation.start() def setWarninginfo(self, text): self.lab_info.setStyleSheet(""" .QLabel { border:1px solid #ffccc7; border-radius:3px; line-height: 140px; padding: 5px; color: #434343; background: #fff2f0; } """) self.lab_info.setText(text) def setSuccessinfo(self, text): self.lab_info.setStyleSheet(""" .QLabel { border:1px solid #b7eb8f; border-radius:3px; line-height: 140px; padding: 5px; color: #434343; background: #f6ffed; } """) self.lab_info.setText(text)

这段代码继续定义了 Window 类的其他方法,用于实现窗口的一些特殊效果和功能。

  1. mouseMoveEvent 方法:当**鼠标移动时触发,用于实现拖动窗口的效果**。在方法中,首先判断鼠标左键是否按下且窗口正在被拖动(self.m_dragTrue),然后通过 self.move() 方法将窗口移动到当前鼠标位置减去初始偏移量的位置。
  2. mouseReleaseEvent 方法:当**鼠标释放时触发,用于停止拖动窗口**的效果。在方法中,将 self.m_drag 设置为 False,表示窗口不再被拖动。
  3. _frame 方法:用于**设置窗口的边框和阴影效果**。通过设置窗口的标志位和属性,实现无边框窗口和透明背景,并添加一个带有阴影效果的 QGraphicsDropShadowEffect
  4. doFadeIn 方法:用于**实现窗口的淡入效果**。通过创建一个 QPropertyAnimation 对象,设置动画的目标对象为当前窗口,属性为 windowOpacity(窗口的透明度),持续时间为250毫秒。然后设置动画的起始值为0,结束值为1,设置缓动曲线为 QEasingCurve.InOutCubic,并启动动画。
  5. doFadeOut 方法:用于**实现窗口的淡出效果**。与 doFadeIn 方法类似,设置动画的起始值为1,结束值为0,然后启动动画。在动画完成后,连接 self.close 方法,以便在动画完成后关闭窗口。
  6. setWarninginfosetSuccessinfo 方法:用于设置窗口上的信息标签的样式和文本。这两个方法分别**设置了警告信息和成功信息**的样式,包括边框、背景色等,并通过 setText 方法设置文本内容。

这些方法提供了一些额外的功能,如拖动窗口、窗口特效和信息标签的样式设置,以增强GUI窗口的交互和视觉效果。所以,我们有必要逐个分析一下。

——mousePressEvent

通过下列操作,可实现拖动窗口的功能。当用户按下鼠标左键时,窗口会进入拖动状态,并记录下鼠标按下时的初始位置和窗口的初始位置之间的偏移量。在后续的 mouseMoveEvent 方法中,可以根据这个偏移量来实现窗口的跟随移动。

def mousePressEvent(self, event): # 重写一堆方法使其支持拖动 if event.button() == Qt.LeftButton: self.m_drag = True self.m_DragPosition = event.globalPos() - self.pos()#拖动距离 event.accept() # self.setCursor(QCursor(Qt.OpenHandCursor))

这部分代码是 mousePressEvent 方法的实现。当鼠标按下时,该方法会被调用。在这段代码中,首先通过 event.button() 判断鼠标按下的是左键(Qt.LeftButton)。

如果鼠标按下的是左键,以下操作将被执行:

  1. self.m_drag = True将一个成员变量 m_drag 设置为 True,用于表示窗口正在被拖动
  2. self.m_DragPosition = event.globalPos() - self.pos():计算鼠标按下时的全局坐标与窗口当前位置的差值,并将结果保存在成员变量 m_DragPosition 中。这样可以**记录下鼠标按下时的初始位置和窗口的初始位置之间的偏移量**。
  3. event.accept():接受鼠标事件,表示该事件已经被处理。

注意:# self.setCursor(QCursor(Qt.OpenHandCursor))

这行代码的作用是**设置鼠标指针的样式为打开手指形状**(Qt.OpenHandCursor),由于被注释掉了,所以在当前代码段并没有生效。。

通常情况下,当用户将鼠标悬停在可拖动的区域时,将鼠标指针设置为打开手指形状可以提供一种视觉反馈,表明该区域可以进行拖动操作。这样可以增强用户体验,让用户知道他们可以通过拖动来移动窗口。

如果你想启用这行代码,你可以取消注释,即将 # 符号删除,然后重新运行代码。这样,在鼠标按下时,鼠标指针将会变成打开手指形状。


未完待续


最新更新日期

2023/10/28-09:58

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值