Pyqt5实践:实现快捷方式软件@TOC
工具准备 Python3.x;
Python库:pyqt5
直接贴代码,由于工作繁忙,实在没时间写文档0.0,代码里面都有注释,有不懂评论区问。(先看看反响咋样,如果看的人多我再写具体思路。)
界面代码,使用QtDesigner画的,再通过pyuic转换的。
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'Form.ui'## Created by: PyQt5 UI code generator 5.13.0## WARNING! All changes made in this file will be lost!from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") Form.resize(250, 500) Form.setStyleSheet("#Form{n"" border-top-left-radius:10px;n"" border-bottom-left-radius:10px;n""n""}n""QGroupBox{n""border-top:0px solid rgb(190, 190, 190);n""border-right:0px solid rgb(190, 190, 190);n""border-bottom:2px solid rgb(190, 190, 190);n""border-left:0px solid rgb(190, 190, 190);n""font: 75 10pt "微软雅黑";n""}") self.verticalLayout = QtWidgets.QVBoxLayout(Form) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.choose_exe_btn = QtWidgets.QPushButton(Form) self.choose_exe_btn.setObjectName("choose_exe_btn") self.horizontalLayout.addWidget(self.choose_exe_btn) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.verticalLayout.addLayout(self.horizontalLayout) self.scrollArea = QtWidgets.QScrollArea(Form) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth()) self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setMinimumSize(QtCore.QSize(250, 475)) self.scrollArea.setMaximumSize(QtCore.QSize(250, 475)) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.main_widget = QtWidgets.QWidget() self.main_widget.setGeometry(QtCore.QRect(0, 0, 248, 473)) self.main_widget.setMinimumSize(QtCore.QSize(240, 470)) self.main_widget.setStyleSheet("#main_widget{n"" background-color:rgb(68, 68, 68);n""}n""n""QPushButton{n"" border:1px solid lightgray;n"" background:rgb(255, 255, 255);n""}n""QPushButton::hover{n"" border-color:rgb(0, 170, 255);n"" background:transparent;n""}") self.main_widget.setObjectName("main_widget") self.main_layout = QtWidgets.QVBoxLayout(self.main_widget) self.main_layout.setContentsMargins(0, 0, 0, 6) self.main_layout.setObjectName("main_layout") spacerItem1 = QtWidgets.QSpacerItem(20, 464, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.main_layout.addItem(spacerItem1) self.scrollArea.setWidget(self.main_widget) self.verticalLayout.addWidget(self.scrollArea) self.retranslateUi(Form) QtCore.QmetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "Form")) self.choose_exe_btn.setText(_translate("Form", "选择程序"))
主要代码:
import sys, osif hasattr(sys, 'frozen'): os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH']from Form import Ui_Formfrom PyQt5.QtWidgets import QWidget, QApplication, QGroupBox, QLabel, QPushButton, QAction, QMenu, QSystemTrayIconfrom PyQt5.QtCore import Qt, QRectfrom PyQt5.QtGui import QCursor, QPixmap, QIconfrom PyQt5.Qt import QPropertyAnimationfrom win32 import win32api, win32gui, win32printfrom win32.lib import win32confrom win32.win32api import GetSystemMetricsimport win32uiimport win32guiimport win32conimport win32apiSCREEN_WEIGHT = 1920SCREEN_HEIGHT = 1080WINDOW_WEIGHT = 250WINDOW_HEIGHT = 500class mainwindow(QWidget, Ui_Form): def __init__(self): super(mainwindow, self).__init__() # 初始化父类 self.setupUi(self) self.setWindowOpacity(0.8) # 设置窗口透明度 self.choose_exe_btn.clicked.connect(self.choose_exe_func) self.choose_exe_btn.hide() self.setAcceptDrops(True) self.setWindowFlags(Qt.framelessWindowHint|Qt.WindowStaysOnTopHint) #顶层显示 self.setAutoFillBackground(False) self.setAttribute(Qt.WA_TranslucentBackground, True) # 设置退出选项 iconpath = "icon.png" quit_action = QAction('退出', self, triggered=self.quit) quit_action.setIcon(QIcon(iconpath)) self.tray_icon_menu = QMenu(self) self.tray_icon_menu.addAction(quit_action) self.tray_icon = QSystemTrayIcon(self) self.tray_icon.setIcon(QIcon(iconpath)) self.tray_icon.setContextMenu(self.tray_icon_menu) self.tray_icon.show() self.mouse_drag_pos = None self.is_left_mouse = False self.resize(WINDOW_WEIGHT, WINDOW_HEIGHT) SCREEN_WEIGHT, SCREEN_HEIGHT = self.get_real_resolution() self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.moved = False self.init() def init(self): # 读取配置 f = open("config.ini", "r", encoding="utf-8") s =f.read() f.close() l1 = s.split(";") for l in l1: if len(l) > 0: file_path = l.split(",")[0] file_name = l.split(",")[1] self.append_shortcut(file_path, file_name) def choose_exe_func(self): # 这里原先有个按钮,我没做功能,隐藏了 sener = self.sender() print(sener) def get_real_resolution(self): """获取真实的分辨率""" hDC = win32gui.GetDC(0) # 横向分辨率 w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES) # 纵向分辨率 h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES) return w, h def get_screen_size(self): """获取缩放后的分辨率""" w = GetSystemMetrics(0) h = GetSystemMetrics(1) return w, h def dragEnterEvent(self, QDragEnterEvent): # 这是拖拽文件相关的 QDragEnterEvent.acceptProposedAction() #放行,否则不会执行dropEvent()函数 def dropEvent(self, QDropEvent): # 这是拖拽文件相关的 file_url_list = QDropEvent.mimeData().urls() if len(file_url_list) <= 0: return for file_url in file_url_list: file_path = str(file_url.path().lstrip('/')) file_name = str(file_url.fileName()) if file_name.endswith(".lnk") or file_name.endswith(".exe"): self.append_shortcut(file_path, file_name) def mousePressEvent(self, QMouseEvent): # 移动窗体相关的 if QMouseEvent.button() == Qt.LeftButton: self.mouse_drag_pos = QMouseEvent.globalPos() - self.pos() self.is_left_mouse = True self.setCursor(QCursor(Qt.OpenHandCursor)) QMouseEvent.accept() def mouseMoveEvent(self, QMouseEvent): # 移动窗体相关的 if Qt.LeftButton and self.is_left_mouse: self.move(QMouseEvent.globalPos() - self.mouse_drag_pos) QMouseEvent.accept() def mouseReleaseEvent(self, QMouseEvent): # 移动窗体相关的 self.is_left_mouse = False self.setCursor(QCursor(Qt.ArrowCursor)) def enterEvent(self, event): # 隐藏界面相关的 self.hide_or_show('show', event) def leaveEvent(self, event): # 隐藏界面相关的 self.hide_or_show('hide', event) def hide_or_show(self, mode, event): # 隐藏界面相关的 pos = self.frameGeometry().topLeft() if mode == 'show' and self.moved: if pos.x() + WINDOW_WEIGHT >= SCREEN_WEIGHT: # 右侧显示 self.startAnimation(SCREEN_WEIGHT - WINDOW_WEIGHT + 2, pos.y()) event.accept() self.moved = False elif pos.x() <= 0: # 左侧显示 self.startAnimation(0, pos.y()) event.accept() self.moved = False elif pos.y() <= 0: # 顶层显示 self.startAnimation(pos.x(), 0) event.accept() self.moved = False elif mode == 'hide': if pos.x() + WINDOW_WEIGHT >= SCREEN_WEIGHT: # 右侧隐藏 self.startAnimation(SCREEN_WEIGHT - 2, pos.y()) event.accept() self.moved = True elif pos.x() <= 2: # 左侧隐藏 self.startAnimation(2 - WINDOW_WEIGHT, pos.y()) event.accept() self.moved = True elif pos.y() <= 2: # 顶层隐藏 self.startAnimation(pos.x(), 2 - WINDOW_HEIGHT) event.accept() self.moved = True def startAnimation(self, width, height): # 隐藏界面相关的 animation = QPropertyAnimation(self, b"geometry", self) startpos = self.geometry() animation.setDuration(200) newpos = QRect(width, height, startpos.width(), startpos.height()) animation.setEndValue(newpos) animation.start() def append_shortcut(self, file_path, file_name): # 增加新的快捷方式 index = len(self.main_widget.children()) -1 if index > 3: self.main_widget.setMinimumSize(240, 100*(index+1)) for child in self.main_widget.children(): if child.property("file_path") == file_path: return print(file_path,file_name) self.save_icon(file_path,file_name) group_box = QGroupBox() group_box.setFixedSize(240,100) group_box.setProperty("file_name", file_name) #添加自定义属性,我这里使用是为了储存文件路径和文件名,方便后面打开 group_box.setProperty("file_path", file_path) icon_lab = QLabel(group_box) #icon_lab.setText("icon") if os.path.exists(r"icon/%s.bmp" % file_name.split(".")[0]): pix = QPixmap(r"icon/%s.bmp" % file_name.split(".")[0]) else: pix = QPixmap(r"icon.png") icon_lab.setPixmap(pix) icon_lab.setScaledContents(True) #self.update() icon_lab.setGeometry(10,10,50,50) title_lab = QLabel(group_box) title_lab.setText(file_name) title_lab.setGeometry(10, 70, 200, 20) start_btn = QPushButton(group_box) start_btn.setText("运行") start_btn.setGeometry(130, 40, 50, 20) start_btn.clicked.connect(self.start_func) start_btn.setProperty("file_name", file_name) start_btn.setProperty("file_path", file_path) del_btn = QPushButton(group_box) del_btn.setText("删除") del_btn.setGeometry(185, 40, 50, 20) del_btn.clicked.connect(self.del_func) del_btn.setProperty("file_name", file_name) del_btn.setProperty("file_path", file_path) del_btn.setProperty("index", index+1) self.main_layout.insertWidget(index, group_box) self.save_icon(file_path, file_name) def del_func(self): # 删除快捷方式 btn = self.sender() index = btn.property("index") file_name = btn.property("file_name") try: os.remove(r"icon/%s.bmp" % file_name.split(".")[0]) except Exception: pass self.main_layout.removeWidget(self.main_widget.children()[index]) for child in self.main_widget.children()[index].children(): child.deleteLater() self.main_widget.children()[index].deleteLater() def start_func(self): # 打开软件 btn = self.sender() # sebder()是Qt5的方法,通过该方法可获取触发该槽函数信号来源对象,说简单点就是获取触发该函数的按钮对象 file_path = btn.property("file_path")# 通过自定义属性名获取其值 file_name = btn.property("file_name") cmd = 'cd %s&%s:&start "" "%s"' % (file_path.rstrip(file_name), file_path[0], file_name) os.system(cmd) def save_icon(self, file_path, file_name): # 保存图标 large, small = win32gui.ExtractIconEx(file_path, 0) try: useIcon = large[0] destroyIcon = small[0] except Exception: return win32gui.DestroyIcon(destroyIcon) hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0)) hbmp = win32ui.CreateBitmap() hbmp.CreateCompatibleBitmap(hdc, 32, 32) hdc = hdc.CreateCompatibleDC() hdc.SelectObject(hbmp) hdc.DrawIcon((0, 0), useIcon) savePath = r"icon/%s.bmp" % file_name.split(".")[0] hbmp.SaveBitmapFile(hdc, savePath) def save_config(self): # 保存当前所有的快捷方式 f = open("config.ini", "w", encoding='utf-8') s = "" for child in self.main_widget.children(): file_path = child.property("file_path") file_name = child.property("file_name") if file_name: s = s + "%s,%s;" % (file_path, file_name) f.write(s) f.close() def quit(self): # 退出,这里感觉还有点问题,但有说不出来 self.save_config() self.close() sys.exit()if __name__ == "__main__": app = QApplication(sys.argv) w = mainwindow() w.show() sys.exit(app.exec_())
icon图标文件网上自己找,随便一张都可以。软件使用方法是将软件直接拖到软件里面,即可生成快捷方式。当软件处于窗口最左端和最右端时,会自动隐藏。
如果需要打包好的软件和软件源码,私信发我你的邮件地址,我邮件发给你(不要钱…)。