序
2021款联想拯救者电流声/啸叫问题非官方解决方案https://zhuanlan.zhihu.com/p/398031636这个东东,它没有图形界面,运行和不运行,前台看不出来,所以想弄个有图形界面的版本
调查
主要看看要用到哪些api。
这个问题的关键词是:pyqt,托盘。有空再弄吧……
程序托盘+消息气泡
事物总是从低级到高级的,关于qt托盘,目前处于0级,所以,作为开头,一个可以CV即用的例子是必要的。如下所示。
窗口最大化时的托盘
窗口关闭时的托盘 效果挺好的。
有了这个托盘以后,是不是能自己做一个定时屏保呢?就像stretchly。
Stretchly--The break time reminder apphttps://hovancik.net/stretchly/about/#humans-and-tools
程序托盘+定时闹钟
第一个版本:pyQT播放音乐
还有代码,还能运行。
研究
看看这些api怎么用的,拿来利用一下。
主要是,音频播放,程序托盘这两个部分。
研究路线目前定成这样:
pyqt5——播放音频——循环播放音频——程序托盘——打包为exe
pyqt5,在前几节CSDN里,已经了解了一点了,此处就跳过了。
播放音频
理论操作流程
Qt | 播放音频文件 QMediaplayerhttps://zhuanlan.zhihu.com/p/460799026当参数为0时可以实现静音的效果——这个是需要的。
实际操作
因为是qt,所以必须得先弄个窗口,不弄报错……即使是空白的。别人是战术性停顿,那这个应该叫战术性空白窗口吧……
然后按上面那个加点代码进去。
from PyQt5.QtMultimedia import QMediaPlayer,QMediaContent
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication,QMainWindow
import sys
from PyQt5.uic import loadUi
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__()#super()构造器方法返回父级的对象。
self.ui=loadUi("music_play.ui")#加载ui
self.player= QMediaPlayer() # 初始化播放器
self.player.setVolume(100) # 设置策略
url = QUrl.fromLocalFile("test0.mp3")
self.player.setMedia(QMediaContent(url))
self.player.play()
print("test")
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.ui.show()
sys.exit(app.exec_())
结果
弹着窗口唱着歌
循环播放音频
一遍播完不行呐,得循环起来才行
怎么办呢?
理论方法
播放列表。
具体代码
在循环中播放背景音乐Qthttps://qa.1r1g.com/sf/ask/2638343151/ 卡在了loop的设置上,python里没有C++的::
枚举变量
搞不明白,直接传数字吧,能用就行……
实际代码
from PyQt5.QtMultimedia import QMediaPlayer,QMediaContent,QMediaPlaylist
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication,QMainWindow
import sys
from PyQt5.uic import loadUi
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__()#super()构造器方法返回父级的对象。
self.ui=loadUi("music_play.ui")#加载ui
#设置播放列表
self.play_list=QMediaPlaylist()
self.play_list.addMedia(QMediaContent(QUrl.fromLocalFile("test1.mp3")))
self.play_list.setPlaybackMode(3)#听说3表示loop
#设置播放器
self.player= QMediaPlayer()
self.player.setVolume(50)
self.player.setPlaylist(self.play_list)
self.player.play()
print("test")
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.ui.show()
sys.exit(app.exec_())
运行结果
弹着一个窗口,循环播放着同一段音频
到这里,目的就实现了。但是有个托盘更好一点。
程序托盘
托盘,tray
理论方法
托盘的菜单以及菜单里的选项,怎么做?从0开始,文档英文的,也看不懂,完全是一团浆糊。
看不懂就分析,分析不出来就往会的上面靠。
和之前的相比,只是多了个托盘而已。那末,只要搞明白托盘如何实现,托盘和GUI程序如何沟通,大致就可以了。
查了查,托盘菜单界面和代码是这么个对应的关系。
点击事件大概就是一些信号槽函数的绑定。
差不多就是这样吧。
代码实现
但是写程序的时候往往会遇到很多问题。
比如,这个关闭,重载了但是莫得反应。
from PyQt5.QtMultimedia import QMediaPlayer,QMediaContent,QMediaPlaylist
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication,QMainWindow
import sys
from PyQt5.uic import loadUi
'''导入UI界面组件相关的模块'''
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
'''导入应用操作相关的模块'''
import sys
from PyQt5.QtMultimedia import *
#主窗口
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__()#super()构造器方法返回父级的对象。
self.ui=loadUi("music_play.ui")#加载ui
#设置播放列表
self.play_list=QMediaPlaylist()
self.play_list.addMedia(QMediaContent(QUrl.fromLocalFile("test1.mp3")))
self.play_list.setPlaybackMode(3)#听说3表示loop
#设置播放器
self.player= QMediaPlayer()
self.player.setVolume(50)
self.player.setPlaylist(self.play_list)
self.player.play()
print("test")
self.tray = TrayModel(self)#这个self,可能对应的是构造函数里的window
def closeEvent(self, a0: QCloseEvent) -> None:
a0.ignore()#忽略这个关闭
self.ui.hide()#隐藏窗体
self.tray.show()#显示托盘
print("关闭")
#所谓的托盘
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QCloseEvent
# 首先不管其他的,先创建一个类实现托盘功能,最后将托盘功能融入到小闹钟的源代码里面应用就成了。
class TrayModel(QSystemTrayIcon):
def __init__(self, Window):
super(TrayModel, self).__init__()
self.window = Window
self.init_ui()
def init_ui(self):
# 初始化菜单
self.menu = QMenu()
self.manage_action = QAction('小闹钟设置', self, triggered=self.manage_clock)#参考QT设计师里的动作编辑器
self.quit_action = QAction('退出应用', self, triggered=self.quit_clock)#动作-发射信号-信号槽函数,还能这么写
self.menu.addAction(self.manage_action)
self.menu.addAction(self.quit_action)
self.setContextMenu(self.menu)
self.setIcon(QIcon("E:6.jpg"))
self.icon = self.MessageIcon()
self.activated.connect(self.app_click)
#托盘菜单项对应的槽函数
def manage_clock(self):
self.window.showNormal()#正常显示原窗口
self.window.activateWindow()#未知
def quit_clock(self):
quit()#大概是退出程序的意思
def app_click(self, reason):
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.ui.show()
sys.exit(app.exec_())
哪里出了问题……
这个链接里,重载closeevent,结果很正常
用self,正常了,然后又改成self.ui,也正常了。为什么呢?
可以一边唱歌一边重载虚函数了。
from PyQt5.uic import loadUi
'''导入UI界面组件相关的模块'''
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
'''导入应用操作相关的模块'''
import sys
from PyQt5.QtMultimedia import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QCloseEvent
#主窗口
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
#super().__init__()#super()构造器方法返回父级的对象。
self.ui=loadUi("music_play.ui")#加载ui
#self.ui=loadUi("main_widget.ui")#加载ui
#设置播放列表
self.play_list=QMediaPlaylist()
self.play_list.addMedia(QMediaContent(QUrl.fromLocalFile("test0.mp3")))
self.play_list.setPlaybackMode(3)#听说3表示loop
#设置播放器
self.player= QMediaPlayer()
self.player.setVolume(50)
self.player.setPlaylist(self.play_list)
self.player.play()
print("test")
def closeEvent(self, event) -> None:
print("closeenent的重载虚函数")
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
倒数第二行,win.show就能正常重载,win.ui.show就不能正常重载。原因就是这个。
这个好像没法解决……把ui保存成py应该行。
那就不重载ui窗口的X了,换个方法吧……
还有一个存在已久的问题,找了找,好像是因为屏幕分辨率
结果
from PyQt5.uic import loadUi
'''导入UI界面组件相关的模块'''
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5 import QtWidgets, QtCore, QtGui
'''导入应用操作相关的模块'''
import sys
from PyQt5.QtMultimedia import *
from PyQt5.QtWidgets import *
#主窗口
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
#super().__init__()#super()构造器方法返回父级的对象。
self.ui=loadUi("music_play.ui")#加载ui
#self.ui=loadUi("main_widget.ui")#加载ui
#设置播放列表
self.play_list=QMediaPlaylist()
self.play_list.addMedia(QMediaContent(QUrl.fromLocalFile("test0.mp3")))
self.play_list.setPlaybackMode(3)#听说3表示loop
#设置播放器
self.player= QMediaPlayer()
self.player.setVolume(0)
self.player.setPlaylist(self.play_list)
self.player.play()
self.tray = TrayModel(self)#这个self,可能对应的是构造函数里的window
self.ui.pushButton_goToTray.clicked.connect(self.go_to_tray)
imgName="explain.jpg"
jpg = QtGui.QPixmap(imgName).scaled(self.ui.label_2.width(), self.ui.label_2.height())
self.ui.label_2.setPixmap(jpg)
self.ui.hide()
self.tray.show()#显示托盘
def go_to_tray(self):
print("最小化到托盘")
self.ui.hide()
self.tray.show()#显示托盘
class TrayModel(QSystemTrayIcon):
def __init__(self, Window):
super(TrayModel, self).__init__()
self.window = Window.ui
self.main_window=Window
self.init_ui()
def init_ui(self):
# 初始化菜单
self.menu = QMenu()
self.play_action=QAction('开始播放', self, triggered=self.start_play)
self.stop_action=QAction('暂停播放', self, triggered=self.stop_play)
self.open_win_action = QAction('打开窗口', self, triggered=self.open_win)#参考QT设计师里的动作编辑器
self.quit_action = QAction('退出应用', self, triggered=self.quit)#动作-发射信号-信号槽函数,还能这么写
self.menu.addAction(self.play_action)
self.menu.addAction(self.stop_action)
self.menu.addAction(self.open_win_action)
self.menu.addAction(self.quit_action)
self.setContextMenu(self.menu)
self.setIcon(QIcon('e:/cpu.jpg'))
#self.icon = self.MessageIcon()
# self.activated.connect(self.app_click)
#托盘菜单项对应的槽函数
def start_play(self):
self.main_window.player.play()
def stop_play(self):
self.main_window.player.pause()
def open_win(self):
self.main_window.ui.showNormal()#正常显示原窗口
self.main_window.ui.activateWindow()#未知
def quit(self):
quit()#大概是退出程序的意思
# def app_click(self, reason):
# pass
if __name__ == '__main__':
#QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv)
win = MainWindow()
#win.ui.show()
sys.exit(app.exec_())
需要一点点资源
运行结果
打包成exe,安装到另一个电脑里,托盘就无效了……
那就算了吧,是这个意思就行了。