基于TinyPNG所提供API的自动上传压缩可视化py脚本

0 引言

用md写发布到网络上的文章需要利用图床,如果图片体积太大,不仅上传图床需要时间,网页加载也要时间,所以可以考虑减小图片体积。经过一番搜索,找到了TinyPNG在线压缩网站,只需图片拖进网站,然后等待,然后下载。
浏览器下载完后要切换到下载目录,剪切图片,跳回图片保存目录替换图片,如果下载时指定目录的话,下次写另一篇文章,又要换到另一个位置,烦死了!

1 模型的建立

我会为每一篇文章指定一个图片保存目录,方便以后管理,而截图时直接就将图片保存在该目录下,所以我希望直接将图片拖进程序,然后它就直接变成了压缩成品,没有其他操作。

窗口接收文件;一个标签,显示文字“图片”,一个标签,文字显示为拖入图片的绝对地址;一个标签,显示目前状态;一个按钮,按下则开始工作。
理论上,不需要按钮,但是由本人控制何时开始感觉更有安全感。

为了方便查看各控件的坐标,在cad中做了初步的规划,由于界面实在太简单,也不准备再更改,就没有保存二维图,在此仅列出控件几何参数。

标签 定义名 位置 尺寸
窗体 xiiyue 500,400
静态标签 label_s 40,65 60,30
路径标签 label_picfile 130,50 330,60
状态标签 label_state 40,120 420,160
确认按钮 butn 200,305 100,30

2 代码实现

2.1 窗体

新建类,用于创建空白控件,自动成为窗体。

class xiiyue(QWidget):
    pass

其实不需要新建继承QWidget的类,我是边学边写,跟着写。新建类后想要运行它,在以下代码

if __name__ == "__main__":
    app = QApplication(sys.argv)  # 创建应用
    xiyue = xiiyue()              # 实例化
    xiyue.show()                  # 显示窗口
    sys.exit(app.exec_())         # 持续运行

这句if使得其他文件导入此文件不会运行,而执行此文件才会运行。我本来就打算在一个文件里完成所有代码,因此不需要考虑导入的问题,不过这种格式的确有逻辑清晰的优点,这样写也没毛病。
写到此时用到了QWidget,QApplication,sys,因此文件开头导入模块:

import sys
from PyQt5.QtWidgets import QWidget,QApplication

继续调整主窗体,改写init。
1,继承所有,毕竟不能影响QWidget的原本功能
2,设置窗体名
3,设置窗口大小
4,加载子控件

def __init__(self):
    super(xiiyue, self).__init__()
    # 设置窗口名
    self.setWindowTitle("图片压缩")
    # 定义窗口大小
    self.resize(500, 400)
    # 布置控件
    self.load()

为了保证init的简洁明了,子控件的建立和外观设定都放在了load()函数里。

2.2 子控件

定义load()函数

def load(self):
    pass

其中为各子控件的创建和设置代码

  • 静态标签部分
# 建标签
self.label_s = QLabel(self)
# 标签位置和尺寸
self.label_s.setGeometry(40, 65, 60, 30)
# 标签格式,字体颜色红,大小15像素,加粗
self.label_s.setStyleSheet("color:red;font-size:15px;font-weight:bold;")
# 标签居中设置,水平垂直居中
self.label_s.setAlignment(QtCore.Qt.AlignCenter)
# 标签文字
self.label_s.setText("图片")
  • 路径标签部分
self.label_picfile = QLabel(self)
self.label_picfile.setGeometry(130, 50, 330, 60)
# 标签格式,背景白,字体大小15像素
self.label_picfile.setStyleSheet("background-color:white;font-size:15px;")
# 标签居中设置,左对齐,垂直居中
self.label_picfile.setAlignment(QtCore.Qt.AlignLeft |QtCore.Qt.AlignVCenter)
self.label_picfile.setText(self.file_name)
# 标签设置自动换行
self.label_picfile.setWordWrap(True)

这里有个变量file_name没有定义,它是存放文件名的变量,在init中加上

self.file_name = ''
  • 状态标签部分
self.label_state = QLabel(self)
self.label_state.setGeometry(40, 120, 420, 160)
self.label_state.setAlignment(QtCore.Qt.AlignCenter)
self.label_state.setStyleSheet("font-size:50px;font-weight:bold;")
self.label_state.setText("就绪")
  • 确认按钮部分
self.butn = QPushButton(self)
self.butn.setGeometry(200,305,100,30)
self.butn.setText("开始压缩")

以上用到了QLabel、QPushButton和QtCore同样要导入

from PyQt5.QtWidgets import QLabel,QPushButton
from PyQt5 import QtCore

2.3 拖入图片功能

现在程序的外形都有了,如图所示。

基于TinyPNG所提供API的自动上传压缩可视化py脚本_第1张图片

但是还没有相应的功能,本小节就实现运行图片拖入程序并获取位置信息。
在init中加入代码启用拖拽功能

# 启用拖拽
self.setAcceptDrops(True)

文件拖拽如控件时会自动调用dragEnterEvent函数,因此在类中重写此函数。

# evn参数接收拖入事件
def dragEnterEvent(self, evn):
    # 获取文件名
    self.file_name=evn.mimeData().text()
    # 截取需要部分
    self.file_name=self.file_name[8:]
    # 设置路径标签文本
    self.label_picfile.setText(self.file_name)

路径标签中显示出路径说明一切都准备好了,可以点击按钮开始压缩。
evn.mimeData().text()返回的路径开头8个字符是“file:///”,需要将其剪切。

2.4 按钮功能

按下按钮就开始调用压缩函数,但是有一个问题,上传图片给tinypng然后返回结果需要一定的时间,而在这段时间内,程序会未响应的现象,心灰之余,该项目被我放弃了好长时间。现在闲着没事,搜索了一下,发现多线程可以解决这类问题。
按钮功能通过信号与槽机制实现,定义槽函数,即按钮按下后需要做的事

def butn_job(self):
    if self.file_name != '':
        # 设置状态标签文本,表明正在压缩
        self.label_state.setText("等")
        # 新建线程,指明该线程需执行的函数
        self.thread_deal = threading.Thread(target=self.deal_pic)
        # 线程启动
        self.thread_deal.start()
    # 没有拖入图片时不工作
    else:
        self.label_state.setText("拖入图片")

线程需要threading模块

import threading

按钮的信号需要与槽连接,内置的信号为clicked函数,在init中连接

self.butn.clicked.connect(self.butn_job)

2.5 压缩

直接写

def deal_pic(self):
    # 断开按钮信号与槽的连接,处理图片时按钮点击无反应
    self.butn.blockSignals(True)
    # 压缩图片
    source = tinify.from_file(self.file_name)
    # 保存图片
    source.to_file(self.file_name)
    # 记录本月上传次数
    compressions_this_month =str(tinify.compression_count)
    # 次数没地方放,就显示在标题处吧
    self.setWindowTitle("图片压缩" + "本月使用:" + compressions_this_month)
    # 设置状态标签
    self.label_state.setText("就绪")
    # 恢复按钮信号与槽的连接
    self.butn.blockSignals(False)
    # 重置路径标签
    self.file_name = ''
    self.label_picfile.setText(self.file_name)

需要用到tinify模块

import tinify

需要提供key
在程序开头就给它加上

tinify.key = "xxxxxxxxxxxxxxxxxxx"

至此所有工作都完成,完整代码在最后,接下来是试验。

3 实机试验

我在使用的时候发现,未响应问题确实解决了,但等待时间也太久了,我加了一个计时功能以便直观感受。
导入time模块

tinify.key = "xxxxxxxxxxxxxxxxxxx"

在图片压缩的两行代码上下加入时间记录函数,并将耗时显示在标题

t1 = time.time()
source = tinify.from_file(self.file_name)
source.to_file(self.file_name)
t2 = time.time()
t = t2 - t1
compressions_this_month =str(tinify.compression_count)
self.setWindowTitle("图片压缩" + "本月使用:" + compressions_this_month + "用时:" + str(t))

随便个截图,277k,开始压缩了,看图

基于TinyPNG所提供API的自动上传压缩可视化py脚本_第2张图片

结束了,看图

基于TinyPNG所提供API的自动上传压缩可视化py脚本_第3张图片

37s,然后我下载了一个压缩图片的软件。

最后,此项目结束,有所收获,并尽量还原实际的思考过程。

完整代码

# -*- coding:utf-8 -*-
# by xiyue
import sys
import threading
import tinify
import time
from PyQt5.QtWidgets import QWidget,QLabel,QApplication,QPushButton
from PyQt5 import QtCore

class xiiyue(QWidget):
    def __init__(self):
        super(xiiyue, self).__init__()
        #定义变量
        self.file_name = ''
        # 窗口标题
        self.setWindowTitle("图片压缩")
        # 定义窗口大小
        self.resize(500, 400)
        #布置控件
        self.load()
        # 启用Drops方法
        self.setAcceptDrops(True)
        #signal and slot
        self.butn.clicked.connect(self.butn_job)

    def load(self):
        #静态标签
        self.label_s = QLabel(self)
        self.label_s.setGeometry(40, 65, 60, 30)
        self.label_s.setStyleSheet("color:red;font-size:15px;font-weight:bold;")
        self.label_s.setAlignment(QtCore.Qt.AlignCenter)
        self.label_s.setText("图片")

        #路径标签
        self.label_picfile = QLabel(self)
        self.label_picfile.setGeometry(130, 50, 330, 60)
        self.label_picfile.setStyleSheet("background-color:white;font-size:15px;")
        self.label_picfile.setAlignment(QtCore.Qt.AlignLeft |QtCore.Qt.AlignVCenter)
        self.label_picfile.setText(self.file_name)
        self.label_picfile.setWordWrap(True)

        #状态标签
        self.label_state = QLabel(self)
        self.label_state.setGeometry(40, 120, 420, 160)
        self.label_state.setAlignment(QtCore.Qt.AlignCenter)
        self.label_state.setStyleSheet("font-size:50px;font-weight:bold;")
        self.label_state.setText("就绪")

        #确认按钮
        self.butn = QPushButton(self)
        self.butn.setGeometry(200,305,100,30)
        self.butn.setText("开始压缩")

    # 鼠标拖入事件
    def dragEnterEvent(self, evn):
        self.file_name=evn.mimeData().text()
        self.file_name=self.file_name[8:]
        self.label_picfile.setText(self.file_name)

    # 按钮函数
    def butn_job(self):
        if self.file_name != '':
            self.label_state.setText("等")
            self.thread_deal = threading.Thread(target=self.deal_pic)
            self.thread_deal.start()
        else:
            self.label_state.setText("拖入图片")

    # 压缩图片
    def deal_pic(self):
        self.butn.blockSignals(True)
        t1 = time.time()
        source = tinify.from_file(self.file_name)
        source.to_file(self.file_name)
        t2 = time.time()
        t = t2 - t1
        compressions_this_month =str(tinify.compression_count)
        self.setWindowTitle("图片压缩" + "本月使用:" + compressions_this_month + "用时:" + str(t))
        self.label_state.setText("就绪")
        self.butn.blockSignals(False)
        self.file_name = ''
        self.label_picfile.setText(self.file_name)




if __name__ == "__main__":
    tinify.key = "xxxxxxxxxxxxxxxxxxxxxxxxx"
    app = QApplication(sys.argv)
    xiyue = xiiyue()
    xiyue.show()
    sys.exit(app.exec_())

你可能感兴趣的:(基于TinyPNG所提供API的自动上传压缩可视化py脚本)