PyQT5介绍及基本使用

王江
创建于03-20
阅读 3418
收藏TA

需扫码在手机上打开
文章后点击更新提醒

PyQt5 

1. PyQt5的下载与安装


 
1.1 PyQt5介绍 

Qt(官方发音 [kju:t])是一个跨平台的C++开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序


 

Qt 是纯 C++ 开发的,正常情况下需要先学习C语言、然后在学习C++然后才能使用Qt开发带界面的程序


 

多亏了开源社区使得Qt 还可以用Python、Ruby、Perl 等脚本语言进行开发。


 

Qt 支持的操作系统有很多,例如通用操作系统 Windows、Linux、Unix,智能手机系统Android、iOS, 嵌入式系统等等。可以说是跨平台的


 

QT官网:https://doc.qt.io/qt-5/index.html


 

PyQt的开发者是英国的“Riverbank Computing”公司。它提供了GPL(简单的说,以GPL协议发布到网上的素材,你可以使用,也可以更改,但是经过你更改然后再次发布的素材必须也遵守GPL协议,主要要求是必须开源,而且不能删减原作者的声明信息等)与商业协议两种授权方式,因此它可以免费地用于自由软件的开发。


 

PyQt可以运行于Microsoft Windows、Mac OS X、Linux以及Unix的多数变种上


 

PyQt是Python语言的GUI(Graphical User Interface,简称 GUI,又称图形用户接口)编程解决方案之一


 

可以用来代替Python内置的Tkinter。其它替代者还有PyGTK、wxPython等,与Qt一样,PyQt是一个自由软件


 

文档相关地址:https://www.riverbankcomputing.com/software/pyqt/


 

比较不错的参考资料:https://wiki.python.org/moin/PyQt/Tutorials


 
 

Qt (C++ 语言 GUI )


  

PyQt = Python + Qt技术


  

Tkinter


 

Python官方采用的标准库,优点是作为Python标准库、稳定、发布程序较小,缺点是控件相对较少。


  

wxPython


 

基于wxWidgets的Python库,优点是控件比较丰富,缺点是稳定性相对差点、文档少、用户少。


  

PySide2、PyQt5


 

基于Qt 的Python库,优点是控件比较丰富、跨平台体验好、文档完善、用户多。


 

缺点是 库比较大,发布出来的程序比较大。


 

PyQt5 的开发者是英国的“Riverbank Computing”公司 , 而 PySide2 则是 qt 针对python语言提供的专门


  
1.2 windows PyQt5的安装 
执行命令,允许创建虚拟环境 
pip install virtualenv
pip install virtualenvwrapper-win
 
创建新的虚拟环境 
mkvirtualenv -p python3 py3-qt --no-download
 
安装pyqt5(命令行) 
workon py3-qt  
pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple
 


版本测试

from PyQt5 import QtWidgets


from PyQt5.QtCore import *


print(QT_VERSION_STR)


pip加速国内镜像
阿里云 https://mirrors.aliyun.com/pypi/simple/

中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/

豆瓣(douban) https://pypi.douban.com/simple/

清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/

中国科学技术大学 https://pypi.mirrors.ustc.edu.cn/simple/


2.PyQt5基本UI


 
2.1 第一个PyQt程序 
import sys

from PyQt5.QtWidgets import QApplication, QWidget 

if __name__ == '__main__':
    

    app = QApplication(sys.argv)
    
    w = QWidget()

    
    w.setWindowTitle("第一个PyQt")

    
    w.show()

    
    app.exec()

 


2.3 模块介绍 

PyQt中有非常多的功能模块,开发中最常用的功能模块主要有三个:


 
QtCore:包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用QtGui:包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类QtWidgets:包含了一些列创建桌面应用的UI元素 

可以参考PyQt官网的所有模块,地址:https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html#ref-module-index


 

C++具体实现的API文档,地址:https://doc.qt.io/qt-5/qtwidgets-module.html


 

用到什么功能就它相关的api或者别人分享的使用心得,这是学习最快的方式


 

3.基本UI


 

窗口内的所有控件,若想在窗口中显示,都需要表示它的父亲是谁,而不能直接使用 show 函数显示


 
3.1 按钮QPushButton 
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    
    w.setWindowTitle("第一个PyQt程序")

    
    btn = QPush("按钮")

    
    btn.setParent(w)

    
    w.show()

    
    app.exec()

 


3.2 文本QLabel 

纯文本控件名称为  QLabel , 位于 PyQt5.QtWidgets 里面


 

纯文本控件仅仅作为标识显示而已,类似输入内容前的一段标签提示(账号 、密码)


 
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel
if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    
    w.setWindowTitle("第一个PyQt")

    
    
    
    

    
    label = QLabel("账号: ", w)

    
    label.setGeometry(20, 20, 30, 30)

    
    w.show()

    
    app.exec()

 


import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    
    w.setWindowTitle("第一个PyQt")

    
    
    
    

    
    label = QLabel("账号: ", w)

    
    label.setGeometry(20, 20, 30, 30)

    
    w.show()

    
    app.exec()



3.3 输入框 
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    
    w.setWindowTitle("第一个PyQt")

    
    label = QLabel("账号", w)
    label.setGeometry(20, 20, 30, 20)

    
    edit = QLineEdit(w)
    edit.setPlaceholderText("请输入账号")
    edit.setGeometry(55, 20, 200, 20)

    
    btn = QPush("注册", w)
    
    btn.setGeometry(50, 80, 70, 30)

    
    w.show()

    
    app.exec()

 
3.4 调整窗口大小 
resize 
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    
    w.setWindowTitle("第一个PyQt5程序")

    
    w.resize(500,500)
    
    label = QLabel("账号", w)
    
    label.setGeometry(20, 20, 30, 20)
    
    edit = QLineEdit(w)
    edit.setPlaceholderText("请输入账号")
    edit.setGeometry(55, 20, 200, 20)
    
    btn = QPush("注册", w)
    btn.setGeometry(50, 80, 70, 30)
    
    w.show()
    
    app.exec()

 
3.5 调整窗口显示屏幕中间 
move:移动屏幕 
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit,QDesktopWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    
    w.setWindowTitle("第一个PyQt5程序")

    
    w.resize(500,500)

    
    

    
    center = QDesktopWidget().availableGeometry().center()
    print("center:",center)
    x = center.x()
    y = center.y()
    
    w.move(x//2,y//2)
    

    print(w.frameSize())
    print(w.frameGeometry())
    print(w.frameGeometry().getRect())

    
    old_x,old_y,width,height = w.frameGeometry().getRect()
    w.move(x-width//2,y-height//2)


    label = QLabel("账号", w)
    
    label.setGeometry(20, 20, 30, 20)
    
    edit = QLineEdit(w)
    edit.setPlaceholderText("请输入账号")
    edit.setGeometry(55, 20, 200, 20)
    
    btn = QPush("注册", w)
    btn.setGeometry(50, 80, 70, 30)
    
    w.show()
    
    app.exec()

 


3.6 设置窗口icon 

可下载icon网址


 
import sys

from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)

    
    w = QWidget()
    
    w.setWindowTitle("看看我图标帅吗")
    
    w.setWindowIcon(QIcon('test.jpg'))
    
    w.show()

    app.exec()

 


4.布局


 

在Qt里面布局分为四个大类 :


 
QBoxLayoutQGridLayoutQFormLayoutQStackedLayout 
4.1 QBoxLayout 

直译为:盒子布局


 

一般使用它的两个子类QHBoxLayout 和 QVBoxLayout 负责水平和垂直布局


 
4.1.1 垂直布局 
import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QPushButton, QGroupBox, QMainWindow
from PyQt5.QtCore import Qt


class My(QWidget):
    def __init__(self):
        
        super().__init__()
        
        self.resize(300, 300)
        
        self.setWindowTitle("垂直布局")
        
        layout = QVBoxLayout()

        
        

        
        layout.addStretch(1)
        
        btn1 = QPush("按钮1")
        
        
        layout.addWidget(btn1)

        layout.addStretch(1)

        
        btn2 = QPush("按钮2")
        
        layout.addWidget(btn2)

        layout.addStretch(1)

        
        btn3 = QPush("按钮3")
        
        layout.addWidget(btn3)

        layout.addStretch(2)

        btn4 = QPush("按钮4")
        
        layout.addWidget(btn4)

        layout.addStretch(2)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    w = My()
    w.show()
    app.exec()

 


4.1.2 水平布局 
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QHBoxLayout, QRadioButton


class My(QWidget):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        
        container = QVBoxLayout()
        
        
        hobby_box = QGroupBox("爱好")
        
        v_layout = QVBoxLayout()
        btn1 = QRadio("抽烟")
        btn2 = QRadio("喝酒")
        btn3 = QRadio("烫头")
        
        v_layout.addWidget(btn1)
        v_layout.addWidget(btn2)
        v_layout.addWidget(btn3)
        
        hobby_box.setLayout(v_layout)

        
        
        gender_box = QGroupBox("性别")
        
        h_layout = QHBoxLayout()
        
        btn4 = QRadio("男")
        btn5 = QRadio("女")
        
        h_layout.addWidget(btn4)
        h_layout.addWidget(btn5)
        
        gender_box.setLayout(h_layout)

        
        container.addWidget(hobby_box)
        
        container.addWidget(gender_box)


        
        music_box = QGroupBox("音乐")
        m_layout = QHBoxLayout()

        btn6 = QRadio("古风")
        btn7 = QRadio("流行")

        m_layout.addWidget(btn6)
        m_layout.addWidget(btn7)

        music_box.setLayout(m_layout)


        container.addWidget(music_box)




        
        self.setLayout(container)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = My()
    w.show()

    app.exec()

 


4.2 QGridLayout 
网格布局 
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLineEdit, QGridLayout


class My(QWidget):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("计算器")
        
        data = {
            0: ["7", "8", "9", "+", "("],
            1: ["4", "5", "6", "-", ")"],
            2: ["1", "2", "3", "*", "<-"],
            3: ["0", ".", "=", "/", "C"]
        }
        
        layout = QVBoxLayout()
        
        edit = QLineEdit()
        edit.setPlaceholderText("请输入内容")
        
        layout.addWidget(edit)
        
        grid = QGridLayout()
        
        for line_number, line_data in data.items():
            
            for col_number, number in enumerate(line_data):
                
                btn = QPush(number)
                
                grid.addWidget(btn, line_number, col_number)

        
        layout.addLayout(grid)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = My()
    w.show()

    app.exec()



4.3 QFormLayout 

一般适用于提交数据form表单。比如: 登录,注册类似的场景


 
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QVBoxLayout, QFormLayout, QLineEdit, QPushButton, QApplication, QWidget


class My(QWidget):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        
        
        
        self.setFixedSize(300, 150)

        
        container = QVBoxLayout()

        
        form_layout = QFormLayout()

        
        edit = QLineEdit()
        edit.setPlaceholderText("请输入账号")
        form_layout.addRow("账号:", edit)

        
        edit2 = QLineEdit()
        edit2.setPlaceholderText("请输入密码")
        form_layout.addRow("密码:", edit2)

        
        container.addLayout(form_layout)

        
        login_btn = QPush("登录")
        login_btn.setFixedSize(100, 30)

        
        container.addWidget(login_btn, alignment=Qt.AlignRight)

        
        self.setLayout(container)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = My()
    w.show()

    app.exec()

 


4.4 抽屉布局 

提供了多页面切换的布局,一次只能看到一个界面。 抽屉布局


 
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QStackedLayout, QLabel


class Window1(QWidget):
    def __init__(self):
        super().__init__()
        QLabel("我辈岂是蓬蒿人", self)
        self.setStyleSheet("background-color:green;")


class Window2(QWidget):
    def __init__(self):
        super().__init__()
        QLabel("人生得以须尽欢", self)
        self.setStyleSheet("background-color:red;")


class My(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.create_stacked_layout()
        self.init_ui()

    def create_stacked_layout(self):
        
        self.stacked_layout = QStackedLayout()
        
        win1 = Window1()
        win2 = Window2()
        
        self.stacked_layout.addWidget(win1)
        self.stacked_layout.addWidget(win2)

    def init_ui(self):
        
        self.setFixedSize(300, 270)

        
        container = QVBoxLayout()

        
        widget = QWidget()
        widget.setLayout(self.stacked_layout)
        widget.setStyleSheet("background-color:grey;")

        
        btn_press1 = QPush("抽屉1")
        btn_press2 = QPush("抽屉2")
        
        btn_press1.clicked.connect(self.btn_press1_clicked)
        btn_press2.clicked.connect(self.btn_press2_clicked)

        
        container.addWidget(widget)
        container.addWidget(btn_press1)
        container.addWidget(btn_press2)

        
        self.setLayout(container)

    def btn_press1_clicked(self):
        
        self.stacked_layout.setCurrentIndex(0)

    def btn_press2_clicked(self):
        
        self.stacked_layout.setCurrentIndex(1)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    win = My()
    win.show()

    app.exec()

 


5. 窗口


 
5.1 分类 

在Qt中,生成窗口有三种方式: QWidget | QMainWindow | QDialog


 
QWidget 

控件和窗口的父类 ,自由度高(什么都东西都没有),没有划分菜单、工具栏、状态栏、主窗口 等区域


 
QMainWindow 

是 QWidget的子类,包含菜单栏,工具栏,状态栏,标题栏等,中间部分则为主窗口区域


 
QDialog 

对话框窗口的基类


 
5.2 QWidget 
import  sys

from PyQt5.QtWidgets import QWidget, QLabel , QApplication

class mywnd(QWidget):

    def __init__(self):
        super(mywnd, self).__init__()
        self.initUI()

    def initUI(self):
        label = QLabel("这是文字~~" )
        label.setStyleSheet("font-size:30px;color:red")
        label.setParent(self)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = mywnd()

    
    w.setWindowTitle("qwidget")

    
    w.show()

    
    app.exec()
 


5.2 QMainWindow 
import sys

from PyQt5.QtWidgets import QMainWindow, QLabel, QApplication


class My(QMainWindow):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        label = QLabel("这是文字~~")
        label.setStyleSheet("font-size:30px;color:red")

        
        menu = self.menuBar()
        
        
        menu.setNativeMenuBar(False)

        file_menu = menu.addMenu("文件")
        file_menu.addAction("新建")
        file_menu.addAction("打开")
        file_menu.addAction("保存")

        edit_menu = menu.addMenu("编辑")
        edit_menu.addAction("复制")
        edit_menu.addAction("粘贴")
        edit_menu.addAction("剪切")

        
        self.setCentralWidget(label)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = My()
    
    w.setWindowTitle("我是窗口标题....")
    
    w.show()

    
    app.exec()

 


5.3 QDialog 
import sys

from PyQt5.QtWidgets import QDialog, QPushButton, QApplication


class MyDialog(QDialog):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        ok_btn = QPush("确定", self)
        ok_btn.setGeometry(50, 50, 100, 30)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyDialog()
    
    w.setWindowTitle("对话框")
    
    w.show()

    
    app.exec()

 


6. 信号与槽


 
6.1 信号与槽介绍 

一、说明

 信号和槽是 Qt的核心内容


 
信号(signal)

 其实就是事件(按钮点击 、内容发生改变 、窗口的关闭事件) 或者是 状态 (check选中了, togglebutton 切换。) 

当程序触发了某种状态或者发生了某种事件(比如:按钮被点击了, 内容改变等等),那么即可发射出来一个信号。


 
 

槽( slot)

 若想捕获这个信号,然后执行相应的逻辑代码,那么就需要使用到槽 , 槽实际上是一个函数, 当信号发射出来后,会执行与之绑定的槽函数


  

将信号与槽链接

 为了能够实现,当点击某个按钮时执行某个逻辑,需要把具体的信号和具体的槽函数绑定到一起.


  

操作大体流程如下


 
对象.信号.connect(槽函数)
 


当出现了某一种信号(某一种事件)的时候,我们需要执行一段代码(用函数来包装这份代码。)

解决办法


 
信号和槽
 
6.2 案例 

功能:接收信号


 
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton


class My(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        
        self.resize(500, 300)
        
        btn = QPush("点我点我", self)
        
        btn.setGeometry(200, 200, 100, 30)
        
        
        btn.clicked.connect(self.click_my_btn)

    def click_my_btn(self, arg):
        
        
        print("点击按钮啦~", arg)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = My()
    w.show()

    app.exec()

 


6.3 自定义信号 

除了接收Qt自带的信号之外,我们也可以自行定义信号,在合适的时机,自行发射信号


 

自定义信号需要使用到 pyqtSignal来声明信号 ,并且需要在类中的函数之外声明


 

如果会自定义信号,那么信号和槽基本上也就掌握了。否则永远只会接收别人发射出的信号


 
import sys
import time

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class My(QWidget):
    
    my_signal = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.init_ui()
        self.msg_history = list()  

    def init_ui(self):
        self.resize(500, 200)

        
        container = QVBoxLayout()

        
        self.msg = QLabel("")
        self.msg.resize(440, 15)
        
        self.msg.setWordWrap(True)  
        self.msg.setAlignment(Qt.AlignCenter)  
        self.msg.setStyleSheet("background-color: yellow; color: red;")

        
        scroll = QScrollArea()
        scroll.setWidget(self.msg)

        
        v_layout = QVBoxLayout()
        v_layout.addWidget(scroll)

        
        h_layout = QHBoxLayout()
        btn = QPush("开始检测", self)
        
        btn.clicked.connect(self.check)
        h_layout.addStretch(1)  
        h_layout.addWidget(btn)
        h_layout.addStretch(1)

        
        container.addLayout(v_layout)
        container.addLayout(h_layout)

        
        self.setLayout(container)

        
        self.my_signal.connect(self.my_slot)

    def my_slot(self, msg):
        
        print(msg)
        self.msg_history.(msg)
        self.msg.setText("
".join(self.msg_history))
        self.msg.resize(440, self.msg.frameSize().height() + 15)
        self.msg.repaint()  

    def check(self):
        for i, ip in enumerate(["192.168.1.%d" % x for x in range(1, 255)]):
            msg = "模拟,正在检查 %s 上的漏洞...." % ip
            
            if i % 5 == 3:
                
                self.my_signal.emit(msg + "【发现漏洞】")
            time.sleep(0.01)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = My()
    w.show()

    app.exec()

 


7.Qt Designer


 
7.1 介绍 

纯靠代码来编写界面,效率属实是有点底,今天我们用另外一个辅助设计图形化的软件 QT Designer


 
7.2 下载 

Mac版本:[http://download.codetutor.top/software/Mac/Qt%20Designer.dmg](http://download.codetutor.top/software/Mac/Qt Designer.dmg)


 

Windows版本:[http://download.codetutor.top/software/win/Qt%20Designer%20Setup.exe](http://download.codetutor.top/software/win/Qt Designer Setup.exe)


 
7.3 安装&运行 

安装过程很简单,按照正常软件安装即可,安装后的图片如下图:


 


但Mac平台用户要注意,运行时会出现如下图问题


 


解决办法:在“应用程序”文件夹,按住control键然后运行。只需要这种方式运行第一次即可,以后运行就像普通软件一样打开


 


7.4 使用QT Designer 

Mac运行之后的效果如下:


 


7.5 使用流程 

1.创建一个基于QWidget的界面


 


2.此时会创建一个新的窗口,如下效果


 


3.拖动想要的控件


 


4.选中控件,看属性


 


5.修改属性


 


6.如果没有看到preperty等窗口怎么办?看下图


 


7.信号与槽(没有没有看到Singal/Slot Editor请按照上一步操作进行显示)


 


8.预览效果


 


9.保存


 


10.python代码使用test.ui文件


 

若要加载ui文件,则需要导入 uic 模块 , 它位于PyQt5 中


 
"""
动态加载ui文件
"""

import sys

from PyQt5.QtWidgets import QApplication
from PyQt5 import uic

if __name__ == '__main__':
    app = QApplication(sys.argv)

    ui = uic.loadUi("./test.ui")
    
    ui.show()

    app.exec()

 

查看原文 原文转载自blog.csdn.net,著作权归作者所有
阅读 3418
文章由 美篇工作版 编辑制作
投诉