聲明:本文僅供學習用,旨在分享
基於項目需要,運用了PyQt進行了桌面版APP的開發,在此將一些常用方法進行總結。
1、環境的安裝及配置:
本人運用的是pycharm2016.3.2專業版,python3.6.0 64位,這兩者的安裝及配置不再闡述。首先是安裝相應模塊,運用豆瓣源安裝,安裝順序爲:sip=4.19.8>>>>PyQt5=5.11.3>>>>PyQt5-tools=5.11.3.1.4>>>>PyInstaller=3.5,
例如:pip install sip==4.19.8 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com。基於經驗安裝順序最好不要調換,否則有時會出現無法正常運行的情況。安裝完畢後配置打包環境:File---->settings---->Tools---->External Tools後選擇加號按鈕,如下圖
之後再按照下圖內容進行填寫:
其中:-D:指打包成多個文件,-D與-F對應,-F是打包成一個單獨的文件
-p:即path,指定python安裝包路徑
-i:指定圖標所在目錄
編寫完代碼後一般右鍵選擇External Tools再選擇剛纔創建的工具即可打包
有時打包會出現Unable to run PyInstaller - “Please install PyWin32 or pywin32-ctypes”的情況,需要到在PyInstaller文件夾中找到文件compat.py,並把以下兩行進行替換後保存即可。
from win32ctypes.pywin32 import pywintypes替換爲import pywintypes
from win32ctypes.pywin32 import win32api替換爲import win32api
除此外有時打包報for real_module_name, six_moduleAttributeError: ‘str’ object has no attribute 'items’錯誤,這時運行pip install -U --pre setuptools即可。
2、上述的模塊安裝後,就可以開始進行界面設計,首先是創建窗口,對於窗口類型pyqt提供了QMainWindow、QWidget、QDialog三種類型。其中:
- QMainWindow窗口包含菜單欄、工具欄、狀態欄、標題欄等,是最常見的窗口形式,也可以說是GUI程序的主窗口。
- QWidget類是所有用戶界面對象的基類,是用戶界面最基礎的原子,也可以容納其他的widget,它接收鼠標、鍵盤產生的事件,然後迴應。需注意的是setCentralWidget是隻能由mainwindow類調用的。
- QDialog是對話框窗口的基類,派生自QWidget,主要用來執行短期任務,或者與用戶進行互動,它可以是模態的,也可以是非模態的,應用場景比如可在關閉主程序關閉按鈕時彈出詢問是否關閉,或者當界面的按鈕過多不美觀時可把一些按鈕放在這種對話框中,例如註冊。
所以如果是主窗口,就使用QMainWindow類;如果不確定,有可能作爲頂層窗口,也有可能嵌入到其他窗口,就使用QWidget類;如果是對話框,就使用QDialog類。在功能上QMainWindow > QWidget > QDialog。
3、接下來將運用一個簡單的實例,模擬登錄後界面的跳轉及登錄時信息填寫錯誤後的提示來演示這三種類型的使用,代碼如下:
# -*- coding: utf-8 -*-
'''多窗口反覆切換'''
import sys # 導入系統
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
class Login_UI(QWidget): # 第一個窗口類
def __init__(self):
super(Login_UI, self).__init__()
self.resize(300, 200) # 設置窗口大小
self.setWindowTitle('登錄界面') # 設置窗口標題
self.Layout = QtWidgets.QVBoxLayout(self)#全局縱向
self.Layout.setContentsMargins(20,20,20,20)
self.Layout.setSpacing(0)
self.linewidget=QtWidgets.QWidget()
self.lineLayout = QtWidgets.QVBoxLayout(self.linewidget)
self.user=QtWidgets.QLineEdit(self)
self.user.setPlaceholderText('請輸入用戶名')
self.pwd=QtWidgets.QLineEdit(self)
self.pwd.setPlaceholderText('請輸入密碼')
self.lineLayout.addWidget(self.user)
self.lineLayout.addWidget(self.pwd)
self.buttonwidget = QtWidgets.QWidget()
self.buttonLayout=QtWidgets.QHBoxLayout(self.buttonwidget)
self.login = QPushButton('登錄', self) # 設置按鈕和按鈕名稱
self.login.setMaximumSize(QtCore.QSize(100,30)) # 設置按鈕大小
self.register = QPushButton('註冊', self)
self.register.setMaximumSize(QtCore.QSize(100, 30))
self.buttonLayout.addWidget(self.login)
self.buttonLayout.addWidget(self.register)
self.Layout.addWidget(self.linewidget)
self.Layout.addWidget(self.buttonwidget)
self.login.clicked.connect(self.login_function) # 將信號連接到槽
self.register.clicked.connect(self.register_function)
def login_function(self):
if 'test' in self.user.text() and '123' in self.pwd.text():
self.hide() # 隱藏此窗口
self.Main = MainUi()
self.Main.show() # 將第二個窗口顯示出來
else:
msgBox = QtWidgets.QMessageBox()
msgBox.setWindowTitle(u'提示')
msgBox.setText('信息錯誤,請重寫')
# 隱藏ok按鈕
msgBox.addButton(QMessageBox.Ok)
msgBox.button(QMessageBox.Ok).hide()
msgBox.exec_() # 模態對話框
def register_function(self):
register=Register()
if register.exec_():
self.user.setText(register.text.split('::')[0])
self.pwd.setText(register.text.split('::')[1])
class Register(QtWidgets.QDialog):
def __init__(self,parent=None,):
super(Register, self).__init__(parent)
self.Layout = QVBoxLayout(self) # 全局縱向
self.setWindowTitle('註冊界面')
self.user = QtWidgets.QLineEdit(self)
self.user.setPlaceholderText('請輸入用戶名')
self.pwd = QtWidgets.QLineEdit(self)
self.pwd.setPlaceholderText('請輸入密碼')
self.jump = QPushButton('完成', self) # 設置按鈕和按鈕名稱
self.jump.setMaximumSize(QtCore.QSize(100, 30)) # 設置按鈕大小
self.Layout.addWidget(self.user)
self.Layout.addWidget(self.pwd)
self.Layout.addWidget(self.jump)
self.jump.clicked.connect(self.back_to_login) # 將信號連接到槽
self.text=''
def back_to_login(self):#跳回登錄界面
self.text=self.user.text()+'::'+self.pwd.text()
self.accept()
class Close_Windows(QtWidgets.QDialog):
"""對QDialog類重寫,實現一些功能"""
def closeEvent(self, event):
reply = QtWidgets.QMessageBox.question(self,
'退出界面',
"是否要退出?",
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
event.accept()
else:
event.ignore()
class MainUi(QMainWindow,Close_Windows): # 建立第二個窗口的類,此窗口還繼承重寫的界面關閉類
def __init__(self):
super(MainUi, self).__init__()
self.resize(500, 350)
self.setWindowTitle('登陸後界面') # 設置第二個窗口標題
self.buttonwidget = QtWidgets.QWidget()
self.buttonLayout = QtWidgets.QVBoxLayout(self.buttonwidget)
self.setCentralWidget(self.buttonwidget)
self.jump = QPushButton('跳回登錄界面', self) # 設置按鈕和按鈕名稱
self.jump.setMaximumSize(QtCore.QSize(100, 30)) # 設置按鈕大小
self.register = QPushButton('跳到註冊界面', self)
self.register.setMaximumSize(QtCore.QSize(100, 30))
self.buttonLayout.addWidget(self.jump)
self.buttonLayout.addWidget(self.register)
self.jump.clicked.connect(self.back_to_login) # 將信號連接到槽
self.register.clicked.connect(self.back_to_register)
def back_to_login(self):#跳回登錄界面
self.hide() # 隱藏此窗口
self.Login = Login_UI()
self.Login.show()
def back_to_register(self):#跳到註冊界面填寫完信息後回登錄界面
register = Register()
if register.exec_():
self.back_to_login()
self.Login.user.setText(register.text.split('::')[0])
self.Login.pwd.setText(register.text.split('::')[1])
def main():
app = QApplication(sys.argv)
w = Login_UI()
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
運行效果如下: