本来打算剩余的几天寒假是好好看会儿高数的,结果吧,可能在家里实在是一点书都看不下去,昨晚看了俩小时高数骨头差点散架,学习这种事还是回学校再说吧。
倒是有一点记忆尤甚,空间中的点$(x,y,z)$到$x$轴的距离是多少,我居然脑子有坑算了向径的模,在和向径的$\alpha$角来了个正弦操作,晚上散步才想起来,这个距离不就是$y^2+z^2$嘛。。。
无聊到玩手机,还不如玩会儿带你闹,这几天的收获也较为丰富。
- 自己没事瞎折腾,整理了windows窗口,任务栏,还安装了Mac系统下的dock栏,用(看)着很爽,但是,突然发现电脑的时间被我整没了,也就是我打开电脑看不了时间,很无语。于是就自己用所学知识(python+QT+pyinstaller)写了个图形化的小软件,可能这是我电脑上第一次运行自己安装的软件吧,当然这个过程遇到了一堆坑。
爬虫的东西准备放下一篇博客了。
前言传记
电脑总体的折腾效果如下,这个dock真的比windows的任务栏舒服多了。
然后安排了一些新软件
- 快速启动 Wox
- 快速查找 Everything
- 及时预览 Quciklook
更多强大实惠的软件look这里:
https://camuseblog.top/2019-02-10-/software/
软件开发记
回归正题,很早之前接触了QT也写过一些小程序,还解决了上学期的课设,感觉基本的问题应该能驾驭了,既然把自己电脑的时间折腾没了,就自己写一个时钟小程序吧。
思路很简单,调时间的库,把返回的时间截取为字符串,在窗口(QTextEdit)中显示就行了,然后用pyinstaller
打包一下,结果到处是坑23333。
不过在各种谷歌和stackoverflow的帮助下还是解决了,没有谷歌和stackoverflow我可能真的生活不能自理。
软件效果如下,点击show time就可以显示时间啦
控件线程的坑
QTextEdit这个控件如果想实现刷新功能,就是显示完上一时刻的时间后,清空控件,然后显示下一时刻的时间,得进行如下操作,仅仅clear()
是不够的。
有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态。例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响应用户的任何操作,窗口也不会重新绘制,从而处于“无法响应”状态,这是一个非常糟糕的体验 。
在这种情况下,有一种方法是使用多线程,即在子线程中处理文件保存,主线程负责界面相关。
而如果不想使用多线程,最简单的办法就是在文件保存过程中调用QtWidgets.QApplication.processEvents()
,该函数的作用是让程序处理那些还没有处理的事件,然后再把使用权返回给调用者。
1 2 3
| QtWidgets.QApplication.processEvents() self.ui.results_window.clear()
|
字体的坑
导入北京时间后,截取字符串一切OK,可就是显示不到QT的窗口中去(QTextEdit)。其实也不是,当时怀疑是转义的问题,我当时用字符串测试了一下,22,33,44这些数字都能显示上去,唯独11这个数字显示不上去???得亏是11点写的这个程序,不然真的又是一个BUG。为什么呢?
其实原因很吐血,我随便换了个别的字体,就又能正常显示了,无语。可能原因:QTextEdit的字体我设置的是palatino
,这个字体无法显示11
这个字符串。
(虽然我知道可能不是字体的原因,但每个程序员都能碰到一些脑仁疼无法解释的玄学BUG)
pyinstaller的坑
很早之前听说过这个库,能把.py
文件打包为可执行的.exe
文件,我试了一下,又是一堆坑。
比如,GUI界面的程序打包姿势和命令行的程序打包姿势是不一样的,而且尤其是使用了PyQt5的情况下。
正确打包姿势为:
1
| pyinstaller -F -w -i logo.ico clock.py
|
如果使用了QTdesigner
工具的话,add-data
把外部的ui
文件包含进来,不然的话:整个过程没有错误没有警告,但是程序就是不对让你找bug到怀疑人生。
而且,GUI文件是不需要输出命令行console
的,所以后面使用-w
取消console
的输出,不然软件运行会有个大黑窗口。
pyinstaller
虽然是python的第三方库,也能pip
安装,但是千万别import pyinstaller
,没有这个操作,pyinstaller
就是在cmd
里面直接用的。(我以为是我pip
错了包的原因,又瞎搜了半天,无语)。
而且,pyinstaller
之后会生成dist
文件,需要把程序执行所需要的图片,数据,copy一份到dist
文件夹里面,和.exe
文件在同一个目录。
经过了无数的坑,终于开发出了自己的.exe
程序,自己留着用呗。但是这个是个很好的开始啊,比如给这个软件扩充功能,能显示地区,温度等信息,或者当个记事本,记录一些待解决事件,这的确是个好的开始,但是这些功能等着以后闲的没事在扩充吧。
时钟程序如下:那些png文件什么的,自己寻找一个吧。那个.ui
文件我是使用的QTdesigner,布局的话自己画一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| import sys
from PyQt5.QtWidgets import QMainWindow, qApp, QApplication, \ QVBoxLayout, QToolTip, QMessageBox, QAction from PyQt5 import uic, QtWidgets, QtGui
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QFont
from PyQt5.QtCore import QCoreApplication, Qt from datetime import datetime, timedelta, timezone import time import PyQt5.QtGui
Ui_MainWindow, QtBaseClass = uic.loadUiType("mainWindow.ui")
class MyApp(QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.statusBar().showMessage('Ready') self.ui.pushButton.clicked.connect(self.calculate_time) self.setWindowTitle('CLOCK') self.setWindowOpacity(0.8)
palette = QtGui.QPalette() pix = QtGui.QPixmap('test.jpg') pix = pix.scaled(self.width(),self.height()) palette.setBrush(QtGui.QPalette.Background,QtGui.QBrush(pix)) self.setPalette(palette)
self.setWindowIcon(QIcon('icon.png')) QToolTip.setFont(QFont('SansSerif', 10)) self.setToolTip('This is my Clock')
exit_action = QAction(QIcon('exit.png'), 'Exit', self) exit_action.setShortcut('Ctrl+Q') exit_action.triggered.connect(qApp.quit) self.ui.toolbar = self.addToolBar('Exit') self.ui.toolbar.addAction(exit_action)
exit_action1 = QAction(QIcon('exit.png'), '&Exit', self) exit_action1.setShortcut('Ctrl+Q') exit_action1.setStatusTip('Exit application') exit_action1.triggered.connect(qApp.quit) menu_bar = self.menuBar() file_menu = menu_bar.addMenu('&退出') file_menu.addAction(exit_action1)
def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.close()
def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', \ "Are you sure to quit?", \ QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore()
def calculate_time(self): time_number = 0 self.ui.results_window.clear() while time_number < 20: utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc) bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8))) bj_dt = str(bj_dt) bj_dt = bj_dt[0:19] self.ui.results_window.setText(' '+bj_dt)
QtWidgets.QApplication.processEvents() time.sleep(1)
self.ui.results_window.clear() time_number = time_number + 1
QtWidgets.QApplication.processEvents() self.ui.results_window.clear() self.ui.results_window.setText(' I don\'t wanna to show time,try button again~')
if __name__ == "__main__": app = QApplication(sys.argv) window = MyApp() window.show() sys.exit(app.exec_())
|
成品
归结原因
近期系统的学了一下PyQt5的知识后,总结了踩坑的原因:干活之前不读文档,吓折腾只会浪费更多时间。