PyQT is a Python wrapper around the QT GUI application development framework
实际上很多项目都是用的pyqt4,但既然pyqt5已经出了。本次项目就干脆用pyqt5,方便后续维护。
然而,网上的资料还是pyqt4更多一些,pyqt5的资料较少,官方文档对于某些API的介绍只有一行,这种情况就只能翻翻qt的C++文档了。
install(max os X) :
brew install pyqt –with-python3
看到一个计算圆周率每一位的GUI小程序,觉得还不错。作者是用pyqt4和python2写的。直接复制过来,用pyqt5和python3会有些问题。另外,原作者贴的代码似乎漏了一个”/”,导致结果有误。
1
2
3
4
5
6
7
8
9
def pi_digits():
"""generator for digits of pi"""
q,r,t,k,n,l = 1,0,1,1,3,3
while True:
if 4*q+r-t < n*t:
yield n
q,r,t,k,n,l = (10*q,10*(r-n*t),t,k,(10*(3*q+r))/t-10*n,l)
else:
q,r,t,k,n,l = (q*k,(2*q+r)*l,t*l,k+1,(q*(7*k+2)+r*l)/(t*l),l+2)
见so:
-https://stackoverflow.com/questions/9004789/1000-digits-of-pi-in-python
修正过的代码如下:
def pi_digits():
q, r, t, k, m, x = 1, 0, 1, 1, 3, 3
for j in range(1000):
if 4 * q + r - t < m * t:
yield m
q, r, t, k, m, x = 10*q, 10*(r-m*t), t, k, (10*(3*q+r))//t - 10*m, x
else:
q, r, t, k, m, x = q*k, (2*q+r)*x, t*x, k+1, (q*(7*k+2)+r*x)//(t*x), x+2
完整代码,适用于pyqt5,python3.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#---author:SErHo-----
#---url: https://gist.github.com/2773445
from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import (QWidget, QLabel,
QComboBox, QApplication,QSpinBox,QTextEdit,QPushButton,QHBoxLayout,QGridLayout)
from time import sleep
class RockPI(QWidget):
def __init__(self, parent=None):
super(RockPI, self).__init__(parent)
self.resize(480, 320)
spinLabel = QLabel("位数: ")
self.spinBox = QSpinBox()
self.spinBox.setMaximum(100000)
resultLabel = QLabel("结果: ")
self.resultText = QTextEdit()
self.resultText.setReadOnly(True)
self.startButton = QPushButton("开始")
self.resetButton = QPushButton("重置")
buttonLayout2 = QHBoxLayout()
buttonLayout2.addWidget(self.startButton)
buttonLayout2.addWidget(self.resetButton)
mainLayout = QGridLayout()
mainLayout.addWidget(spinLabel, 0, 0)
mainLayout.addWidget(self.spinBox, 0, 1)
mainLayout.addWidget(resultLabel, 1, 0, QtCore.Qt.AlignTop)
mainLayout.addWidget(self.resultText, 1, 1)
mainLayout.addLayout(buttonLayout2, 3, 1)
self.setLayout(mainLayout)
self.setWindowTitle("Rock PI")
#self.setWindowIcon(QtGui.QIcon('pi.png')) Icon for Windows
self.timer = None
self.startButton.clicked.connect(self.start)
self.resetButton.clicked.connect(self.reset)
def updateResult(self, value):
newValue = self.resultText.toPlainText() + value
self.resultText.setText(newValue)
if len(newValue)==(self.spinBox.value() + 1):
self.startButton.setText("开始")
self.startButton.setEnabled(False)
def reset(self):
if self.timer:
self.timer.add_post.disconnect(self.updateResult)
self.timer.stop()
self.timer.quit()
self.timer.wait()
self.timer.deleteLater()
self.timer = None
self.resultText.clear()
self.spinBox.setValue(0)
self.startButton.setText("开始")
self.startButton.setEnabled(True)
self.resetButton.setEnabled(False)
self.startButton.clicked.disconnect(self.suspend) ###连按两下重置 程序会崩溃。因为disconnect的前提是有connect
#可以考虑加个类似互锁的机制
self.startButton.clicked.connect(self.start)
def start(self):
self.digits = self.spinBox.value()
if not self.digits:
return
if not self.timer:
self.timer = Timer(self.digits)
self.timer.add_post.connect(self.updateResult)
self.timer.start()
self.startButton.setText("暂停")
self.resetButton.setEnabled(True)
self.startButton.clicked.disconnect(self.start)
self.startButton.clicked.connect(self.suspend)
def suspend(self):
self.timer.stop()
self.startButton.setText("开始")
self.startButton.clicked.disconnect(self.suspend)
self.startButton.clicked.connect(self.start)
class Timer(QtCore.QThread):
add_post = QtCore.pyqtSignal(str)
def __init__(self, digits, parent=None):
super(Timer, self).__init__(parent)
self.stoped = False
self.mutex = QtCore.QMutex() #Locker
self.pi = pi_digits()
self.digits = digits
self.printed = False
self.count = 0
def run(self):
with QtCore.QMutexLocker(self.mutex):
self.stoped = False
while True:
if self.stoped or (self.count==self.digits):
return
value = next(self.pi)
#print(value) output to terminal
if not self.printed:
value = str(value) + "."
self.printed = True
self.add_post.emit(str(value))
self.count += 1
sleep(0.1)
def stop(self):
with QtCore.QMutexLocker(self.mutex):
self.stoped = True
def pi_digits():
q, r, t, k, m, x = 1, 0, 1, 1, 3, 3
for j in range(1000):
if 4 * q + r - t < m * t:
yield m
q, r, t, k, m, x = 10*q, 10*(r-m*t), t, k, (10*(3*q+r))//t - 10*m, x
else:
q, r, t, k, m, x = q*k, (2*q+r)*x, t*x, k+1, (q*(7*k+2)+r*x)//(t*x), x+2
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
rockpi = RockPI()
rockpi.show()
sys.exit(app.exec_())
有一些网站上的文档还不错:
-https://pythonprogramming.net/basic-gui-pyqt-tutorial/
-http://pyqt.sourceforge.net/Docs/PyQt5/pyqt4_differences.html#qtgui-module
-https://stackoverflow.com/questions/41848769/pyqt5-object-has-no-attribute-connect
-http://pyqt.sourceforge.net/Docs/PyQt4/old_style_signals_slots.html?highlight=connect
-http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html?highlight=connect
-http://pyqt.sourceforge.net/Docs/PyQt5/
-http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html
-https://www.tutorialspoint.com/pyqt/pyqt_using_qt_designer.htm
-http://zetcode.com/gui/pyqt5/
-https://pythonspot.com/en/pyqt5/
中文论坛:
-http://www.qtcn.org/pyqtbook/