PyQt5学习笔记

PyQt5

第一阶段:

QT-Designer的使用

第二阶段:

代码的编写,API函数的熟悉

p27 屏幕坐标系

屏幕左上角为坐标原点

import sys
from PyQt5.QtWidgets import QWidget,QApplication,QPushButton
#函数作用:展示控件坐标
def show_geometry():
    print("方法1")
    print(widget.x())   #窗口左上角坐标(含有边框-标题栏的坐标)
    print(widget.y())
    print(widget.width())   #尺寸只含有工作区
    print(widget.height())
    """运行结果:
    方法1
        200
        400
        600
        600
    """
    #方法2
    print("方法2")
    print(widget.geometry().x())   #窗口左上角坐标(不含有边框-标题栏的坐标)
    print(widget.geometry().y())
    print(widget.geometry().width())   #尺寸只含有工作区
    print(widget.geometry().height())
    """运行结果:
    方法2
        211
        445
        600
        600
    """
    print("方法3")
    print(widget.frameGeometry().x())  # 窗口左上角坐标(含有边框-标题栏的坐标)
    print(widget.frameGeometry().y())
    print(widget.frameGeometry().width())  # 尺寸包含有非工作区
    print(widget.frameGeometry().height())
    """运行结果:
    方法3
        200
        400
        622
        656
    """
#创建应用
app=QApplication(sys.argv)
#创建窗口
widget=QWidget()
#添加按钮
button=QPushButton(widget)
#给按钮添加文字
button.setText("按钮")
#设置按钮大小
button.resize(200,200)
#移动按钮
button.move(24,52)
#按钮事件
button.clicked.connect(show_geometry)
#设置窗口大小
widget.resize(600,600)
#移动窗口
widget.move(200,400)
#设置窗口名称
widget.setWindowTitle("屏幕坐标系")
#展示窗口
widget.show()
#程序退出
sys.exit(app.exec_())

p28 设置窗口和应用程序图标

import sys
from PyQt5.QtWidgets import QMainWindow,QApplication
from PyQt5.QtGui import QIcon
class window(QMainWindow):
    def __init__(self):
        super(window, self).__init__()
    def init_ui(self):
        #设置窗口坐标以及尺寸
        self.setGeometry(300,300,400,400) #(x,y,w,h)
        #设置窗口标题
        self.setWindowTitle("设置窗口图标")
        #设置窗口图标
        self.setWindowIcon(QIcon("./1.jpg"))
if __name__=="__main__":
    app=QApplication(sys.argv)
    main=window()
    main.init_ui()
    main.show()
    sys.exit(app.exec_())

运行结果:

p29 为控件添加提示消息

效果:将鼠标放置在控件上,会短暂的显示提示消息

import sys
from PyQt5.QtWidgets import QMainWindow,QApplication,QPushButton
#设置提示信息需引入的类
from PyQt5.QtWidgets import QToolTip
#引入字体相关
from PyQt5.QtGui import QFont
class window(QMainWindow):
    def __init__(self):
        super(window, self).__init__()
        self.initGui()
    def initGui(self):
        #设置字体 字体类型可以在QT-Designer中查找
        QToolTip.setFont(QFont("Calibri Light",12))
        #为窗体添加提示信息
        self.setToolTip("今天是<b>星期四</b>")
        self.setGeometry(200,200,400,400)
        self.setWindowTitle("设置控件提示信息")
        #为按钮添加提示信息
        self.button=QPushButton(self)
        self.button.setText("按钮")
        self.button.setGeometry(250,250,100,100)
        self.button.setToolTip("<b> 这是一个按钮</b>")
if __name__=="__main__":
    app = QApplication(sys.argv)
    main = window()
    main.show()
    sys.exit(app.exec_())

运行结果:

p30 QLabel控件的基本使用方法

"""QLabel常用操作:
setAlignment() 设置文本的对齐方式
setIndent() 设置文本缩进
setBuddy() 设置伙伴关系
setText() 设置文本内容
selectedText() 返回所选择的字符
setWordWrap() 设置是否允许换行
在QT-Designer中的属性编辑器中可以查看

Qlabel 常用的信号或事件:
1.当鼠标滑过Qlabel控件时触发:linkHovered
2.当鼠标点击QLabel控件时触发:linkActivated
"""
import sys
from PyQt5.QtWidgets import  QVBoxLayout,QMainWindow,QApplication,QPushButton,QWidget,QLabel
from PyQt5.QtGui import QPalette,QPixmap #显示背景与图片所用模块
from PyQt5.QtCore import Qt

class LabelDemo(QWidget):
    def __init__(self):
        super(LabelDemo, self).__init__()
        self.initGui()
    def initGui(self):
        # 放置四个Label控件
        label1 = QLabel(self)
        label2 = QLabel(self)
        label3 = QLabel(self)
        label4 = QLabel(self)
        #label1 添加文字
        label1.setText("<font color=yellow>这是一个文本标签.</font>")
        #添加背景
        label1.setAutoFillBackground(True)
        #设置调色板与背景属性
        palette=QPalette()
        palette.setColor(QPalette.Window,Qt.black)
        label1.setPalette(palette)
        #居中
        label1.setAlignment(Qt.AlignCenter)
        #label2 显示超链接
        label2.setText("<a href='#'>欢迎使用Python Gui程序</a>")
        #label3 显示图片
        #居中
        label3.setAlignment(Qt.AlignCenter)
        #显示提示消息
        label3.setToolTip('这是一个图片标签')
        # 显示图片
        label3.setPixmap(QPixmap("./11.jpg"))
        # label4 显示超链接
        label4.setText("<a href='https://www.baidu.com'>百度网址</a>")
        #让其右对齐
        label4.setAlignment(Qt.AlignRight)
        #设置提示消息
        label4.setToolTip("这是百度的超链接")
        #由于label4 既含有超链接,有含有触发事件,而这只能为1
        label4.setOpenExternalLinks(True) #超链接有效
        # 将控件进行垂直布局
        vbox=QVBoxLayout()
        vbox.addWidget(label1)
        vbox.addWidget(label2)
        vbox.addWidget(label3)
        vbox.addWidget(label4)
        #绑定事件
        label2.linkHovered.connect(self.linkHovered)
        label4.linkActivated.connect(self.linkClicked)
        #设置主窗口布局与标题
        self.setLayout(vbox)
        # self.setGeometry(400,400,600,600)
        self.setWindowTitle("QLabel控件的基本使用")
    #定义信号与槽
    def linkHovered(self):
        print("鼠标滑过标签2时触发事件")
    def linkClicked(self):
        print("当鼠标单击Label4时出发事件")

if __name__=="__main__":
    app=QApplication(sys.argv)
    main=LabelDemo()
    main.show()
    sys.exit(app.exec_())

运行效果:

在这里插入图片描述

p31 QLabel与伙伴控件



    def initUI(self):
        #设置主屏幕标题
        self.setWindowTitle('QLabel与伙伴控件')
        #创建控件
        nameLabel = QLabel('&Name',self) #&Name热键,可以通过按‘alt'+N快速跳转
        nameLineEdit = QLineEdit(self)
        # 设置伙伴控件
        nameLabel.setBuddy(nameLineEdit)

        passwordLabel = QLabel('&Password',self)
        passwordLineEdit = QLineEdit(self)
        # 设置伙伴控件
        passwordLabel.setBuddy(passwordLineEdit)

        btnOK = QPushButton('&OK')
        btnCancel = QPushButton('&Cancel')

        #布局:使用栅格布局
        mainLayout = QGridLayout(self)
        mainLayout.addWidget(nameLabel,0,0) #第一行第一列,默认占用一行一列
        mainLayout.addWidget(nameLineEdit,0,1,1,2) #第一行第二列,且占用一行两列

        mainLayout.addWidget(passwordLabel,1,0)
        mainLayout.addWidget(passwordLineEdit,1,1,1,2)

        mainLayout.addWidget(btnOK,2,1)
        mainLayout.addWidget(btnCancel,2,2)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QLabelBuddy()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p32 QLineEdit控件与回显模式

'''

QLineEdit控件与回显模式

基本功能:输入单行的文本

EchoMode(回显模式)

4种回显模式

1. Normal    #输入什么显示什么
2. NoEcho    #无论输入什么,什么都不显示
3. Password   #将输入的内容隐藏
4. PasswordEchoOnEdit #输入显示,但将鼠标移动至其他输入栏时,与passw效果一致


Mac : Command    Windows:Control
'''
from PyQt5.QtWidgets import *
import sys

class QLineEditEchoMode(QWidget) :
    def __init__(self):
        super(QLineEditEchoMode,self).__init__()
        self.initUI()

    def initUI(self):
        #设置窗口标题
        self.setWindowTitle('文本输入框的回显模式')
        #设置布局 使用表单布局
        formLayout = QFormLayout()
        #添加四个QLineEdit控件
        normalLineEdit = QLineEdit()
        noEchoLineEdit = QLineEdit()
        passwordLineEdit = QLineEdit()
        passwordEchoOnEditLineEdit = QLineEdit()
        #向布局中添加控件
        """使用格式:
        addRow(名称,控件对象)
        """
        formLayout.addRow("Normal",normalLineEdit)
        formLayout.addRow("NoEcho", noEchoLineEdit)
        formLayout.addRow("Password",passwordLineEdit)
        formLayout.addRow("PasswordEchoOnEdit",passwordEchoOnEditLineEdit)

        # placeholdertext
        #设置提示消息
        normalLineEdit.setPlaceholderText("Normal")
        noEchoLineEdit.setPlaceholderText("NoEcho")
        passwordLineEdit.setPlaceholderText("Password")
        passwordEchoOnEditLineEdit.setPlaceholderText("PasswordEchoOnEdit")
        #设置回显模式
        normalLineEdit.setEchoMode(QLineEdit.Normal)
        noEchoLineEdit.setEchoMode(QLineEdit.NoEcho)
        passwordLineEdit.setEchoMode(QLineEdit.Password)
        passwordEchoOnEditLineEdit.setEchoMode(QLineEdit.PasswordEchoOnEdit)

        self.setLayout(formLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QLineEditEchoMode()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p33 限制QLineEdit控件的输入

'''

现在QLineEdit控件的输入(校验器)

如限制只能输入整数、浮点数或满足一定条件的字符串


'''

from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIntValidator,QDoubleValidator, QRegExpValidator
from PyQt5.QtCore import QRegExp
import sys

class QLineEditValidator(QWidget):
    def __init__(self):
        super(QLineEditValidator,self).__init__()
        self.initUI()

    def initUI(self):
        #设置屏幕标题
        self.setWindowTitle('校验器')

        # 创建表单布局
        formLayout = QFormLayout()
        #创建三个控件
        intLineEdit = QLineEdit()
        doubleLineEdit = QLineEdit()
        validatorLineEdit = QLineEdit()
        #将控件加入布局
        formLayout.addRow('整数类型', intLineEdit)
        formLayout.addRow('浮点类型', doubleLineEdit)
        formLayout.addRow('数字和字母',validatorLineEdit)
        #设置提示信息
        intLineEdit.setPlaceholderText('整型')
        doubleLineEdit.setPlaceholderText('浮点型')
        validatorLineEdit.setPlaceholderText('字母和数字')

        # 整数校验器 [1,99]
        intValidator = QIntValidator(self)
        intValidator.setRange(1,99)

        # 浮点校验器 [-360,360],精度:小数点后2位
        doubleValidator = QDoubleValidator(self)
        doubleValidator.setRange(-360,360)
        doubleValidator.setNotation(QDoubleValidator.StandardNotation)
        # 设置精度,小数点2位
        doubleValidator.setDecimals(2)

        # 字符和数字
        reg = QRegExp('[a-zA-Z0-9]+$')
        validator = QRegExpValidator(self)
        validator.setRegExp(reg)

        # 设置校验器

        intLineEdit.setValidator(intValidator)
        doubleLineEdit.setValidator(doubleValidator)
        validatorLineEdit.setValidator(validator)

        self.setLayout(formLayout)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QLineEditValidator()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p34 使用掩码限制QLineEdit控件的输入

'''

用掩码限制QLineEdit控件的输入

A    ASCII字母字符是必须输入的(A-Z、a-z)
a    ASCII字母字符是允许输入的,但不是必需的(A-Z、a-z)
N    ASCII字母字符是必须输入的(A-Z、a-z、0-9)
n    ASII字母字符是允许输入的,但不是必需的(A-Z、a-z、0-9)
X    任何字符都是必须输入的
x    任何字符都是允许输入的,但不是必需的
9    ASCII数字字符是必须输入的(0-9)
0    ASCII数字字符是允许输入的,但不是必需的(0-9)
D    ASCII数字字符是必须输入的(1-9)
d    ASCII数字字符是允许输入的,但不是必需的(1-9)
#    ASCI数字字符或加减符号是允许输入的,但不是必需的
H    十六进制格式字符是必须输入的(A-F、a-f、0-9)
h    十六进制格式字符是允许输入的,但不是必需的(A-F、a-f、0-9)
B    二进制格式字符是必须输入的(0,1)
b    二进制格式字符是允许输入的,但不是必需的(0,1)
>    所有的字母字符都大写
<    所有的字母字符都小写
!    关闭大小写转换
\    使用"\"转义上面列出的字符
'''

from PyQt5.QtWidgets import *
import sys

class QLineEditMask(QWidget) :
    def __init__(self):
        super(QLineEditMask,self).__init__()
        self.initUI()

    def initUI(self):
        #给窗口设置标题
        self.setWindowTitle('用掩码限制QLineEdit控件的输入')
        #设置表单布局
        formLayout = QFormLayout()
        #创建三个控件
        ipLineEdit = QLineEdit()
        macLineEdit = QLineEdit()
        dateLineEdit = QLineEdit()
        licenseLineEdit = QLineEdit()
        # 192.168.21.45
        #使用格式:
        """
        setInputMask(输入格式,符号)
        输入格式按照输入位数与对应的掩码含义编写
        符号代替相关的位,没有输入或输入位数不足,用符号代替
        """
        ipLineEdit.setInputMask('000.000.000.000;_')
        macLineEdit.setInputMask('HH:HH:HH:HH:HH:HH;_')
        dateLineEdit.setInputMask('0000-00-00')
        licenseLineEdit.setInputMask('>AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;#')

        formLayout.addRow('数字掩码',ipLineEdit)
        formLayout.addRow('Mac掩码', macLineEdit)
        formLayout.addRow('日期掩码',dateLineEdit)
        formLayout.addRow('许可证掩码',licenseLineEdit)

        self.setLayout(formLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QLineEditMask()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p35 QlineEdit控件综合案例

'''

QLineEdit综合案例

'''

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt
import sys

class QLineEditDemo(QWidget):
    def __init__(self):
        super(QLineEditDemo,self).__init__()
        self.initUI()

    def initUI(self):
        edit1 = QLineEdit()
        # 使用int校验器
        edit1.setValidator(QIntValidator())
        edit1.setMaxLength(4)  # 不超过9999,即输入最大长度为4
        #右对齐
        edit1.setAlignment(Qt.AlignRight)
        edit1.setFont(QFont('Arial',20))

        edit2 = QLineEdit()
        edit2.setValidator(QDoubleValidator(0.99,99.99,2)) #范围与精度
        #掩码
        edit3 = QLineEdit()
        edit3.setInputMask('99_9999_999999;#')

        edit4 = QLineEdit()
        edit4.textChanged.connect(self.textChanged) #文本变化时触发事件

        edit5 = QLineEdit()
        edit5.setEchoMode(QLineEdit.Password)
        edit5.editingFinished.connect(self.enterPress)  #输入完成出发事件

        edit6 = QLineEdit('Hello PyQt5')
        edit6.setReadOnly(True) #设置只读模式


        formLayout = QFormLayout()
        formLayout.addRow('整数校验',edit1)
        formLayout.addRow('浮点数校验',edit2)
        formLayout.addRow('Input Mask',edit3)
        formLayout.addRow('文本变化', edit4)
        formLayout.addRow('密码',edit5)
        formLayout.addRow('只读',edit6)
        self.setLayout(formLayout)
        self.setWindowTitle('QLineEdit综合案例')
    def textChanged(self,text):
        print('输入的内容:' + text)

    def enterPress(self):
        print('已输入值')
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QLineEditDemo()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p36 使用QTextEdit控件输入多行文本

'''

QTextEdit控件

'''

from PyQt5.QtWidgets import *
import sys

class QTextEditDemo(QWidget) :
    def __init__(self):
        super(QTextEditDemo,self).__init__()
        self.initUI()

    def initUI(self):
        #设置窗口标题
        self.setWindowTitle('QTextEdit控件演示')
        #调整窗口大小
        self.resize(300,320)
        #创建多行文本控件
        self.textEdit = QTextEdit()
        #设置四个按钮控件
        self.buttonText = QPushButton('显示文本')
        self.buttonHTML = QPushButton('显示HTML')

        self.buttonToText = QPushButton('获取文本')
        self.buttonToHTML = QPushButton('获取HTML')

        #进行垂直布局
        layout = QVBoxLayout()
        layout.addWidget(self.textEdit)
        layout.addWidget(self.buttonText)
        layout.addWidget(self.buttonToText)
        layout.addWidget(self.buttonHTML)
        layout.addWidget(self.buttonToHTML)

        self.setLayout(layout)
        #关联信号与槽
        self.buttonText.clicked.connect(self.onClick_ButtonText)
        self.buttonHTML.clicked.connect(self.onClick_ButtonHTML)

        self.buttonToText.clicked.connect(self.onClick_ButtonToText)
        self.buttonToHTML.clicked.connect(self.onClick_ButtonToHTML)

    def onClick_ButtonText(self):
        self.textEdit.setPlainText('Hello World,世界你好吗?')    #setPlainText()设置文本内容

    def onClick_ButtonToText(self):
        print(self.textEdit.toPlainText())          #获取文本内容

    def onClick_ButtonHTML(self):
        self.textEdit.setHtml('<font color="blue" size="5">Hello World</font>')     #setHtml()设置HTML类型内容
    def onClick_ButtonToHTML(self):
        print(self.textEdit.toHtml())       #获取内容

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QTextEditDemo()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

在这里插入图片描述

p37 按钮控件

'''

按钮控件(QPushButton)

QAbstractButton

QPushButton     #普通按钮
AToolButton
QRadioButton    #单选按钮
QCheckBox       #复选框


'''


import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class QPushButtonDemo(QDialog) :
    def __init__(self):
        super(QPushButtonDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('QPushButton Demo')

        layout = QVBoxLayout()

        self.button1 = QPushButton('第1个按钮')
        #setText()设置按钮上的文本
        self.button1.setText('First Button1')

        #以下两条语句使按钮具有check功能,第一未选中,再次点击即为选中,作用类似于开关
        self.button1.setCheckable(True)
        self.button1.toggle()

        self.button1.clicked.connect(self.buttonState)
        self.button1.clicked.connect(lambda :self.whichButton(self.button1))

        layout.addWidget(self.button1)
        # 在文本前面显示图像

        self.button2 = QPushButton('图像按钮')
        self.button2.setIcon(QIcon(QPixmap('./images/python.png')))
        self.button2.clicked.connect(lambda:self.whichButton(self.button2))
        layout.addWidget(self.button2)

        self.button3 = QPushButton('不可用的按钮')
        #通过setEnable使按钮不可用,即无法点击
        self.button3.setEnabled(False)
        layout.addWidget(self.button3)

        self.button4 = QPushButton('&MyButton') #设置热键
        #设置默认,如不按任何按钮,按回车键时默认为按下此按键
        self.button4.setDefault(True)
        self.button4.clicked.connect(lambda:self.whichButton(self.button4))
        layout.addWidget(self.button4)

        self.setLayout(layout)
        self.resize(400,300)

    def buttonState(self):
        #isChecked() 判断按钮是否被选中
        if self.button1.isChecked():
            print('按钮1已经被选中')
        else:
            print('按钮1未被选中')

    def whichButton(self,btn):
        #button.text():获取按钮上的文本
        print('被单击的按钮是<' + btn.text() + '>')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QPushButtonDemo()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p38单选按钮控件

'''

单选按钮控件(QRadioButton)

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class QRadioButtonDemo(QWidget):
    def __init__(self):
        super(QRadioButtonDemo,self).__init__()
        self.initUI()
    def initUI(self):
        #设置窗口标题
        self.setWindowTitle('QRadioButton')
        #采用水平布局
        layout = QHBoxLayout()
        self.button1 = QRadioButton('单选按钮1')
        #按钮1默认被选中
        self.button1.setChecked(True)

        #切换选中状态触发事件
        self.button1.toggled.connect(self.buttonState)
        layout.addWidget(self.button1)

        self.button2 = QRadioButton('单选按钮2')
        self.button2.toggled.connect(self.buttonState)
        layout.addWidget(self.button2)
        self.setLayout(layout)


    def buttonState(self):
        radioButton = self.sender()

        if radioButton.isChecked() == True:
            print('<' + radioButton.text() + '> 被选中')
        else:
            print('<' + radioButton.text() + '> 被取消选中状态')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QRadioButtonDemo()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p39 复选框控件

'''

复选框控件(QCheckBox)

3种状态

未选中:0

半选中:1

选中:2

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt

class QCheckBoxDemo(QWidget):
    def __init__(self):
        super(QCheckBoxDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('复选框控件演示')

        layout = QHBoxLayout()

        self.checkBox1 = QCheckBox('复选框控件1')
        #默认被选中
        self.checkBox1.setChecked(True)
        self.checkBox1.stateChanged.connect(lambda :self.checkboxState(self.checkBox1))
        layout.addWidget(self.checkBox1)

        self.checkBox2 = QCheckBox('复选框控件2')
        self.checkBox2.stateChanged.connect(lambda:self.checkboxState(self.checkBox2))
        layout.addWidget(self.checkBox2)

        self.checkBox3 = QCheckBox('半选中')
        self.checkBox3.stateChanged.connect(lambda:self.checkboxState(self.checkBox3))
        #设置半选中状态
        #起始默认为半选中状态
        self.checkBox3.setTristate(True)
        #设置具有半选中状态功能
        self.checkBox3.setCheckState(Qt.PartiallyChecked)
        layout.addWidget(self.checkBox3)

        self.setLayout(layout)

    def checkboxState(self,cb):
        check1Status = self.checkBox1.text() + ', isChecked=' + str(self.checkBox1.isChecked()) + ',checkState=' + str(self.checkBox1.checkState()) + '\n'
        check2Status = self.checkBox2.text() + ', isChecked=' + str(self.checkBox2.isChecked()) + ',checkState=' + str(self.checkBox2.checkState()) + '\n'
        check3Status = self.checkBox3.text() + ', isChecked=' + str(self.checkBox3.isChecked()) + ',checkState=' + str(self.checkBox3.checkState()) + '\n'
        print(check1Status + check2Status + check3Status)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QCheckBoxDemo()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p40 下拉列表控件

'''

下拉列表控件(QComboBox)

1. 如果将列表项添加到QComboBox控件中

2. 如何获取选中的列表项

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class QComboBoxDemo(QWidget):
    def __init__(self):
        super(QComboBoxDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('下拉列表控件演示')
        self.resize(300,100)

        layout = QVBoxLayout()

        self.label = QLabel('请选择编程语言')
        #添加复选框控件
        self.cb = QComboBox()
        #如果将列表项添加到QComboBox控件中,以列表形式传入,一次可添加多个
        self.cb.addItem('C++')
        self.cb.addItem('Python')
        self.cb.addItems(['Java','C#','Ruby'])

        #当前选择索引发生变化触发信号
        self.cb.currentIndexChanged.connect(self.selectionChange)

        layout.addWidget(self.label)
        layout.addWidget(self.cb)

        self.setLayout(layout)

    def selectionChange(self,i):
        #更改label上的文本
        self.label.setText(self.cb.currentText())
        self.label.adjustSize()

        for count in range(self.cb.count()):
            #可以根据索引获取列表项
            print('item' + str(count) + '=' + self.cb.itemText(count))
        #通过currentText() 获取当前被选中的表项
        print('current index',i,'selection changed', self.cb.currentText())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QComboBoxDemo()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p41 滑块控件

'''

滑块控件(QSlider)

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class QSliderDemo(QWidget):
    def __init__(self):
        super(QSliderDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('滑块控件演示')
        self.resize(300,700)

        layout = QVBoxLayout()
        self.label = QLabel('你好 PyQt5')
        self.label.setAlignment(Qt.AlignCenter)

        layout.addWidget(self.label)

        #水平滑块
        self.slider = QSlider(Qt.Horizontal)



        # 设置最小值
        self.slider.setMinimum(12)
        # 设置最大值
        self.slider.setMaximum(48)

        # 步长
        self.slider.setSingleStep(3)

        # 设置当前值
        self.slider.setValue(18)

        # 设置刻度的位置,刻度在下方
        self.slider.setTickPosition(QSlider.TicksBelow)
        # 设置刻度的间隔
        self.slider.setTickInterval(6)

        layout.addWidget(self.slider)
        #滑块值发生改变(即滑块滑动)触发事件
        self.slider.valueChanged.connect(self.valueChange)

        #水平滑块
        self.slider1 = QSlider(Qt.Vertical)
        layout.addWidget(self.slider1)
        # 设置最小值
        self.slider1.setMinimum(10)
        # 设置最大值
        self.slider1.setMaximum(60)

        # 步长
        self.slider1.setSingleStep(5)

        # 设置当前值
        self.slider1.setValue(30)

        # 设置刻度的位置,刻度在下方
        self.slider1.setTickPosition(QSlider.TicksLeft)
        # 设置刻度的间隔
        self.slider1.setTickInterval(2)
        self.slider1.valueChanged.connect(self.valueChange)
        self.setLayout(layout)

    def valueChange(self):
        #通过value属性获取滑块当前的值
        print('当前值:%s' % self.sender().value())
        size = self.sender().value()
        #通过滑块的值调整label上文本的字体大小
        self.label.setFont(QFont('Arial',size))
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QSliderDemo()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p42 计数器控件

'''

计数器控件(QSpinBox)



'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class QSpinBoxDemo(QWidget):
    def __init__(self):
        super(QSpinBoxDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('QSpinBox演示')
        self.resize(300,100)

        layout = QVBoxLayout()
        self.label = QLabel('当前值')
        #文本居中对其
        self.label.setAlignment(Qt.AlignCenter)

        layout.addWidget(self.label)

        self.sb = QSpinBox()
        #设置当前值
        self.sb.setValue(18)
        #设置可调数值范围
        self.sb.setRange(10,38)
        #单次增加步长
        self.sb.setSingleStep(3)
        layout.addWidget(self.sb)
        #计数器值改变触发信号
        self.sb.valueChanged.connect(self.valueChange)
        self.setLayout(layout)

    def valueChange(self):
        #调整label文本内容
        self.label.setText('当前值:' + str(self.sb.value()))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QSpinBoxDemo()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p43 使用QDialog显示通用对话框

'''

对话框:QDialog

QMessageBox  #显示提示消息
QColorDialog
QFileDialog
QFontDialog
QInputDialog	#显示输入消息

QMainWindow
QWidget
QDialog

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class QDialogDemo(QMainWindow):
    def __init__(self):
        super(QDialogDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('QDialog案例')
        self.resize(300,200)

        self.button = QPushButton(self)
        self.button.setText('弹出对话框')
        self.button.move(50,50)
        #通过按钮点击弹出一个新的对话框
        self.button.clicked.connect(self.showDialog)

    def showDialog(self):
        #新对话框中的布局
        dialog = QDialog() #普通对话框
        button = QPushButton('确定',dialog)
        button.clicked.connect(dialog.close) #关闭对话框
        button.move(50,50)
        dialog.setWindowTitle('对话框')
        #设置对话框模式状态,即当前对话框未关闭时,原主屏幕中任何控件都不可用
        dialog.setWindowModality(Qt.ApplicationModal)

        dialog.exec()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QDialogDemo()
    main.show()
    sys.exit(app.exec_())


运行结果:在这里插入图片描述

p44 显示不同类型的提示消息对话框

'''

消息对话框:QMessageBox


1. 关于对话框
2. 错误对话框
3. 警告对话框
4. 提问对话框
5. 消息对话框


有2点差异
1. 显示的对话框图标可能不同
2. 显示的按钮是不一样的

'''
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class QMessageBoxDemo(QWidget):
    def __init__(self):
        super(QMessageBoxDemo,self).__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle('QMessageBox案例')
        self.resize(300,400)

        layout = QVBoxLayout()
        self.button1 = QPushButton()
        self.button1.setText('显示关于对话框')
        self.button1.clicked.connect(self.showDialog)

        self.button2 = QPushButton()
        self.button2.setText('显示消息对话框')
        self.button2.clicked.connect(self.showDialog)

        self.button3 = QPushButton()
        self.button3.setText('显示警告对话框')
        self.button3.clicked.connect(self.showDialog)


        self.button4 = QPushButton()
        self.button4.setText('显示错误对话框')
        self.button4.clicked.connect(self.showDialog)

        self.button5 = QPushButton()
        self.button5.setText('显示提问对话框')
        self.button5.clicked.connect(self.showDialog)


        layout.addWidget(self.button1)
        layout.addWidget(self.button2)
        layout.addWidget(self.button3)
        layout.addWidget(self.button4)
        layout.addWidget(self.button5)
        self.setLayout(layout)

    def showDialog(self):
        text = self.sender().text()
        if text == '显示关于对话框':
            QMessageBox.about(self,'关于','这是一个关于对话框')
        #以下四种类型的对话框会附带两个按钮,根据函数中的调用,
        #QMessageBox.Yes | QMessageBox.No  :代表Yes与No按钮的位置,谁在前则显示的时候谁在左边,
        #下一个参数代表初始时默认在哪个按钮上
        elif text == '显示消息对话框':
            reply = QMessageBox.information(self,'消息','这是一个消息对话框', QMessageBox.Yes | QMessageBox.No,QMessageBox.Yes)
            print(reply == QMessageBox.Yes)
        elif text == '显示警告对话框':
            QMessageBox.warning(self,'警告','这是一个警告对话框',QMessageBox.Yes | QMessageBox.No,QMessageBox.Yes)
        elif text == '显示错误对话框':
            QMessageBox.critical(self,'警告','这是一个警告对话框',QMessageBox.Yes | QMessageBox.No,QMessageBox.Yes)
        elif text == '显示提问对话框':
            QMessageBox.question(self,'警告','这是一个警告对话框',QMessageBox.Yes | QMessageBox.No,QMessageBox.Yes)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QMessageBoxDemo()
    main.show()
    sys.exit(app.exec_())

运行结果: 在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

p45 显示不同类型的消息对话框(输入对话框)

'''

输入对话框:QInputDialog

QInputDialog.getItem #传入列表中的某一项,类似于复选框
QInputDialog.getText	#传入文本
QInputDialog.getInt	#传入整数

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class QInputDialogDemo(QWidget):
    def __init__(self):
        super(QInputDialogDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('输入对话框')
        layout = QFormLayout()

        self.button1 = QPushButton('获取列表中的选项')
        self.button1.clicked.connect(self.getItem)
        self.lineEdit1 = QLineEdit()
        layout.addRow(self.button1, self.lineEdit1)

        self.button2 = QPushButton('获取字符串')
        self.button2.clicked.connect(self.getText)
        self.lineEdit2 = QLineEdit()
        layout.addRow(self.button2, self.lineEdit2)

        self.button3 = QPushButton('获取整数')
        self.button3.clicked.connect(self.getInt)
        self.lineEdit3 = QLineEdit()
        layout.addRow(self.button3, self.lineEdit3)

        self.setLayout(layout)
    #QInputDialog.方法(文本1,文本2,...)
    #文本1为对话框标题栏
    #文本2为对话框中label上的文本内容
    def getItem(self):
        items = ('C','C++','Ruby','Python','Java')
        item, ok =QInputDialog.getItem(self,'请选择编程语言','语言列表',items)
        if ok and item:
            self.lineEdit1.setText(item)
    def getText(self):
        text, ok =QInputDialog.getText(self,'文本输入框','输入姓名')
        if ok and text:
            self.lineEdit2.setText(text)
    def getInt(self):
        num, ok =QInputDialog.getInt(self,'整数输入框','输入数字')
        if ok and num:
            self.lineEdit3.setText(str(num))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QInputDialogDemo()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

p46 字体对话框

'''

字体对话框:QFontDialog



'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class QFontDialogDemo(QWidget):
    def __init__(self):
        super(QFontDialogDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Font Dialog例子')
        layout = QVBoxLayout()
        self.fontButton = QPushButton('选择字体')
        self.fontButton.clicked.connect(self.getFont)
        layout.addWidget(self.fontButton)

        self.fontLabel = QLabel('Hello,测试字体例子')
        layout.addWidget(self.fontLabel)

        self.setLayout(layout)
    def getFont(self):
        #获取字体信息与按键状态
        font, ok = QFontDialog.getFont()
        #如果点击按钮OK
        if ok :
            self.fontLabel.setFont(font)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QFontDialogDemo()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p47颜色对话框

'''

颜色对话框:QColorDialog

'''

'''

字体对话框:QFontDialog



'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class QColorDialogDemo(QWidget):
    def __init__(self):
        super(QColorDialogDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Color Dialog例子')
        layout = QVBoxLayout()
        self.colorButton = QPushButton('设置颜色')
        self.colorButton.clicked.connect(self.getColor)
        layout.addWidget(self.colorButton)

        self.colorButton1 = QPushButton('设置背景颜色')
        self.colorButton1.clicked.connect(self.getBGColor)
        layout.addWidget(self.colorButton1)

        self.colorLabel = QLabel('Hello,测试颜色例子')
        layout.addWidget(self.colorLabel)

        self.setLayout(layout)
    def getColor(self):
        #选择并返回所选颜色消息
        color = QColorDialog.getColor()
        #调色板
        p = QPalette()
        #设置颜色
        p.setColor(QPalette.WindowText,color)
        #给label控件上色
        self.colorLabel.setPalette(p)
    def getBGColor(self):
        color = QColorDialog.getColor()
        p = QPalette()
        p.setColor(QPalette.Window,color)
        self.colorLabel.setAutoFillBackground(True)
        self.colorLabel.setPalette(p)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QColorDialogDemo()
    main.show()
    sys.exit(app.exec_())


运行结果:在这里插入图片描述

p48文件对话框

'''

文件对话框:QFileDialog
参考链接:http://www.python3.vip/tut/py/gui/qt_05_3/#%E9%80%89%E6%8B%A9%E6%96%87%E4%BB%B6%E6%A1%86

获取单个文件,返回的为文件路径
filePath, _  = QFileDialog.getOpenFileName(
            self.ui,             # 父窗口对象
            "选择你要上传的图片", # 标题
            r"d:\\data",        # 起始目录
            "图片类型 (*.png *.jpg *.bmp)" # 选择类型过滤项,过滤内容在括号中
        )

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class QFileDialogDemo(QWidget):
    def __init__(self):
        super(QFileDialogDemo,self).__init__()
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout()
        self.button1 = QPushButton('加载图片')
        self.button1.clicked.connect(self.loadImage)
        layout.addWidget(self.button1)

        self.imageLabel = QLabel()
        layout.addWidget(self.imageLabel)

        self.button2 = QPushButton('加载文本文件')
        self.button2.clicked.connect(self.loadText)
        layout.addWidget(self.button2)

        self.contents = QTextEdit()
        layout.addWidget(self.contents)

        self.setLayout(layout)
        self.setWindowTitle('文件对话框演示 ')

    def loadImage(self):
        #frame为所选图片路径
        fname,_ = QFileDialog.getOpenFileName(self,'打开文件','.','图像文件(*.jpg *.png)')
        self.imageLabel.setPixmap(QPixmap(fname))

    def loadText(self):
        dialog = QFileDialog()
        #设置打开文件模式,可以打开任何类型的文件
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setFilter(QDir.Files)

        if dialog.exec():       #判断是否打开成功
            #选择文件
            filenames = dialog.selectedFiles()
            f = open(filenames[0],encoding='utf-8',mode='r')
            with f:
                data = f.read()
                self.contents.setText(data)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = QFileDialogDemo()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p49 在窗口上绘制直线

'''

绘图API:绘制文本

1. 文本
2. 各种图形(直线,点,椭圆,弧,扇形,多边形等)
3. 图像

QPainter

painter = QPainter()

painter.begin()

painter.drawText(...)

painter.end()


必须在paintEvent事件方法中绘制各种元素


'''

import sys
from PyQt5.QtWidgets import QApplication,QWidget
from PyQt5.QtGui import QPainter,QColor,QFont
from PyQt5.QtCore import Qt

class DrawText(QWidget):
    def __init__(self):
        super(DrawText,self).__init__()
        self.setWindowTitle('在窗口上绘制文本')
        self.resize(300,200)
        self.text = "Python从菜鸟到高手"
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.begin(self)
        #设置画笔颜色
        painter.setPen(QColor(0,255,0))
        #设置画笔字体
        painter.setFont(QFont('SimSun',25))
        #绘制文本
        painter.drawText(event.rect(),Qt.AlignCenter,self.text)
        painter.end()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = DrawText()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p50 用像素点绘制正弦曲线

'''

用像素点绘制正弦曲线

-2PI  2PI

drawPoint(x,y)

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt

class DrawPoints(QWidget):
    def __init__(self):
        super(DrawPoints,self).__init__()
        self.resize(300,300)
        self.setWindowTitle('在窗口上用像素点绘制2个周期的正弦曲线')
    #此函数名不能变,初始化时会自动调用此函数
    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        painter.setPen(Qt.blue)
        #获取窗口尺寸
        size = self.size()
        #绘制1000个点
        for i in range(1000):
            #(x - size.width()/2.0) * math.pi/50) 从-2pi~+2pi
            x = 100 * (-1 + 2.0 * i/1000) + size.width()/2.0
            y = -50 * math.sin((x - size.width()/2.0) * math.pi/50) + size.height()/2.0
            painter.drawPoint(x,y)

        painter.end()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = DrawPoints()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p51 绘制不同类型的直线

'''

绘制不同类型的直线



'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt

class DrawMultiLine(QWidget):
    def __init__(self):
        super(DrawMultiLine,self).__init__()
        self.resize(300,300)
        self.setWindowTitle('设置Pen的样式')

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)

        #颜色,粗细,线条类型(默认为实线)
        pen = QPen(Qt.red,3,Qt.SolidLine)

        painter.setPen(pen)
        #drawline(x1,y1,x2,y2) #(x1,y1)起始点坐标,(x2,y2)为终点坐标
        painter.drawLine(20,40,250,40)
        #改变线条样式
        #虚线
        pen.setStyle(Qt.DashLine)
        painter.setPen(pen)
        painter.drawLine(20, 80, 250, 80)
        #点画线
        pen.setStyle(Qt.DashDotDotLine)
        painter.setPen(pen)
        painter.drawLine(20, 120, 250, 120)
        #细的虚线
        pen.setStyle(Qt.DotLine)
        painter.setPen(pen)
        painter.drawLine(20, 160, 250, 160)

        pen.setStyle(Qt.DashDotDotLine)
        painter.setPen(pen)
        painter.drawLine(20, 200, 250, 200)
        #自定义
        pen.setStyle(Qt.CustomDashLine)
        pen.setDashPattern([1,10,5,8])
        painter.setPen(pen)
        painter.drawLine(20, 240, 250, 240)

        painter.end()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = DrawMultiLine()
    main.show()
    sys.exit(app.exec_())

运行效果:在这里插入图片描述

p52 绘制各种图形

'''

绘制各种图形

弧
圆形
椭圆
矩形(正方形)
多边形
绘制图像

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class DrawAll(QWidget):
    def __init__(self):
        super(DrawAll,self).__init__()
        self.resize(300,600)
        self.setWindowTitle('绘制各种图形')
    def paintEvent(self, event):
        qp = QPainter()
        qp.begin(self)

        qp.setPen(Qt.blue)

        # 绘制弧
        rect = QRect(0,10,100,100) #定义绘制区域
        # alen: 1个alen等于1/16度   45 * 16
        qp.drawArc(rect,0, 90 * 16) #三个参数含义:绘图区域,起始角度,终止角度,第一个参数可以为四个数
        # 通过弧绘制圆
        qp.setPen(Qt.red)
        qp.drawArc(120,10,100,100,0, 360 * 16)

        # 绘制带弦的弧
        qp.drawChord(10,120,100,100,12,130*16)

        # 绘制扇形
        qp.drawPie(10,240,100,100,12,130*16)

        # 椭圆
        qp.drawEllipse(120,120,150,100)  #参数为绘制区域,
        # 绘制5边形
        point1 = QPoint(140,380)
        point2 = QPoint(270,420)
        point3 = QPoint(290,512)
        point4 = QPoint(290,588)
        point5 = QPoint(200,533)

        polygon = QPolygon([point1,point2,point3,point4,point5])
        qp.drawPolygon(polygon)

        # 绘制图像
        image = QImage('./images/book1.png')
        rect = QRect(10, 400, image.width()/3, image.height()/3) #绘制区域,左上角顶点和长宽
        #image.save('./images/book1.png')
        qp.drawImage(rect,image)

        qp.end()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = DrawAll()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p53 用画刷填充图形区域

'''

用画刷填充图形区域

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class FillRect(QWidget):
    def __init__(self):
        super(FillRect,self).__init__()
        self.resize(600,600)
        self.setWindowTitle('用画刷填充区域')

    def paintEvent(self,e):
        qp = QPainter()
        qp.begin(self)
        brush = QBrush(Qt.SolidPattern)  #通过QBush设置填充的不同样式
        qp.setBrush(brush)
        qp.drawRect(10,15,90,60)

        brush = QBrush(Qt.Dense1Pattern)
        qp.setBrush(brush)
        qp.drawRect(130,15,90,60) #绘制矩形

        brush = QBrush(Qt.Dense2Pattern)
        qp.setBrush(brush)
        qp.drawRect(250,15,90,60)

        brush = QBrush(Qt.Dense3Pattern)
        qp.setBrush(brush)
        qp.drawRect(10, 105, 90, 60)

        brush = QBrush(Qt.HorPattern)
        qp.setBrush(brush)
        qp.drawRect(130, 105, 90, 60)
        qp.end()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = FillRect()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p54 让控件支持拖拽操作

'''
让控件支持拖拽动作
A.setDragEnabled(True)

B.setAcceptDrops(True)

B需要两个事件
1. dragEnterEvent   将A拖到B触发
2. dropEvent        在B的区域放下A时触发


'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class MyComboBox(QComboBox) :
    def __init__(self):
        super(MyComboBox,self).__init__()
        #设置控件可以接受拖拽数据
        self.setAcceptDrops(True)
    def dragEnterEvent(self,e):
        print(e)
        if e.mimeData().hasText():  #判断数据是否为文本数据
            e.accept()
        else:
            e.ignore()
    def dropEvent(self,e):
        self.addItem(e.mimeData().text()) #往复选框里放数据

class DrapDropDemo(QWidget):
    def __init__(self):
        super(DrapDropDemo,self).__init__()
        formLayout = QFormLayout()
        formLayout.addRow(QLabel("请将左边的文本拖拽到右边的下拉列表中"))
        lineEdit = QLineEdit()
        #设置控件支持拖拽
        lineEdit.setDragEnabled(True)  # 让QLineEdit控件可拖动

        combo = MyComboBox()
        formLayout.addRow(lineEdit,combo)
        self.setLayout(formLayout)
        self.setWindowTitle('拖拽案例')
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = DrapDropDemo()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p55 使用剪贴板

'''
使用剪贴板


'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class ClipBoard(QDialog):
    def __init__(self):
        super(ClipBoard,self).__init__()
        textCopyButton = QPushButton('复制文本')
        textPasteButton = QPushButton('粘贴文本')

        htmlCopyButton = QPushButton('复制HTML')
        htmlPasteButton = QPushButton('粘贴HTML')

        imageCopyButton = QPushButton('复制图像')
        imagePasteButton = QPushButton('粘贴图像')

        self.textLabel  = QLabel('默认文本')
        self.imageLabel=QLabel("默认图像")
      #  self.imageLabel.setPixmap(QPixmap('./images/book1.png'))

        layout = QGridLayout()
        layout.addWidget(textCopyButton,0,0)
        layout.addWidget(imageCopyButton,0,1)
        layout.addWidget(htmlCopyButton,0,2)
        layout.addWidget(textPasteButton,1,0)
        layout.addWidget(htmlPasteButton,1,1)
        layout.addWidget(imagePasteButton,1,2)

        layout.addWidget(self.textLabel,2,0,1,2)
        layout.addWidget(self.imageLabel,2,2)

        self.setLayout(layout)

        textCopyButton.clicked.connect(self.copyText)

        textPasteButton.clicked.connect(self.pasteText)
        htmlCopyButton.clicked.connect(self.copyHtml)
        htmlPasteButton.clicked.connect(self.pasteHtml)
        imageCopyButton.clicked.connect(self.copyImage)
        imagePasteButton.clicked.connect(self.pasteImage)

        self.setWindowTitle('剪贴板演示')

    def copyText(self):
        clipboard = QApplication.clipboard()  #创建剪贴板
        clipboard.setText('hello world')    #设置剪贴板文字
    def pasteText(self):
        clipboard = QApplication.clipboard()
        self.textLabel.setText(clipboard.text())    #粘贴文本

    def copyImage(self):
        clipboard = QApplication.clipboard()
        clipboard.setPixmap(QPixmap('./images/book.png')) #复制图像

    def pasteImage(self):
        clipboard = QApplication.clipboard()
        self.imageLabel.setPixmap(clipboard.pixmap()) #粘贴图像

    def copyHtml(self):
        mimeData = QMimeData()
        mimeData.setHtml('<b>Bold and <font color=red>Red</font></b>')
        clipboard = QApplication.clipboard()
        clipboard.setMimeData(mimeData)

    def pasteHtml(self):
        clipboard = QApplication.clipboard()
        mimeData = clipboard.mimeData()
        if mimeData.hasHtml():
            self.textLabel.setText(mimeData.html())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = ClipBoard()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p56 日历控件

'''
日历控件

QCalendarWidget

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class MyCalendar(QWidget):
    def __init__(self):
        super(MyCalendar, self).__init__()
        self.initUI()
    def initUI(self):
        #创建日历控件
        self.cal = QCalendarWidget(self)
        #设置日历的最小最大时间
        self.cal.setMinimumDate(QDate(1988,1,1))
        self.cal.setMaximumDate(QDate(2088,1,1))
        #以网格显示
        self.cal.setGridVisible(True)
        #移动位置
        self.cal.move(20,20)
        self.cal.clicked.connect(self.showDate)
        self.label = QLabel(self)
        #选择日期时间
        date = self.cal.selectedDate()
        #将时间转化为指定格式
        self.label.setText(date.toString("yyyy-MM-dd dddd"))
        self.label.move(20,300)

        self.resize(400,350)
        self.setWindowTitle("日历演示")

    def showDate(self,date):
        #self.label.setText((date.toString("yyyy-MM-dd dddd")))
        self.label.setText((self.cal.selectedDate().toString("yyyy-MM-dd dddd")))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = MyCalendar()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p57 设置不同风格的日期和时间

p58 日期和时间控件的高级操作

'''
输入各种风格的日期和时间

QDateTimeEdit

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class DateTimeEdit(QWidget):
    def __init__(self):
        super(DateTimeEdit, self).__init__()
        self.initUI()
    def initUI(self):
        vlayout = QVBoxLayout()
        dateTimeEdit1 = QDateTimeEdit()
        dateTimeEdit2 = QDateTimeEdit(QDateTime.currentDateTime())
        #设置最大最小界限
        dateTimeEdit1.setMinimumDate(QDate.currentDate().addDays(-365))
        dateTimeEdit1.setMaximumDate(QDate.currentDate().addDays(365))
        self.dateTimeEdit = dateTimeEdit1
        dateTimeEdit2.setCalendarPopup(True)
        #只显示日期
        dateEdit = QDateTimeEdit(QDate.currentDate())
        #只显示时间
        timeEdit = QDateTimeEdit(QTime.currentTime())
        #设置显示格式
        dateTimeEdit1.setDisplayFormat("yyyy-MM-dd  HH:mm:ss")
        dateTimeEdit2.setDisplayFormat("yyyy/MM/dd HH-mm-ss")

        dateEdit.setDisplayFormat("yyyy.MM.dd")
        timeEdit.setDisplayFormat("HH:mm:ss")

        dateTimeEdit1.dateChanged.connect(self.onDateChanged)
        dateTimeEdit1.timeChanged.connect(self.onTimeChanged)
        dateTimeEdit1.dateTimeChanged.connect(self.onDateTimeChanged)

        vlayout.addWidget(dateTimeEdit1)
        vlayout.addWidget(dateTimeEdit2)
        vlayout.addWidget(dateEdit)
        vlayout.addWidget(timeEdit)

        self.btn = QPushButton('获取日期和时间')
        self.btn.clicked.connect(self.onButtonClick)
        vlayout.addWidget(self.btn)
        self.setLayout(vlayout)

        self.resize(300,90)
        self.setWindowTitle("设置不同风格的日期和时间")

    # 日期变化
    def onDateChanged(self,date):
        print(date)

    # 时间变化
    def onTimeChanged(self,time):
        print(time)

    # 日期和时间变化
    def onDateTimeChanged(self,datetime):
        print(datetime)

    def onButtonClick(self):
        datetime = self.dateTimeEdit.dateTime()
        print(datetime)

        # 最大日期
        print(self.dateTimeEdit.maximumDate())
        # 最大日期和时间
        print(self.dateTimeEdit.maximumDateTime())

        # 最小日期
        print(self.dateTimeEdit.minimumDateTime())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = DateTimeEdit()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p59 创建和使用菜单

'''

创建和使用菜单

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class Menu(QMainWindow) :
    def __init__(self):
        super(Menu,self).__init__()
        #通过menuBar()创建菜单栏
        bar = self.menuBar()  # 获取菜单栏
        #通过addMenu()添加菜单栏项目
        file = bar.addMenu("文件")
        file.addAction("新建")
        #通过以下方法也可添加菜单栏选项,与addMenu()同等效果
        save = QAction("保存",self)
        #设置快捷键
        save.setShortcut("Ctrl + S")
        file.addAction(save)

        save.triggered.connect(self.process)

        edit = bar.addMenu("Edit")
        edit.addAction("copy")
        edit.addAction("paste")
        quit = QAction("退出",self)
        file.addAction(quit)

    def process(self,a):
        print(self.sender().text())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Menu()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p60 创建和使用工具栏

'''

创建和使用工具栏

工具栏默认按钮:只显示图标,将文本作为悬停提示展示

工具栏按钮有3中显示状态

1.  只显示图标
2.  只显示文本
3.  同时显示文本和图标
'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class Toolbar(QMainWindow) :
    def __init__(self):
        super(Toolbar,self).__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle("工具栏例子")
        self.resize(400,400)
        #添加工具栏
        tb1 = self.addToolBar("File")

        new = QAction(QIcon('./images/new.png'),"new",self)
        tb1.addAction(new)

        open = QAction(QIcon('./images/open.png'),"open",self)
        tb1.addAction(open)

        save = QAction(QIcon('./images/save.png'),"save",self)
        tb1.addAction(save)
        tb1.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

        tb2 = self.addToolBar("File1")
        new1 = QAction(QIcon('./images/new.png'),"新建",self)
        tb2.addAction(new1)
        #设置显示时文本与图像的相对位置
        tb2.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        #点击工具栏按钮触发事件
        tb1.actionTriggered.connect(self.toolbtnpressed)

        tb2.actionTriggered.connect(self.toolbtnpressed)
    def toolbtnpressed(self,a):
        print("按下的工具栏按钮是",a.text())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Toolbar()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p61 创建和使用状态栏

'''

创建和使用状态栏

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class StatusBar(QMainWindow) :
    def __init__(self):
        super(StatusBar,self).__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle("状态栏演示")
        self.resize(300,200)
        #创建菜单栏
        bar = self.menuBar()
        file = bar.addMenu("File")
        #添加菜单选项
        file.addAction("show")
        file.triggered.connect(self.processTrigger)
        self.setCentralWidget(QTextEdit())
        #创建状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)


    def processTrigger(self,q):
        if q.text() == "show" :
            self.statusBar.showMessage(q.text() + " 菜单被点击了",5000)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = StatusBar()
    main.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p62 使用打印机

'''

使用打印机



'''

from PyQt5 import QtGui, QtWidgets, QtPrintSupport
from PyQt5.QtWidgets import *
import sys

class PrintSupport(QMainWindow):
    def __init__(self):
        super(PrintSupport,self).__init__()
        self.setGeometry(500, 200, 300, 300)
        self.button = QPushButton('打印QTextEdit控件中的内容',self)
        self.button.setGeometry(20,20,260,30)
        self.editor = QTextEdit('默认文本',self)
        self.editor.setGeometry(20,60,260,200)

        self.button.clicked.connect(self.print)

    def print(self):
        #创建打印机对象
        printer = QtPrintSupport.QPrinter()

        painter = QtGui.QPainter()
        # 将绘制的目标重定向到打印机
        painter.begin(printer)
        #获取控件editor整个界面
        screen = self.editor.grab()
        #10,10为左上角顶点坐标,开始绘制的起点
        painter.drawPixmap(10,10,screen)
        painter.end()
        print("print")


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    gui = PrintSupport()
    gui.show()
    app.exec_()

运行结果:

在这里插入图片描述

在这里插入图片描述

p63 显示打印对话框

'''

显示打印对话框

'''
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton, QTextEdit, QFileDialog, QDialog
from PyQt5.QtPrintSupport import QPageSetupDialog, QPrintDialog, QPrinter
import sys


class PrintDialog(QWidget):
    def __init__(self):
        super(PrintDialog,self).__init__()
        self.printer = QPrinter()
        self.initUI()



    def initUI(self):
        self.setGeometry(300, 300, 500, 400)
        self.setWindowTitle('打印对话框')

        self.editor = QTextEdit(self)
        self.editor.setGeometry(20,20,300,270)

        self.openButton = QPushButton('打开文件',self)
        self.openButton.move(350,20)

        self.settingsButton = QPushButton('打印设置',self)
        self.settingsButton.move(350,50)

        self.printButton = QPushButton('打印文档',self)
        self.printButton.move(350,80)

        self.openButton.clicked.connect(self.openFile)
        self.settingsButton.clicked.connect(self.showSettingsDialog)
        self.printButton.clicked.connect(self.showPrintDialog)

    # 打开文件
    def openFile(self):
        fname = QFileDialog.getOpenFileName(self,'打开文本文件','./')
        if fname[0]:
            with open(fname[0],'r',encoding='utf-8',errors = 'ignore') as f:
                self.editor.setText(f.read())
    # 显示打印设置对话框
    def showSettingsDialog(self):
        printDialog = QPageSetupDialog(self.printer,self)
        printDialog.exec()

    # 显示打印对话框
    def showPrintDialog(self):
        printdialog = QPrintDialog(self.printer,self)
        if QDialog.Accepted == printdialog.exec():
            self.editor.print(self.printer)





if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = PrintDialog()
    gui.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

p64 显示二维表数据

'''

显示二维表数据(QTableView控件)

数据源

Model

需要创建QTableView实例和一个数据源(Model),然后将两者关联

MVC:Model   Viewer   Controller

MVC的目的是将后端的数据和前端页面的耦合度降低



'''
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys

class TableView(QWidget):

	def __init__(self, arg=None):
		super(TableView, self).__init__(arg)
		self.setWindowTitle("QTableView表格视图控件演示")
		self.resize(500,300);
		#创建4行3列的表格
		self.model = QStandardItemModel(4,3)
		#设置各列的标签名称
		self.model.setHorizontalHeaderLabels(['id','姓名','年龄'])

		self.tableview = QTableView()
		# 关联QTableView控件和Model
		self.tableview.setModel(self.model)

		# 添加数据
		item11 = QStandardItem('10')
		item12 = QStandardItem('雷神')
		item13 = QStandardItem('2000')
		self.model.setItem(0,0,item11) #1行1列添加数据,行列索引从0开始
		self.model.setItem(0,1, item12)
		self.model.setItem(0,2, item13)

		item31 = QStandardItem('30')
		item32 = QStandardItem('死亡女神')
		item33 = QStandardItem('3000')
		self.model.setItem(2,0,item31)
		self.model.setItem(2,1, item32)
		self.model.setItem(2,2, item33)

		layout = QVBoxLayout()
		layout.addWidget(self.tableview)
		self.setLayout(layout)

		


if __name__ == '__main__':
	app = QApplication(sys.argv)	
	table = TableView()
	table.show()
	sys.exit(app.exec_())

运行结果:在这里插入图片描述

p65 显示列数据

'''

显示列表数据(QListView控件)

'''

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QListView, QMessageBox
from PyQt5.QtCore import QStringListModel
import sys


class ListViewDemo(QWidget):
    def __init__(self, parent=None):
        super(ListViewDemo, self).__init__(parent)
        self.setWindowTitle("QListView 例子")
        self.resize(300, 270)
        layout = QVBoxLayout()

        listview = QListView()
        #数据源
        listModel = QStringListModel()
        #列列表
        self.list = ["列表项1","列表项2", "列表项3"]

        listModel.setStringList(self.list)
        #关联控件与model
        listview.setModel(listModel)
        listview.clicked.connect(self.clicked)
        layout.addWidget(listview)

        self.setLayout(layout)

    def clicked(self,item):
        #触发事件,显示消息框
        QMessageBox.information(self,"QListView","您选择了:" + self.list[item.row()])
		#information(主题,显示框标题,显示框内容)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = ListViewDemo()
    win.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p66 扩展的列表控件

'''

扩展的列表控件(QListWidget)

QListView
'''
from PyQt5.QtWidgets import *
import sys

class ListWidgetDemo(QMainWindow):
	def __init__(self, parent=None):
		super(ListWidgetDemo, self).__init__(parent)
		self.setWindowTitle("QListWidget 例子")
		self.resize(300, 270)
		self.listwidget = QListWidget()
		#通过addItem直接添加列数据
		self.listwidget.addItem("item1")
		self.listwidget.addItem("item2")
		self.listwidget.addItem("item3")
		self.listwidget.addItem("item4")
		self.listwidget.addItem("item5")
		self.listwidget.itemClicked.connect(self.clicked)
		self.setCentralWidget(self.listwidget)
	def clicked(self,Index):
		QMessageBox.information(self,"QListWidget","您选择了:" + self.listwidget.item(self.listwidget.row(Index)).text())



if __name__ == "__main__":
	app = QApplication(sys.argv)
	win = ListWidgetDemo()
	win.show()
	sys.exit(app.exec_())

运行结果:在这里插入图片描述

p67 扩展的表格控件

'''

扩展的表格控件(QTableWidget)

QTableView

每一个Cell(单元格)是一个QTableWidgetItem

'''

import sys
from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem, QAbstractItemView)


class TableWidgetDemo(QWidget):
    def __init__(self):
        super(TableWidgetDemo,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("QTableWidget演示")
        self.resize(430, 230);
        layout = QHBoxLayout()
        tablewidget = QTableWidget()
        tablewidget.setRowCount(4) #设置行数
        tablewidget.setColumnCount(3) #设置列数

        layout.addWidget(tablewidget)
        #设置列名
        tablewidget.setHorizontalHeaderLabels(['姓名','年龄','籍贯'])
        #给指定位置添加数据
        nameItem = QTableWidgetItem("小明")
        tablewidget.setItem(0,0,nameItem)

        ageItem = QTableWidgetItem("24")
        tablewidget.setItem(0,1,ageItem)

        jgItem = QTableWidgetItem("北京")
        tablewidget.setItem(0,2,jgItem)

        # 禁止编辑
        tablewidget.setEditTriggers(QAbstractItemView.NoEditTriggers)

        # 整行选择
        tablewidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        # 调整列和行,尺寸根据内容自适应
        tablewidget.resizeColumnsToContents()
        tablewidget.resizeRowsToContents()
        #将表头(行列名)隐藏
        tablewidget.horizontalHeader().setVisible(False) #列名
        # tablewidget.verticalHeader().setVisible(False)  #行名
        #手动设置行名
        tablewidget.setVerticalHeaderLabels(["a","b"])

        # 隐藏表格线
        tablewidget.setShowGrid(False)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = TableWidgetDemo()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p68 在单元格中放置控件

'''

在单元格中放置控件

setItem:将文本放到单元格中
setCellWidget:将控件放到单元格中
setStyleSheet:设置控件的样式(QSS)

'''

import sys
from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem, QAbstractItemView,
                              QComboBox, QPushButton,QVBoxLayout)


class PlaceControlInCell(QWidget):
    def __init__(self):
        super(PlaceControlInCell,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("在单元格中放置控件")
        self.resize(430, 300)
        layout = QHBoxLayout()
        tableWidget = QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)

        layout.addWidget(tableWidget)
        #列名
        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])
        textItem = QTableWidgetItem('小明') #放置文本
        tableWidget.setItem(0,0,textItem)

        combox = QComboBox()
        combox.addItem('男')
        combox.addItem('女')
        # QSS Qt StyleSheet
        #设置下拉列表控件的样式
        combox.setStyleSheet('QComboBox{margin:3px};') #边距3像素
        tableWidget.setCellWidget(0,1,combox) #添加控件

        modifyButton = QPushButton('修改')
        #默认按钮为按下状态
        modifyButton.setDown(True)
        modifyButton.setStyleSheet('QPushButton{margin:3px};')
        tableWidget.setCellWidget(0,2,modifyButton)

        # 调整列和行,尺寸根据内容自适应
        tableWidget.resizeColumnsToContents()
        tableWidget.resizeRowsToContents()

        self.setLayout(layout)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = PlaceControlInCell()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p69 在表格中搜索Cell和行定位

'''

在表格中快速定位到特定的行

1. 数据的定位:findItems  返回一个列表
2. 如果找到了满足条件的单元格,会定位到单元格所在的行:setSliderPosition(row)

'''

import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from PyQt5.QtGui import QColor, QBrush


class DataLocation(QWidget):
    def __init__(self):
        super(DataLocation,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("QTableWidget 例子")
        self.resize(600, 800);

        layout = QHBoxLayout()
        tableWidget = QTableWidget()
        #表格设置为40行4列
        tableWidget.setRowCount(40)
        tableWidget.setColumnCount(4)

        layout.addWidget(tableWidget)
        #添加内容
        for i in range(40):
            for j in range(4):
                itemContent = '(%d,%d)' %(i,j)
                tableWidget.setItem(i,j,QTableWidgetItem(itemContent))
        self.setLayout(layout)

        # 搜索满足条件的Cell
        text = '(4'
        #以列表的形式返回查找结果
        items = tableWidget.findItems(text,QtCore.Qt.MatchStartsWith) #此匹配模式为以text开头的匹配模式
        if len(items) > 0:
            item = items[0]
            #设置背景颜色
            item.setBackground(QBrush(QColor(255,255,0)))
            #设置文字颜色
            item.setForeground(QBrush(QColor(255,0,0)))

            row = item.row()

            # 定位到指定的行
            tableWidget.verticalScrollBar().setSliderPosition(row)
        #也可以精确匹配
        """findItems(text,type):
                text:文本,定位依据(cell 位置)
                type:搜索的方式
        """
if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = DataLocation()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p70 设置单元格字体和颜色

'''
设置单元格字体和颜色



'''

import sys
from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem)
from PyQt5.QtGui import QBrush, QColor, QFont


class CellFontAndColor(QWidget):
    def __init__(self):
        super(CellFontAndColor,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("设置单元格字体和颜色")
        self.resize(430, 230);
        layout = QHBoxLayout()
        tableWidget = QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        layout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])

        newItem = QTableWidgetItem('雷神')
        #设置字体
        newItem.setFont(QFont('Times',14,QFont.Black))
        #设置字体颜色
        newItem.setForeground(QBrush(QColor(255,0,0)))
        tableWidget.setItem(0,0,newItem)

        newItem = QTableWidgetItem('女')
        newItem.setForeground(QBrush(QColor(255,255,0)))
        #设置背景颜色
        newItem.setBackground(QBrush(QColor(0,0,255)))
        tableWidget.setItem(0,1,newItem)

        newItem = QTableWidgetItem('160')
        newItem.setFont(QFont('Times',20,QFont.Black))
        newItem.setForeground(QBrush(QColor(0,0,255)))
        tableWidget.setItem(0,2,newItem)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = CellFontAndColor()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p71 按表格的某一列排序

'''

按列排序

1. 按哪一列排序
2. 排序类型:升序或降序

sortItems(columnIndex,orderType)

'''

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


class ColumnSort(QWidget):
    def __init__(self):
        super(ColumnSort,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("按列排序")
        self.resize(430, 230)
        layout = QVBoxLayout()
        self.tableWidget = QTableWidget()
        #设置行列
        self.tableWidget.setRowCount(4)
        self.tableWidget.setColumnCount(3)
        layout.addWidget(self.tableWidget)
        #设置水平列名
        self.tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])
        #添加数据
        newItem = QTableWidgetItem('张三')
        self.tableWidget.setItem(0,0,newItem)

        newItem=QTableWidgetItem('男')
        self.tableWidget.setItem(0,1,newItem)

        newItem=QTableWidgetItem('165')
        self.tableWidget.setItem(0,2,newItem)

        newItem = QTableWidgetItem('李四')
        self.tableWidget.setItem(1, 0, newItem)

        newItem = QTableWidgetItem('女')
        self.tableWidget.setItem(1, 1, newItem)

        newItem = QTableWidgetItem('160')
        self.tableWidget.setItem(1, 2, newItem)

        newItem = QTableWidgetItem('王五')
        self.tableWidget.setItem(2, 0, newItem)

        newItem = QTableWidgetItem('男')
        self.tableWidget.setItem(2, 1, newItem)

        newItem = QTableWidgetItem('170')
        self.tableWidget.setItem(2, 2, newItem)

        self.button = QPushButton('排序')
        self.button.clicked.connect(self.order)
        layout.addWidget(self.button)
        #设置排序类型
        self.orderType = Qt.DescendingOrder #降序,从大到小
        self.setLayout(layout)


    def order(self):
        if self.orderType == Qt.DescendingOrder:
            self.orderType = Qt.AscendingOrder      #升序,从小到大
        else:
            self.orderType = Qt.DescendingOrder
        #按列索引为2的那一列(即第三列)排序
        self.tableWidget.sortItems(2,self.orderType)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = ColumnSort()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p72 设置单元格的文本对齐方式

'''

设置单元格的文本对齐方式

setTextAlignment

Qt.AlignRight   Qt.AlignBottom

'''

import sys
from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem)
from PyQt5.QtCore import Qt


class CellTextAlignment(QWidget):
    def __init__(self):
        super(CellTextAlignment,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("设置单元格的文本对齐方式")
        self.resize(430, 230);
        layout = QHBoxLayout()
        tableWidget = QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        layout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])

        newItem = QTableWidgetItem('雷神')
        #设置单元格文本对其
        
        #右下角对其
        newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
        tableWidget.setItem(0,0,newItem)

        newItem = QTableWidgetItem('男')
        #中底部对其
        newItem.setTextAlignment(Qt.AlignCenter | Qt.AlignBottom)
        tableWidget.setItem(0,1,newItem)

        newItem = QTableWidgetItem('190')
        #右对齐(右上)
        newItem.setTextAlignment(Qt.AlignRight)
        tableWidget.setItem(0,2,newItem)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = CellTextAlignment()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p73 合并单元格

'''

合并单元格

setSpan(row,col,要合并的行数,要合并的列数)

'''

import sys
from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem)


class Span(QWidget):
    def __init__(self):
        super(Span,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("合并单元格")
        self.resize(430, 230)
        layout = QHBoxLayout()
        tableWidget = QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        layout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])

        newItem = QTableWidgetItem('雷神')
        tableWidget.setItem(0,0,newItem)
        #0行0列开始,合并3行1列
        tableWidget.setSpan(0, 0, 3, 1)

        newItem = QTableWidgetItem('男')
        tableWidget.setItem(0,1,newItem)
        #0行1列开始,合并2行1列
        tableWidget.setSpan(0,1,2,1)

        newItem = QTableWidgetItem('160')
        tableWidget.setItem(0,2,newItem)
        #0行2列开始,合并4行1列
        tableWidget.setSpan(0,2,4,1)


        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = Span()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p74 设置单元格的尺寸

'''

设置单元格尺寸

'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QBrush, QColor, QFont

class CellSize(QWidget):
    def __init__(self):
        super(CellSize,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("QTableWidget 例子")
        self.resize(530, 300)
        layout = QHBoxLayout()
        tableWidget = QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        layout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])
        tableWidget.setRowHeight(0, 80) #第1行的高度
        tableWidget.setColumnWidth(2, 120) #第3列的宽度
        tableWidget.setRowHeight(2,100) #第3行的高度
        newItem = QTableWidgetItem('雷神')
        #字体
        newItem.setFont(QFont('Times',40,QFont.Black))
        #背景
        newItem.setForeground(QBrush(QColor(255,0,0)))
        tableWidget.setItem(0,0,newItem)

        newItem = QTableWidgetItem('女')
        newItem.setForeground(QBrush(QColor(255,255,0)))
        newItem.setBackground(QBrush(QColor(0,0,255)))
        tableWidget.setItem(0,1,newItem)

        newItem = QTableWidgetItem('160')
        newItem.setFont(QFont('Times',60,QFont.Black))
        newItem.setForeground(QBrush(QColor(0,0,255)))
        tableWidget.setItem(0,2,newItem)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = CellSize()
    example.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p75 在单元格中实现图文混排效果

'''

在单元格中实现图文混排的效果

'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *



class CellImageText(QWidget):

    def __init__(self):
        super(CellImageText,self).__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle("在单元格中实现图文混排的效果")
        self.resize(500, 300);
        layout = QHBoxLayout()
        self.tableWidget = QTableWidget()
        self.tableWidget.setRowCount(5)
        self.tableWidget.setColumnCount(4)
        layout.addWidget(self.tableWidget)

        self.tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重', '显示图片'])

        newItem = QTableWidgetItem('李宁')
        self.tableWidget.setItem(0,0,newItem)

        newItem = QTableWidgetItem('男')
        self.tableWidget.setItem(0,1,newItem)
        newItem = QTableWidgetItem('160')
        self.tableWidget.setItem(0,2,newItem)
        #添加图文混合,QIcon():第一个参数为图片路径,第二个为文本
        newItem = QTableWidgetItem(QIcon('./images/bao1.png'),'背包')
        self.tableWidget.setItem(0,3,newItem)



        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = CellImageText()
    example.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p76 改变单元格中图片的尺寸

'''

改变单元格中图片的尺寸

setIconSize(QSize(width,height))

'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


class CellImageSize(QWidget):
    def __init__(self):
        super(CellImageSize,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("改变单元格中图片的尺寸")
        self.resize(1000, 900);
        layout = QHBoxLayout()

        tablewidget = QTableWidget()
        #设置图片的尺寸:300*200
        tablewidget.setIconSize(QSize(300,200))
        tablewidget.setColumnCount(3)
        tablewidget.setRowCount(5)

        tablewidget.setHorizontalHeaderLabels(['图片1', '图片2', '图片3'])

        # 让列的宽度和图片的宽度相同
        for i in range(3):
            tablewidget.setColumnWidth(i,300)

        # 让行的高度和图片的高度相同
        for i in range(15):
            tablewidget.setRowHeight(i,200)

        for k in range(15):
            i = k / 3   # 行
            j = k % 3   # 列
            item = QTableWidgetItem()
            #添加图片
            item.setIcon(QIcon('./images/bao%d.png' % k))
            tablewidget.setItem(i,j,item)


        layout.addWidget(tablewidget)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = CellImageSize()
    example.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p77 在表格中显示上下文菜单

'''

在表格中显示上下文菜单

1.  如何弹出菜单
2.  如果在满足条件的情况下弹出菜单

QMenu.exec_
'''

import sys
from PyQt5.QtWidgets import (QMenu, QPushButton, QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem,
                             QHeaderView)
from PyQt5.QtCore import QObject, Qt


class TableWidgetContextMenu(QWidget):

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

    def initUI(self):
        self.setWindowTitle("在表格中显示上下文菜单")
        self.resize(500, 300);
        layout = QHBoxLayout()
        self.tableWidget = QTableWidget()
        self.tableWidget.setRowCount(5)
        self.tableWidget.setColumnCount(3)
        layout.addWidget(self.tableWidget)

        self.tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重'])


        newItem = QTableWidgetItem("张三")
        self.tableWidget.setItem(0, 0, newItem)

        newItem = QTableWidgetItem("男")
        self.tableWidget.setItem(0, 1, newItem)

        newItem = QTableWidgetItem("160")
        self.tableWidget.setItem(0, 2, newItem)
        # 表格中第二行记录
        newItem = QTableWidgetItem("李四")
        self.tableWidget.setItem(1, 0, newItem)

        newItem = QTableWidgetItem("女")
        self.tableWidget.setItem(1, 1, newItem)

        newItem = QTableWidgetItem("170")
        self.tableWidget.setItem(1, 2, newItem)

        # 表格中第二行记录
        newItem = QTableWidgetItem("李")
        self.tableWidget.setItem(2, 0, newItem)

        newItem = QTableWidgetItem("女")
        self.tableWidget.setItem(2, 1, newItem)

        newItem = QTableWidgetItem("170")
        self.tableWidget.setItem(2, 2, newItem)
        #允许弹出菜单
        self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        #单击鼠标右键,触发事件
        self.tableWidget.customContextMenuRequested.connect(self.generateMenu)

        self.setLayout(layout)

    def generateMenu(self,pos):
        print(pos)  #鼠标坐标,相对于主控件而言

        for i in self.tableWidget.selectionModel().selection().indexes():
            rowNum = i.row() #得到行索引
        # 如果选择的行索引小于2,弹出上下文菜单
        if rowNum < 2:
            #创建菜单栏
            menu = QMenu()
            #添加菜单选项
            item1 = menu.addAction("菜单项1")
            item2 = menu.addAction("菜单项2")
            item3 = menu.addAction("菜单项3")
            #将局部坐标映射为全局坐标,即相对于电脑屏幕
            screenPos = self.tableWidget.mapToGlobal(pos)
            print(screenPos)
            # 被阻塞
            action = menu.exec(screenPos)
            if action == item1:
                print('选择了第1个菜单项',self.tableWidget.item(rowNum,0).text(),
                                        self.tableWidget.item(rowNum,1).text(),
                                        self.tableWidget.item(rowNum, 2).text())
            elif action == item2:
                print('选择了第2个菜单项',self.tableWidget.item(rowNum,0).text(),
                                        self.tableWidget.item(rowNum,1).text(),
                                        self.tableWidget.item(rowNum, 2).text())
            elif action == item3:
                print('选择了第3个菜单项',self.tableWidget.item(rowNum,0).text(),
                                        self.tableWidget.item(rowNum,1).text(),
                                        self.tableWidget.item(rowNum, 2).text())
            else:
                return




if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = TableWidgetContextMenu()
    example.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p78 树控件的基本用法

'''

树控件(QTreeWidget)的基本用法



'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon, QBrush, QColor
from PyQt5.QtCore import Qt


class BasicTreeWidget(QMainWindow):
    def __init__(self, parent=None):
        super(BasicTreeWidget, self).__init__(parent)
        self.setWindowTitle('树控件(QTreeWidget)的基本用法')
        #创建树控件
        self.tree = QTreeWidget()
        # 为树控件指定列数
        self.tree.setColumnCount(2)

        # 指定列标签
        self.tree.setHeaderLabels(['Key','Value'])

        root = QTreeWidgetItem(self.tree)
        root.setText(0,'根节点')
        root.setIcon(0,QIcon('./images/root.png'))
        self.tree.setColumnWidth(0,160)  #设置列宽

        # 添加子节点1
        child1 = QTreeWidgetItem(root)
        #添加文本
        child1.setText(0,'子节点1') #第一列
        child1.setText(1,'子节点1的数据') #第二列
        #添加图片
        child1.setIcon(0,QIcon('./images/bao3.png'))
        #为子节点添加复选框
        child1.setCheckState(0,Qt.Checked)

        # 添加子节点2
        child2 = QTreeWidgetItem(root)
        child2.setText(0,'子节点2')
        child2.setIcon(0,QIcon('./images/bao6.png'))

        # 为child2添加一个子节点
        child3 = QTreeWidgetItem(child2)
        child3.setText(0,'子节点2-1')
        child3.setText(1,'新的值')
        child3.setIcon(0,QIcon('./images/music.png'))

        self.tree.expandAll()  #所有子节点全部展开

        self.setCentralWidget(self.tree)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    tree = BasicTreeWidget()
    tree.show()
    sys.exit(app.exec_())

运行结果:在这里插入图片描述

p79 为树节点添加响应事件

'''

为树节点添加响应事件

'''
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys


class TreeEvent(QMainWindow):
    def __init__(self, parent=None):
        super(TreeEvent, self).__init__(parent)
        self.setWindowTitle('为树节点添加响应事件')
        #创建树控件
        self.tree = QTreeWidget()
        #设置两列
        self.tree.setColumnCount(2)
        #为树控件添加列名
        self.tree.setHeaderLabels(['Key','Value'])
        #创建根节点
        root  = QTreeWidgetItem(self.tree)
        root.setText(0,'root')
        root.setText(1, '0')
        #第一个子节点
        child1 = QTreeWidgetItem(root)
        child1.setText(0,'child1')
        child1.setText(1,'1')
        #第二个子节点
        child2 = QTreeWidgetItem(root)
        child2.setText(0,'child2')
        child2.setText(1,'2')
        #为第二个子节点添加子节点
        child3 = QTreeWidgetItem(child2)
        child3.setText(0,'child3')
        child3.setText(1,'3')
        #点击节点触发事件
        self.tree.clicked.connect(self.onTreeClicked)
        self.setCentralWidget(self.tree)
    def onTreeClicked(self,index):
        #获取当前的单击项
        item = self.tree.currentItem()
        #返回所在行数,从直属父节点算起
        print(index.row())
        #item.text()以列表的形式返回每一行的值
        print('key=%s,value=%s' % (item.text(0),item.text(1)))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    tree = TreeEvent()
    tree.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p80 增加,修改,删除树控件中的节点

'''

添加、修改和删除树控件中的节点

'''

import sys
from PyQt5.QtWidgets import *


class ModifyTree(QWidget):
    def __init__(self, parent=None):
        super(ModifyTree, self).__init__(parent)
        self.setWindowTitle('TreeWidget 例子')

        operatorLayout = QHBoxLayout()
        addBtn = QPushButton('添加节点')
        updateBtn = QPushButton('修改节点')
        deleteBtn = QPushButton('删除节点')

        operatorLayout.addWidget(addBtn)
        operatorLayout.addWidget(updateBtn)
        operatorLayout.addWidget(deleteBtn)

        addBtn.clicked.connect(self.addNode)
        updateBtn.clicked.connect(self.updateNode)
        deleteBtn.clicked.connect(self.deleteNode)

        self.tree = QTreeWidget()

        self.tree.setColumnCount(2)

        self.tree.setHeaderLabels(['Key','Value'])

        root  = QTreeWidgetItem(self.tree)
        root.setText(0,'root')
        root.setText(1, '0')

        child1 = QTreeWidgetItem(root)
        child1.setText(0,'child1')
        child1.setText(1,'1')

        child2 = QTreeWidgetItem(root)
        child2.setText(0,'child2')
        child2.setText(1,'2')

        child3 = QTreeWidgetItem(child2)
        child3.setText(0,'child3')
        child3.setText(1,'3')
        self.tree.clicked.connect(self.onTreeClicked)

        mainLayout = QVBoxLayout(self)
        mainLayout.addLayout(operatorLayout)
        mainLayout.addWidget(self.tree)
        self.setLayout(mainLayout)

    def onTreeClicked(self,index):
        #获取当前点击的节点
        item = self.tree.currentItem()
        print(index.row())
        print('key=%s,value=%s' % (item.text(0),item.text(1)))

    # 添加节点
    def addNode(self):
        print('添加节点')
        item = self.tree.currentItem()
        print(item)
        node = QTreeWidgetItem(item)
        node.setText(0,'新节点')
        node.setText(1,'新值')

    def updateNode(self):
        print('修改节点')
        item = self.tree.currentItem()
        item.setText(0,'修改节点')
        item.setText(1, '值已经被修改')



    def deleteNode(self):
        print('删除节点')
        item = self.tree.currentItem()
        root = self.tree.invisibleRootItem()
        for item in self.tree.selectedItems():
            (item.parent() or root).removeChild(item)





if __name__ == '__main__':
    app = QApplication(sys.argv)
    tree = ModifyTree()
    tree.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p81 QTreeView控件与系统定制模式

p82 选项卡控件

'''

选项卡控件:QTabWidget

可以实现多页面

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class TabWidgetDemo(QTabWidget):
    def __init__(self, parent=None):
        super(TabWidgetDemo, self).__init__(parent)

        self.setWindowTitle("选项卡控件:QTabWidget")
        # 创建用于显示控件的窗口
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tab3 = QWidget()

        #三个控件,添加选项卡页面
        self.addTab(self.tab1,'选项卡1')
        self.addTab(self.tab2,'选项卡2')
        self.addTab(self.tab3,'选项卡3')

        self.tab1UI()
        self.tab2UI()
        self.tab3UI()

    def tab1UI(self):
        #布局
        layout = QFormLayout()
        layout.addRow('姓名',QLineEdit())
        layout.addRow('地址',QLineEdit())
        #修改选项卡名称
        self.setTabText(0,'联系方式')
        self.tab1.setLayout(layout)

    def tab2UI(self):
        layout = QFormLayout()
        sex = QHBoxLayout()
        sex.addWidget(QRadioButton('男'))
        sex.addWidget(QRadioButton('女'))
        layout.addRow(QLabel('性别'),sex)
        layout.addRow('生日',QLineEdit())
        self.setTabText(1,'个人详细信息')
        self.tab2.setLayout(layout)

    def tab3UI(self):
        layout = QHBoxLayout()
        layout.addWidget(QLabel('科目'))
        layout.addWidget(QCheckBox('物理'))
        layout.addWidget(QCheckBox('高数'))
        self.setTabText(2,'教育程度')
        self.tab3.setLayout(layout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = TabWidgetDemo()
    demo.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p83 堆栈窗口控件

'''


堆栈窗口控件(QStackedWidget)


'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class StackedExample(QWidget):
    def __init__(self):
        super(StackedExample, self).__init__()
        self.setGeometry(300, 50, 10, 10)
        self.setWindowTitle('堆栈窗口控件(QStackedWidget)')

        self.list = QListWidget()
        self.list.insertItem(0,'联系方式')
        self.list.insertItem(1,'个人信息')
        self.list.insertItem(2,'教育程度')

        self.stack1 = QWidget()
        self.stack2 = QWidget()
        self.stack3 = QWidget()

        self.tab1UI()
        self.tab2UI()
        self.tab3UI()

        #堆栈窗口控件对象
        self.stack = QStackedWidget()
        self.stack.addWidget(self.stack1)
        self.stack.addWidget(self.stack2)
        self.stack.addWidget(self.stack3)

        hbox = QHBoxLayout()
        hbox.addWidget(self.list)
        hbox.addWidget(self.stack)
        self.setLayout(hbox)

        self.list.currentRowChanged.connect(self.display)
    def tab1UI(self):
        layout = QFormLayout()
        layout.addRow('姓名',QLineEdit())
        layout.addRow('地址',QLineEdit())

        self.stack1.setLayout(layout)

    def tab2UI(self):
        layout = QFormLayout()
        sex = QHBoxLayout()
        sex.addWidget(QRadioButton('男'))
        sex.addWidget(QRadioButton('女'))
        layout.addRow(QLabel('性别'),sex)
        layout.addRow('生日',QLineEdit())

        self.stack2.setLayout(layout)

    def tab3UI(self):
        layout = QHBoxLayout()
        layout.addWidget(QLabel('科目'))
        layout.addWidget(QCheckBox('物理'))
        layout.addWidget(QCheckBox('高数'))

        self.stack3.setLayout(layout)

    def display(self,index):
        self.stack.setCurrentIndex(index)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = StackedExample()
    demo.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p84 停靠控件

'''


停靠控件(QDockWidget)

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class DockDemo(QMainWindow):
    def __init__(self, parent=None):
        super(DockDemo, self).__init__(parent)

        self.setWindowTitle("停靠控件(QDockWidget)")

        layout = QHBoxLayout()
        #创建停靠控件
        self.items = QDockWidget('Dockable',self)
        #在停靠控件中加列表控件
        self.listWidget = QListWidget()
        self.listWidget.addItem('item1')
        self.listWidget.addItem('item2')
        self.listWidget.addItem('item3')

        self.items.setWidget(self.listWidget)

        self.setCentralWidget(QLineEdit())
        # 设置为True则为悬浮状态,False则为停靠状态
        self.items.setFloating(True)
        #第一个参数Qt.RightDockWidgetArea代表默认停靠在主屏幕右方区域
        self.addDockWidget(Qt.RightDockWidgetArea,self.items)




if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = DockDemo()
    demo.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

在这里插入图片描述

p85 容纳多文档的窗口

'''

容纳多文档的窗口

QMdiArea

QMdiSubWindow

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class MultiWindows(QMainWindow):
    count = 0

    def __init__(self, parent=None):
        super(MultiWindows, self).__init__(parent)

        self.setWindowTitle("容纳多文档的窗口")

        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)

        #创建菜单栏,三个选项
        bar = self.menuBar()
        file = bar.addMenu("File")
        file.addAction("New") #新建
        file.addAction("cascade") #重叠
        file.addAction("Tiled") #平铺

        #选项点击触发事件
        file.triggered.connect(self.windowaction)
    def windowaction(self,q):
        print(q.text())
        if q.text() == "New": #新建
            MultiWindows.count = MultiWindows.count + 1
            sub = QMdiSubWindow()
            #在子窗口中添加控件
            sub.setWidget(QTextEdit())
            # sub.setWidget(QPushButton("按钮"))
            sub.setWindowTitle("子窗口" + str(MultiWindows.count))
            #在多文件窗口中添加子窗口
            self.mdi.addSubWindow(sub)
            sub.show()
        elif q.text() == "cascade": #重叠
            self.mdi.cascadeSubWindows()
        elif q.text() == "Tiled": #展开
            self.mdi.tileSubWindows()



if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = MultiWindows()
    demo.show()
    sys.exit(app.exec_())

运行结果: 子窗口可以在主窗口中移动

在这里插入图片描述

p86 滚动条控件

'''

滚动条控件(QScrollBar)

QScrollBar的作用

1. 通过滚动条值的变化控制其他控件状态的变化
2. 通过滚动条值的变化控制控件位置的变化

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class ScrollBar(QWidget):
    def __init__(self):
        super(ScrollBar, self).__init__()
        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout()
        #标签控件
        self.label = QLabel('拖动滚动条去改变文字颜色')

        hbox.addWidget(self.label)
        #滚动条控件
        self.scrollbar1 = QScrollBar()
        #设置滚动条的最大值
        self.scrollbar1.setMaximum(255)
        #滚动条滑动触发事件
        self.scrollbar1.sliderMoved.connect(self.sliderMoved)

        self.scrollbar2 = QScrollBar()
        self.scrollbar2.setMaximum(255)
        self.scrollbar2.sliderMoved.connect(self.sliderMoved)

        self.scrollbar3 = QScrollBar()
        self.scrollbar3.setMaximum(255)
        self.scrollbar3.sliderMoved.connect(self.sliderMoved)

        self.scrollbar4 = QScrollBar()
        self.scrollbar4.setMaximum(255)
        self.scrollbar4.sliderMoved.connect(self.sliderMoved1)
        hbox.addWidget(self.scrollbar1)
        hbox.addWidget(self.scrollbar2)
        hbox.addWidget(self.scrollbar3)
        hbox.addWidget(self.scrollbar4)
        self.setGeometry(300,300,300,200)

        self.setLayout(hbox)

        self.y = self.label.pos().y()

    def sliderMoved(self):
        print(self.scrollbar1.value(),self.scrollbar2.value(),self.scrollbar3.value())
        palette = QPalette()
        c = QColor(self.scrollbar1.value(),self.scrollbar2.value(),self.scrollbar3.value(),255)
        #设置label字体颜色
        palette.setColor(QPalette.Foreground,c)
        self.label.setPalette(palette)
    def sliderMoved1(self):
        #移动label的位置
        self.label.move(self.label.x(),self.y + self.scrollbar4.value())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = ScrollBar()
    demo.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p87 动态显示当前时间

'''

动态显示当前时间

QTimer:定时器
QThread

多线程:用于同时完成多个任务




'''

from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QListWidget, QGridLayout, QLabel
from PyQt5.QtCore import QTimer, QDateTime
import sys


class ShowTime(QWidget):

    def __init__(self, parent=None):
        super(ShowTime, self).__init__(parent)
        self.setWindowTitle("动态显示当前时间")
        #放置标签用于显示时间
        self.label = QLabel('显示当前时间')
        self.startBtn = QPushButton('开始')
        self.endBtn = QPushButton('结束')
        layout= QGridLayout()
        #创建定时器对象
        self.timer = QTimer()
        #到时间时触发事件
        self.timer.timeout.connect(self.showTime)

        layout.addWidget(self.label,0,0,1,2)
        layout.addWidget(self.startBtn,1,0)
        layout.addWidget(self.endBtn,1,1)

        self.startBtn.clicked.connect(self.startTimer)
        self.endBtn.clicked.connect(self.endTimer)

        self.setLayout(layout)

    def showTime(self):
        #得到当前时间
        time = QDateTime.currentDateTime()
        #转换时间格式
        timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd")
        self.label.setText(timeDisplay)

    def startTimer(self):
        #开始定时器,定时为1000毫秒,即1秒
        self.timer.start(1000)
        self.startBtn.setEnabled(False) #开始按钮设为不可用状态
        self.endBtn.setEnabled(True)

    def endTimer(self):
        self.timer.stop()
        self.startBtn.setEnabled(True)
        self.endBtn.setEnabled(False) #结束按钮设为不可用状态

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = ShowTime()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p88 让窗口定时关闭

'''

让程序定时关闭

QTimer.singleShot

'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

if __name__ == '__main__':
    app = QApplication(sys.argv)
    label = QLabel('<font color=red size=140><b>Hello World,窗口在5秒后自动关闭!</b></font>')
    #将窗口标题栏等控件隐藏
    label.setWindowFlags(Qt.SplashScreen | Qt.FramelessWindowHint)
    label.show()
    #5秒到后单次执行app.quit
    QTimer.singleShot(5000,app.quit)
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p89 使用线程类编写计数器

'''

使用线程类(QThread)编写计数器


QThread

def run(self):
   while True:
       self.sleep(1)
       if sec == 5:
           break;

QLCDNumber



WorkThread(QThread)
用到自定义信号

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

sec = 0

class WorkThread(QThread):
    timer = pyqtSignal()   # 每隔1秒发送一次信号
    end = pyqtSignal()     # 计数完成后发送一次信号
    def run(self):
        while True:
            self.sleep(1)  # 休眠1秒
            #计数到5秒退出
            if sec == 5:
                self.end.emit()   # 发送end信号
                break
            self.timer.emit()   # 发送timer信号

class Counter(QWidget):

    def __init__(self, parent=None):
        super(Counter, self).__init__(parent)

        self.setWindowTitle("使用线程类(QThread)编写计数器")
        self.resize(300, 120)

        layout = QVBoxLayout()

        #数码管控件
        self.lcdNumber = QLCDNumber()
        layout.addWidget(self.lcdNumber)

        button = QPushButton('开始计数')
        layout.addWidget(button)

        self.workThread = WorkThread()

        self.workThread.timer.connect(self.countTime)
        self.workThread.end.connect(self.end)
        button.clicked.connect(self.work)

        self.setLayout(layout)

    def countTime(self):
        global sec
        sec += 1
        self.lcdNumber.display(sec)

    def end(self):
        #消息对话框
        #参数依次为:主窗口,对话框标题,对话框文本内容,对话框按钮
        QMessageBox.information(self,'消息','计数结束',QMessageBox.Ok)

    def work(self):
        self.workThread.start()




if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Counter()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p90 用web浏览器控件显示网页

'''

用Web浏览器控件(QWebEngineView)显示网页

PyQt5和Web的交互技术

同时使用Python和Web开发程序,混合开发

Python+JavaScript+HTML5+CSS

QWebEngineView

'''

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
import sys

class WebEngineView(QMainWindow):

    def __init__(self ):
        super(WebEngineView, self).__init__()
        self.setWindowTitle('打开外部网页例子')
        self.setGeometry(5, 30, 1355, 730)
        #网页显示控件
        self.browser = QWebEngineView()
        #指定URL
        # self.browser.load(QUrl('https://www.jd.com')) #京东商城
        self.browser.load(QUrl("https://www.baidu.com"))
        self.setCentralWidget(self.browser)


if __name__ == '__main__':
	app = QApplication(sys.argv)
	win = WebEngineView()
	win.show()
	sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p91 装载本地Web页面

'''

装载本地Web页面

'''

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
import sys
import os
class WebEngineView(QMainWindow):

    def __init__(self ):
        super(WebEngineView, self).__init__()
        self.setWindowTitle('装载本地Web页面')
        self.setGeometry(5, 30, 1355, 730)
        url = os.getcwd() + '/test.html'
        self.browser = QWebEngineView()
        #加载本地HTML文件
        self.browser.load(QUrl.fromLocalFile(url))

        self.setCentralWidget(self.browser)


        print(os.getcwd())
if __name__ == '__main__':
	app = QApplication(sys.argv)
	win = WebEngineView()
	win.show()
	sys.exit(app.exec_())

运行结果:

在这里插入图片描述

在这里插入图片描述

p92 显示嵌入Web页面

'''

显示嵌入Web页面

'''

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
import sys
import os
class InnerHTML(QMainWindow):

    def __init__(self ):
        super(InnerHTML, self).__init__()
        self.setWindowTitle('显示嵌入Web页面')
        self.setGeometry(5, 30, 1355, 730)

        self.browser = QWebEngineView()
        #直接嵌入HTML代码
        self.browser.setHtml('''
        
        <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试页面</title>
</head>
<body>
    <h1>Hello PyQt5</h1>
    <h2>Hello PyQt5</h2>
    <h3>Hello PyQt5</h3>
    <h4>Hello PyQt5</h4>
</body>
</html>
        ''')
        self.setCentralWidget(self.browser)

if __name__ == '__main__':
	app = QApplication(sys.argv)
	win = InnerHTML()
	win.show()
	sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p93 PyQt5调用JavaScript代码,并返回值

'''

PyQt5调用JavaScript代码


PyQt5和JavaScript交互

什么叫交互

PyQt5 <-> JavaScript




'''


from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
import sys
import os


class PyQtCallJS(QWidget):

    def __init__(self):
        super(PyQtCallJS, self).__init__()
        self.setWindowTitle('PyQt5调用JavaScript')
        self.setGeometry(5, 30, 1355, 730)
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)
        self.browser = QWebEngineView()

        url = os.getcwd() + '/tt.html'
        self.browser.load(QUrl.fromLocalFile(url))

        self.layout.addWidget(self.browser)

        button = QPushButton('设置全名')
        button.clicked.connect(self.fullname)
        self.layout.addWidget(button)

    def js_callback(self,result):
        print(result)
    def fullname(self):
        self.value = 'hello world'
        self.browser.page().runJavaScript('fullname("' + self.value + '");',self.js_callback)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = PyQtCallJS()
    win.show()
    sys.exit(app.exec_())



运行结果:

在这里插入图片描述

p94 JavaScript调用PythonAPI计算阶乘


p95 绝对布局

'''
绝对布局

'''


import sys,math
from PyQt5.QtWidgets import *


class AbsoluteLayout(QWidget) :
    def __init__(self):
        super(AbsoluteLayout,self).__init__()
        self.setWindowTitle("绝对布局")
        
        #采用move决定控件的摆放位置
        self.label1 = QLabel('欢迎',self)
        self.label1.move(15,20)

        self.label2 = QLabel('学习',self)
        self.label2.move(35,40)

        self.label3 = QLabel('PyQt5',self)
        self.label3.move(55,80)





if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = AbsoluteLayout()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p96 水平盒布局

'''

水平盒布局(QHBoxLayout)

通过 addWidget(object):直接添加控件对象object

'''

import sys,math
from PyQt5.QtWidgets import *


class HBoxLayout(QWidget) :
    def __init__(self):
        super(HBoxLayout,self).__init__()
        self.setWindowTitle("水平盒布局")

        hlayout = QHBoxLayout()
        hlayout.addWidget(QPushButton('按钮1'))
        hlayout.addWidget(QPushButton('按钮2'))
        hlayout.addWidget(QPushButton('按钮3'))
        hlayout.addWidget(QPushButton('按钮4'))
        hlayout.addWidget(QPushButton('按钮5'))
        #设置控件之间的间距
        hlayout.setSpacing(20)
        self.setLayout(hlayout)






if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = HBoxLayout()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p97 设置控件的对齐方式

'''

设置控件的对齐方式

addWidget(object,distance,align):
        object:控件对象
        distance:控件占据空间
        align:对齐方式

'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt


class HBoxLayoutAlign(QWidget) :
    def __init__(self):
        super(HBoxLayoutAlign,self).__init__()
        self.setWindowTitle("水平盒布局")

        hlayout = QHBoxLayout()
        hlayout.addWidget(QPushButton('按钮1'),2,Qt.AlignLeft | Qt.AlignTop) #左侧顶端对其
        hlayout.addWidget(QPushButton('按钮2'),4,Qt.AlignLeft | Qt.AlignTop)
        hlayout.addWidget(QPushButton('按钮3'),1,Qt.AlignLeft | Qt.AlignTop)
        hlayout.addWidget(QPushButton('按钮4'),1,Qt.AlignLeft | Qt.AlignBottom)#左侧底部对其
        hlayout.addWidget(QPushButton('按钮5'),1,Qt.AlignLeft | Qt.AlignBottom)
        hlayout.setSpacing(40)
        self.setLayout(hlayout)






if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = HBoxLayoutAlign()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p98 垂直盒布局

'''

垂直盒布局(QBoxLayout)



'''

import sys,math
from PyQt5.QtWidgets import *


class VBoxLayout(QWidget) :
    def __init__(self):
        super(VBoxLayout,self).__init__()
        self.setWindowTitle("垂直盒布局")

        layout = QVBoxLayout()
        layout.addWidget(QPushButton('按钮1'))
        layout.addWidget(QPushButton('按钮2'))
        layout.addWidget(QPushButton('按钮3'))
        layout.addWidget(QPushButton('按钮4'))
        layout.addWidget(QPushButton('按钮5'))

        self.setLayout(layout)






if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = VBoxLayout()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p99 设置布局的伸缩量

'''

设置伸缩量(addStretch)



'''

import sys,math
from PyQt5.QtWidgets import *


class Stretch(QWidget) :
    def __init__(self):
        super(Stretch,self).__init__()
        self.setWindowTitle("设置伸缩量")
        btn1 = QPushButton(self)
        btn2 = QPushButton(self)
        btn3 = QPushButton(self)
        btn1.setText("按钮1")
        btn2.setText("按钮2")
        btn3.setText("按钮3")

        layout = QHBoxLayout()
        #设置伸缩量,即按钮之间距离1:2:3
        #若伸缩量为0,先将其放置,页面其他的地方再放置其他控件
        layout.addStretch(1)
        layout.addWidget(btn1)

        layout.addStretch(2)
        layout.addWidget(btn2)
        layout.addStretch(3)
        layout.addWidget(btn3)

        self.setLayout(layout)







if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Stretch()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p100 让按钮永远在窗口的右下角

'''

让按钮永远在窗口右下角


'''

import sys,math
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt


class RightBottomButton(QWidget) :
    def __init__(self):
        super(RightBottomButton,self).__init__()
        self.setWindowTitle("让按钮永远在右下角")
        self.resize(400,300)

        okButton = QPushButton("确定")
        cancelButton = QPushButton("取消")

        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(okButton)
        hbox.addWidget(cancelButton)
       
        vbox = QVBoxLayout()
        btn1 = QPushButton("按钮1")
        btn2 = QPushButton("按钮2")
        btn3 = QPushButton("按钮3")

        vbox.addStretch(0)
        vbox.addWidget(btn1)
        vbox.addWidget(btn2)
        vbox.addWidget(btn3)
        vbox.addStretch(1)
        vbox.addLayout(hbox)

        self.setLayout(vbox)





if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = RightBottomButton()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p101 栅格布局:用循环方式实现计算器UI

'''

栅格布局:实现计算器UI
Grid中addWidget(object,x,y,row,col):
		object:控件对象
		x,y:行列坐标
		col,row:对象占据的行列数目
'''

import sys,math
from PyQt5.QtWidgets import *


class Calc(QWidget) :
    def __init__(self):
        super(Calc,self).__init__()
        self.setWindowTitle("栅格布局")

        grid = QGridLayout()
        self.setLayout(grid)

        names = ['Cls','Back','','Close',
                 '7','8','9','/',
                 '4','5','6','*',
                 '1','2','3','-',
                 '0','.','=','+']
        #5行4列,获取坐标
        positions = [(i,j) for i in range(5) for j in range(4)]
        print(positions)

        for position,name in zip(positions,names):
            if name == '':
                continue
            button = QPushButton(name)
           # print(position)
            #取出坐标,在元组前加* 可以取出里面的元素
            grid.addWidget(button,*position)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Calc()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p102 栅格布局:进行表单UI设计

'''

栅格布局:表单设计

'''

import sys,math
from PyQt5.QtWidgets import *


class GridForm(QWidget) :
    def __init__(self):
        super(GridForm,self).__init__()
        self.setWindowTitle("栅格布局:表单设计")

        titleLabel = QLabel('标题')
        authorLabel = QLabel('作者')
        contentLabel = QLabel('内容')

        titleEdit = QLineEdit()
        authorEdit = QLineEdit()
        contentEdit = QTextEdit()

        grid = QGridLayout()
        grid.setSpacing(10)

        grid.addWidget(titleLabel,1,0)
        grid.addWidget(titleEdit,1,1)

        grid.addWidget(authorLabel,2,0)
        grid.addWidget(authorEdit,2,1)

        grid.addWidget(contentLabel,3,0)
        grid.addWidget(contentEdit,3,1,5,1)

        self.setLayout(grid)
        self.resize(350,300)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = GridForm()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p103 表单布局

'''

表单布局(QFormLayout)
通过addRow()方法
'''

import sys,math
from PyQt5.QtWidgets import *


class FormForm(QWidget) :
    def __init__(self):
        super(FormForm,self).__init__()
        self.setWindowTitle("表单布局")
        self.resize(350,300)

        formLayout = QFormLayout()

        titleLabel = QLabel('标题')
        authorLabel = QLabel('作者')
        contentLabel = QLabel('内容')

        titleEdit = QLineEdit()
        authorEdit = QLineEdit()
        contentEdit = QTextEdit()

        formLayout.addRow(titleLabel,titleEdit)
        formLayout.addRow(authorLabel,authorEdit)
        formLayout.addRow(contentLabel,contentEdit)

        self.setLayout(formLayout)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = FormForm()
    main.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p104 拖动控件之间的边界

'''

拖动控件之间的边界(QSplitter)
可以左右拖动控件在页面的位置
'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class Splitter(QWidget):
    def __init__(self):
        super(Splitter, self).__init__()
        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout(self)
        self.setWindowTitle('QSplitter 例子')
        self.setGeometry(300, 300, 300, 200)

        topleft = QFrame()
        #设置样式
        topleft.setFrameShape(QFrame.StyledPanel)

        bottom = QFrame()
        bottom.setFrameShape(QFrame.StyledPanel)

        splitter1 = QSplitter(Qt.Horizontal) #水平空指边界
        textedit = QTextEdit()
        splitter1.addWidget(topleft)
        splitter1.addWidget(textedit)
        splitter1.setSizes([200,100])

        splitter2 = QSplitter(Qt.Vertical) #垂直空指边界
        splitter2.addWidget(splitter1)
        splitter2.addWidget(bottom)


        hbox.addWidget(splitter2)
        self.setLayout(hbox)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Splitter()
    demo.show()
    sys.exit(app.exec_())


运行结果:

在这里插入图片描述

p105 信号与槽基础

'''

信号(Signal)与槽(Slot)

'''
from PyQt5.QtWidgets import *
import sys

class SigalSlotDemo(QWidget):
    def __init__(self):
        super(SigalSlotDemo,self).__init__()
        self.initUI()

    def onClick(self):
        self.btn.setText("信号已经发出")
        self.btn.setStyleSheet("QPushButton(max-width:200px;min-width:200px")

    def initUI(self):
        self.setGeometry(300, 300, 500, 400)
        self.setWindowTitle('信号(Signal)与槽(Slot)')
        self.btn = QPushButton('我的按钮',self)
        self.btn.clicked.connect(self.onClick)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = SigalSlotDemo()
    gui.show()
    sys.exit(app.exec_())

p106 自定义信号实现对象之间的通信

'''

自定义信号

pyqtSignal()

'''

from PyQt5.QtCore import *
class MyTypeSignal(QObject):
    # 定义一个信号
    sendmsg = pyqtSignal(object)
	
    #也可以定义传递多个参数的信号
    # 发送3个参数的信号
    sendmsg1 = pyqtSignal(str,int,int)

    def run(self):
        #通过emit触发信号
        self.sendmsg.emit('Hello PyQt5')

    def run1(self):
        self.sendmsg1.emit("hello",3,4)


class MySlot(QObject):
    def get(self,msg):
        print("信息:" + msg)
    def get1(self,msg,a,b):
        print(msg)
        print(a+b)


if __name__ == '__main__':
    send = MyTypeSignal()
    slot = MySlot()

    send.sendmsg.connect(slot.get)
    send.sendmsg1.connect(slot.get1)

    #调用run()发送信号
    send.run()
    send.run1()

    send.sendmsg.disconnect(slot.get)
    send.run()

运行结果:

在这里插入图片描述

p107 可以传递多个参数的信号

p108 为类添加多个信号

'''
为类添加多个信号
pyqtSignal()创建信号对象
'''

from PyQt5.QtCore import *

class MultiSignal(QObject):

    signal1 = pyqtSignal()

    signal2 = pyqtSignal(int)

    signal3 = pyqtSignal(int, str)

    signal4 = pyqtSignal(list)

    signal5 = pyqtSignal(dict)

    # 声明一个重载版本的信号,也就是槽函数的参数可以是int和str类型,也可以只有一个str类型的参数
    signal6 = pyqtSignal([int,str],[str]) #这个信号参数可选

    def __init__(self):
        super(MultiSignal,self).__init__()
        self.signal1.connect(self.signalCall1)
        self.signal2.connect(self.signalCall2)
        self.signal3.connect(self.signalCall3)
        self.signal4.connect(self.signalCall4)
        self.signal5.connect(self.signalCall5)
        self.signal6[str].connect(self.signalCall6Overload)
        self.signal6[int,str].connect(self.signalCall6)

        self.signal1.emit()
        self.signal2.emit(10)
        self.signal3.emit(1,"hello world")
        self.signal4.emit([1,2,3,4,5,6])
        self.signal5.emit({"name":"Bill","age":30})
        self.signal6[str].emit("test")
        self.signal6[int,str].emit(100,"mytest")
    def signalCall1(self):
        print("signal1 emit")

    def signalCall2(self,val):
        print("signal2 emit,value:", val)

    def signalCall3(self,val,text):
        print("signal3 emit,value:", val,text)

    def signalCall4(self,val):
        print("signal4 emit,value:", val)

    def signalCall5(self,val):
        print("signal5 emit,value:", val)

    def signalCall6(self,val,text):
        print("signal6 emit,value:", val,text)

    def signalCall6Overload(self,val):
        print("signal6 overload emit,value:", val)

if __name__ == '__main__':
    multiSignal = MultiSignal()

运行结果:

在这里插入图片描述

p109 信号与槽的N对N连接与断开

'''

信号槽N对N连接与断开连接:

    一个信号对应多个槽
    一个槽应对多个信号

'''

from PyQt5.QtCore import *

class NNSignal(QObject):
    signal1 = pyqtSignal()
    signal2 = pyqtSignal(int)
    signal3 = pyqtSignal()
    def __init__(self):
        super(NNSignal,self).__init__()
		
        #一个信号对应多个槽函数时,按照绑定的循序先后执行函数
        self.signal1.connect(self.call1)
        self.signal1.connect(self.call11)

        self.signal3.connect(self.call1)
        self.signal1.emit()
        self.signal3.emit()

        self.signal2.connect(self.signal1)

        self.signal2.emit(2)   # 触发了信号1

        #接触关联
        self.signal1.disconnect(self.call1)
        self.signal1.disconnect(self.call11)
        self.signal2.disconnect(self.signal1)

        self.signal1.connect(self.call1)
        self.signal2.connect(self.call2)

        self.signal1.emit()
        self.signal2.emit(100)

    def call1(self):
        print("call1 emit")

    def call11(self):
        print("call11 emit")

    def call2(self,val):
        print("call2 emit:",val)
if __name__ == '__main__':
    nnSignal = NNSignal()

运行结果:

在这里插入图片描述

p110 为窗口添加信号

'''

为窗口类添加信号

'''
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys

class WinSignal(QWidget):
    #创建信号对象
    button_clicked_signal = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.setWindowTitle("为窗口类添加信号")
        self.resize(300,100)


        btn = QPushButton('关闭窗口',self)
        #按钮点击触发事件
        btn.clicked.connect(self.btn_clicked)
        #信号与槽关联
        self.button_clicked_signal.connect(self.btn_close)

    def btn_clicked(self):
        #发射信号button_clicked_signal
        self.button_clicked_signal.emit()

    def btn_close(self):
        #窗口关闭
        self.close()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = WinSignal()
    example.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p111 多线程更新UI数据

'''

多线程更新UI数据(在两个线程中传递数据)

'''

from PyQt5.QtCore import QThread ,  pyqtSignal,  QDateTime
from PyQt5.QtWidgets import QApplication,  QDialog,  QLineEdit
import time
import sys

#子线程获取当前时间,主线程显示窗口
class BackendThread(QThread):
    update_date = pyqtSignal(str)

    def run(self):
        while True:
            #获取当前时间
            data = QDateTime.currentDateTime()
            #转换时间格式 年-月-日 小时:分钟:秒
            currentTime = data.toString("yyyy-MM-dd hh:mm:ss")
            self.update_date.emit(str(currentTime))
            time.sleep(1)
class ThreadUpdateUI(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.setWindowTitle('多线程更新UI数据')
        self.resize(400,100)
        self.input = QLineEdit(self)
        self.input.resize(400,100)

        self.initUI()
    def initUI(self):
        self.backend = BackendThread()
        self.backend.update_date.connect(self.handleDisplay)
        #启动线程
        self.backend.start()

    def handleDisplay(self,data):
        #显示时间
        self.input.setText(data)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = ThreadUpdateUI()
    example.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p112 信号与槽自动连接

'''
信号与槽自动连接

on_objectname_signalname

on_okButton_clicked

'''

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication ,QWidget ,QHBoxLayout , QPushButton
import sys

class AutoSignalSlot(QWidget):
    def __init__(self):
        super(AutoSignalSlot,self).__init__()
        self.okButton = QPushButton("ok",self)
        #设置对象名
        self.okButton.setObjectName("okButton")
        self.okButton1 = QPushButton("cancel",self)
        self.okButton1.setObjectName("cancelButton")
        layout = QHBoxLayout()
        layout.addWidget(self.okButton)
        layout.addWidget(self.okButton1)
        self.setLayout(layout)
        #用槽函数名称自动连接信号与槽  槽函数命名格式为:on_objectname_signalname
        QtCore.QMetaObject.connectSlotsByName(self)
        #self.okButton.clicked.connect(self.on_okButton_clicked)
    #采用装饰器标注此函数为槽函数
    @QtCore.pyqtSlot()
    def on_okButton_clicked(self):
        print("点击了ok按钮")

    @QtCore.pyqtSlot()
    def on_cancelButton_clicked(self):
        print("点击了cancel按钮")
if __name__ == '__main__':
    app = QApplication(sys.argv)
    example = AutoSignalSlot()
    example.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p113 用Lambda 表达式为槽函数传递参数

'''

使用Lambda表达式为槽函数传递参数

Lambda表达式:匿名函数,也就是没有名字的函数

fun = lambda :print("hello world")

fun()

fun1 = lambda x,y:print(x,y)
fun1("a","b")


'''

from PyQt5.QtWidgets import *
import sys

class LambdaSlotArg(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("使用Lambda表达式为槽函数传递参数")

        button1 = QPushButton("按钮1")
        button2 = QPushButton("按钮2")
        ok = 100
        #使用Lambda表达式为槽函数传递参数
        button1.clicked.connect(lambda :self.onButtonClick(10,ok))
        button2.clicked.connect(lambda :self.onButtonClick(ok,-20))
        button1.clicked.connect(lambda :QMessageBox.information(self,"结果","单击了button1"))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)
        mainFrame = QWidget()
        mainFrame.setLayout(layout)
        self.setCentralWidget(mainFrame)
    def onButtonClick(self,m,n):
        print("m + n =",m + n )
        QMessageBox.information(self,"结果",str(m+n))
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = LambdaSlotArg()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p114 用partial对象为槽函数传递参数

'''

使用Partial对象为槽函数传递参数


'''

from PyQt5.QtWidgets import *
import sys
from functools import partial

class PartialSlotArg(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("使用Partial表达式为槽函数传递参数")

        button1 = QPushButton("按钮1")
        button2 = QPushButton("按钮2")
        x = 20
        y = -123
        button1.clicked.connect(partial(self.onButtonClick,10,20))
        button2.clicked.connect(partial(self.onButtonClick, x, y))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)
        mainFrame = QWidget()
        mainFrame.setLayout(layout)
        self.setCentralWidget(mainFrame)
    def onButtonClick(self,m,n):
        print("m + n =",m + n )
        QMessageBox.information(self,"结果",str(m+n))
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = PartialSlotArg()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p115 override(覆盖)槽函数

'''

Override(覆盖)槽函数

'''

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

class OverrideSlot(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Override(覆盖)槽函数")
    #键盘按下事件
    def keyPressEvent(self, e):
        #按下 'Esc'键,窗口关闭
        if e.key() == Qt.Key_Escape:
            self.close()
        #按下‘Alt’键,窗口标题改变
        elif e.key() == Qt.Key_Alt:
            self.setWindowTitle("按下Alt键")



if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = OverrideSlot()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p116 多窗口交互,不使用信号与槽

"""DateDialog:"""
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class DateDialog(QDialog):
    def __init__(self,parent=None):
        super(DateDialog,self).__init__(parent)
        self.setWindowTitle("DateDialog")

        layout = QVBoxLayout(self)
        #日期编辑控件
        self.datetime = QDateTimeEdit(self)
        #允许弹出日历
        self.datetime.setCalendarPopup(True)
        #显示当前时间
        self.datetime.setDateTime(QDateTime.currentDateTime())

        layout.addWidget(self.datetime)
        #放置两个按钮OK与Cancel,并采用水平布局
        buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,Qt.Horizontal,self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        layout.addWidget(buttons)
    #获取日期
    def dateTime(self):
        return self.datetime.dateTime()

    @staticmethod
    def getDateTime(parent = None):
        dialog = DateDialog(parent)
        result = dialog.exec()
        date = dialog.dateTime()
        return (date.date(),date.time(),result == QDialog.Accepted)


'''

多窗口交互(1):不使用信号与槽

Win1

Win2

'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from DateDialog import DateDialog

class MultiWindow1(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("多窗口交互(1):不使用信号与槽")

        self.lineEdit = QLineEdit(self)
        self.button1 = QPushButton('弹出对话框1')
        self.button1.clicked.connect(self.onButton1Click)

        self.button2 = QPushButton('弹出对话框2')
        self.button2.clicked.connect(self.onButton2Click)

        gridLayout = QGridLayout()
        gridLayout.addWidget(self.lineEdit)
        gridLayout.addWidget(self.button1)
        gridLayout.addWidget(self.button2)

        self.setLayout(gridLayout)

    def onButton1Click(self):
        dialog = DateDialog(self)
        result = dialog.exec()
        date = dialog.dateTime()
        self.lineEdit.setText(date.date().toString())
        dialog.destroy()

    def onButton2Click(self):
        date,time,result = DateDialog.getDateTime()
        self.lineEdit.setText(date.toString())
        if result == QDialog.Accepted:
            print('点击确定按钮')
        else:
            print('单击取消按钮')
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = MultiWindow1()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p117 多窗口交互,使用信号与槽

"""NewDialog"""
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

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


class NewDateDialog(QDialog):
    Signal_OneParameter = pyqtSignal(str)

    def __init__(self, parent=None):
        super(NewDateDialog, self).__init__(parent)
        self.setWindowTitle('子窗口:用来发射信号')

        # 在布局中添加部件
        layout = QVBoxLayout(self)

        self.label = QLabel(self)
        self.label.setText('前者发射内置信号\n后者发射自定义信号')

        self.datetime_inner = QDateTimeEdit(self)
        self.datetime_inner.setCalendarPopup(True)
        self.datetime_inner.setDateTime(QDateTime.currentDateTime())

        self.datetime_emit = QDateTimeEdit(self)
        self.datetime_emit.setCalendarPopup(True)
        self.datetime_emit.setDateTime(QDateTime.currentDateTime())

        layout.addWidget(self.label)
        layout.addWidget(self.datetime_inner)
        layout.addWidget(self.datetime_emit)

        # 使用两个button(ok和cancel)分别连接accept()和reject()槽函数
        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addWidget(buttons)

        self.datetime_emit.dateTimeChanged.connect(self.emit_signal)

    def emit_signal(self):
        date_str = self.datetime_emit.dateTime().toString()
        self.Signal_OneParameter.emit(date_str)


'''

多窗口交互(2):使用信号与槽

如果一个窗口A与另一个窗口B交互,那么A尽量不要直接访问B窗口中的控件,
应该访问B窗口中的信号,并指定与信号绑定的槽函数

例:如果A直接访问B窗口的控件,一旦B窗口控件发生改变,那么A和B的代码都需要变化

如果A访问的是B中的信号,那么B中的控件发生了改变,只需要修改B中的代码即可



'''

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from NewDateDialog import NewDateDialog

class MultiWindow2(QWidget):
    def __init__(self, parent=None):
        super(MultiWindow2, self).__init__(parent)
        self.resize(400, 90)
        self.setWindowTitle('多窗口交互(2):使用信号与槽')

        self.open_btn = QPushButton('获取时间')
        self.lineEdit_inner = QLineEdit(self)
        self.lineEdit_emit = QLineEdit(self)
        self.open_btn.clicked.connect(self.openDialog)

        self.lineEdit_inner.setText('接收子窗口内置信号的时间')
        self.lineEdit_emit.setText('接收子窗口自定义信号的时间')

        grid = QGridLayout()
        grid.addWidget(self.lineEdit_inner)
        grid.addWidget(self.lineEdit_emit)

        grid.addWidget(self.open_btn)
        self.setLayout(grid)

    def openDialog(self):
        dialog = NewDateDialog(self)
        # 连接子窗口的内置信号与主窗口的槽函数
        dialog.datetime_inner.dateTimeChanged.connect(self.deal_inner_slot)
        # 连接子窗口的自定义信号与主窗口的槽函数
        dialog.Signal_OneParameter.connect(self.deal_emit_slot)
        dialog.show()

    def deal_inner_slot(self, date):
        self.lineEdit_inner.setText(date.toString())


    def deal_emit_slot(self, dateStr):
        self.lineEdit_emit.setText(dateStr)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = MultiWindow2()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p118 设置窗口风格

'''

窗口、绘图与特效:设置窗口风格

设置窗口中控件的风格

QApplication.setStyle(...)

可以同过:QStyleFactory.keys() 来查看窗口的所有风格
'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import QtCore
from PyQt5.QtGui  import *

class WindowStyle(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('设置窗口风格')
        horizontalLayout = QHBoxLayout()
        self.styleLabel = QLabel('设置窗口风格:')
        self.styleComboBox = QComboBox()
        self.styleComboBox.addItems(QStyleFactory.keys())

        # 获取当前窗口的风格
        print(QApplication.style().objectName())
        #查找搜索当前风格
        index = self.styleComboBox.findText(QApplication.style().objectName(),QtCore.Qt.MatchFixedString)
        #设置当前索引
        self.styleComboBox.setCurrentIndex(index)
        #改变下拉列表的值触发事件
        self.styleComboBox.activated[str].connect(self.handleStyleChanged)
        horizontalLayout.addWidget(self.styleLabel)
        horizontalLayout.addWidget(self.styleComboBox)
        self.setLayout(horizontalLayout)
    def handleStyleChanged(self,style):
        #设置风格
        QApplication.setStyle(style)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = WindowStyle()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p119 设置窗口样式

'''

设置窗口样式(主要是窗口边框、标题栏以及窗口本身的样式)

'''

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

class WindowPattern(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(500,260)
        self.setWindowTitle('设置窗口的样式')
        #设置窗口样式
        self.setWindowFlags(Qt.WindowMaximizeButtonHint | Qt.WindowStaysOnTopHint ) 
        self.setObjectName("MainWindow")
        #设置背景图
        self.setStyleSheet("#MainWindow{border-image:url(images/python.jpg);}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = WindowPattern()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p120 用代码设置窗口的最大化和最小化

'''
用代码控制窗口的最大化和最小化

'''


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


### 自定义窗口类
class WindowMaxMin(QWidget):


    ###  构造函数
    def __init__(self, parent=None):
        '''构造函数'''
        # 调用父类构造函数
        super(WindowMaxMin, self).__init__(parent)
        self.resize(300,400)
        self.setWindowTitle("用代码控制窗口的最大化和最小化")
        self.setWindowFlags(Qt.WindowMaximizeButtonHint)

        layout = QVBoxLayout()
        maxButton1 = QPushButton()
        maxButton1.setText('窗口最大化1')
        maxButton1.clicked.connect(self.maximized1)


        maxButton2 = QPushButton()
        maxButton2.setText('窗口最大化2')
        #最大化
        maxButton2.clicked.connect(self.showMaximized)

        minButton = QPushButton()
        minButton.setText('窗口最小化')
        #最小化
        minButton.clicked.connect(self.showMinimized)


        layout.addWidget(maxButton1)
        layout.addWidget(maxButton2)
        layout.addWidget(minButton)
        self.setLayout(layout)



    def maximized1(self):
        #桌面对象
        desktop = QApplication.desktop()
        # 获取桌面可用尺寸
        rect = desktop.availableGeometry()

        self.setGeometry(rect)



if __name__ == "__main__":

    app = QApplication(sys.argv)

    window = WindowMaxMin()
    window.show()
    # 应用程序事件循环
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p121 项目实战:实现绘图应用

'''

项目实战:实现绘图应用

需要解决3个核心内容
1. 如何绘图

在paintEvent方法中绘图,通过调用update方法触发painEvent的调用


2. 在哪里绘图

在白色背景的QPixmap对象中绘图

3. 如何通过移动鼠标进行绘图

鼠标拥有3个事件:
(1)鼠标按下:mousePressEvent
(2)鼠标移动:mouseMoveEvent
(3)鼠标抬起:mouseReleaseEvent

4.保存图片:
img=QPixmap.toImage():将画布转换为图片
img.save(filename):将图片保存,filename为存储路径
'''

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QPixmap,QColor,QFont
from PyQt5.QtCore import Qt, QPoint
import pyqtgraph as pg
import pyqtgraph.exporters

class Drawing(QWidget):
    def __init__(self, parent=None):
        super(Drawing, self).__init__(parent)
        self.setWindowTitle("绘图应用")
        self.pix = QPixmap()
        self.lastPoint = QPoint()
        self.endPoint = QPoint()
        self.initUi()
    def initUi(self):

        self.resize(400, 400)
        # 画布大小为400*400,背景为黑色
        self.pix = QPixmap(400, 400)
        self.pix.fill(Qt.black)


    def paintEvent(self, event):
        #画笔
        pp = QPainter(self.pix)
        #设置画笔颜色与粗细
        #画笔为白色
        pp.setPen(QColor(255, 255, 255))
        # 设置画笔字体
        pp.setFont(QFont('SimSun', 1000))
        # 根据鼠标指针前后两个位置绘制直线
        pp.drawLine(self.lastPoint, self.endPoint)
        # 让前一个坐标值等于后一个坐标值,
        # 这样就能实现画出连续的线
        self.lastPoint = self.endPoint
        painter = QPainter(self)
        painter.drawPixmap(0, 0, self.pix)

        #将鼠标绘制的图像作为图片保存在本地
        img=self.pix.toImage()
        img.save("img.jpg")

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.lastPoint = event.pos()

    def mouseMoveEvent(self, event):
        if event.buttons() and Qt.LeftButton:
            self.endPoint = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        # 鼠标左键释放
        if event.button() == Qt.LeftButton:
            self.endPoint = event.pos()
            # 进行重新绘制
            self.update()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Drawing()
    form.show()
    sys.exit(app.exec_())



运行结果:

在这里插入图片描述

p122 QSS基础

'''

QSS基础

QSS(Qt Style Sheets)
Qt样式表

用于设置控件的样式(控件的背景色,字体大小)

CSS

'''

from PyQt5.QtWidgets import *
import sys
class BasicQSS(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QSS样式")
        btn1 = QPushButton(self)
        btn1.setText("按钮1")
        btn2 = QPushButton(self)
        btn2.setText("按钮2")

        btn3 = QPushButton(self)
        btn3.setText("按钮3")

        vbox = QVBoxLayout()
        vbox.addWidget(btn1)
        vbox.addWidget(btn2)
        vbox.addWidget(btn3)

        self.setLayout(vbox)
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = BasicQSS()
    # 选择器
    qssStyle = '''
        QPushButton {
            background-color:red;
        }
    '''
    #form内的所有按钮均会被设置成以上样式
    form.setStyleSheet(qssStyle)
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p123 使用QSS选择器设置控件样式

'''

使用QSS选择器设置控件样式
qdarkstyle
'''

from PyQt5.QtWidgets import *
import sys
import qdarkstyle
class QSSSelector(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QSS样式")
        btn1 = QPushButton(self)
        btn1.setText("按钮1")
        btn2 = QPushButton(self)
        #添加特性
        btn2.setProperty('name','btn2')
        btn2.setText("按钮2")

        btn3 = QPushButton(self)
        btn3.setProperty('name','btn3')
        btn3.setText("按钮3")

        vbox = QVBoxLayout()
        vbox.addWidget(btn1)
        vbox.addWidget(btn2)
        vbox.addWidget(btn3)

        self.setLayout(vbox)
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = QSSSelector()
    # 选择器
    #只设置name值为btn2,btn3的按钮
    qssStyle = '''
        QPushButton[name="btn2"] {
            background-color:red;
            color:yellow;
            height:120;
            font-size:60px;
        }
        QPushButton[name="btn3"] {
            background-color:blue;
            color:yellow;
            height:60;
            font-size:30px;
        }
    '''
    form.setStyleSheet(qssStyle)
    # form.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p124 QSS子控件选择器

'''

QSS子控件选择器

QComboBox

'''

from PyQt5.QtWidgets import *
import sys

class QSSSubControl(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QSS子控件选择器")
        combo = QComboBox(self)
        combo.setObjectName("myComboBox")
        combo.addItem("Window")
        combo.addItem("Linux")
        combo.addItem("Mac OS X")

        combo.move(50,50)

        self.setGeometry(250,200,320,150)
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = QSSSubControl()
    #定义下拉列表的样式
    qssStyle = '''
       QComboBox#myComboBox::drop-down {
           image:url(./images/dropdown.png)
       }
    '''
    form.setStyleSheet(qssStyle)
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p125QDarkStyleSheet样式

'''

使用QSS选择器设置控件样式
qdarkstyle
'''

from PyQt5.QtWidgets import *
import sys
import qdarkstyle
class QSSSelector(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QSS样式")
        btn1 = QPushButton(self)
        btn1.setText("按钮1")
        btn2 = QPushButton(self)
        #添加特性
        btn2.setProperty('name','btn2')
        btn2.setText("按钮2")

        btn3 = QPushButton(self)
        btn3.setProperty('name','btn3')
        btn3.setText("按钮3")

        vbox = QVBoxLayout()
        vbox.addWidget(btn1)
        vbox.addWidget(btn2)
        vbox.addWidget(btn3)

        self.setLayout(vbox)
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = QSSSelector()
    # 选择器
    #只设置name值为btn2,btn3的按钮
    qssStyle = '''
        QPushButton[name="btn2"] {
            background-color:red;
            color:yellow;
            height:120;
            font-size:60px;
        }
        QPushButton[name="btn3"] {
            background-color:blue;
            color:yellow;
            height:60;
            font-size:30px;
        }
    '''
    # form.setStyleSheet(qssStyle)
    form.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p126 3种设置背景色和背景图片的方式

"""给窗口设置背景图片"""
'''

使用多种方式设置窗口背景色和背景图片

1.  QSS
2.  QPalette
3.  直接绘制

'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class Background2(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("绘制背景图片")
    def paintEvent(self, event):
        painter = QPainter(self)
        pixmap = QPixmap('./images/screen1.jpg')

        painter.drawPixmap(self.rect(),pixmap)
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Background2()

    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p127 实现不规则窗口

p128 移动和关闭不规则窗口

'''

实现不规则窗口(异形窗口)

通过mask实现异形窗口

需要一张透明的png图,透明部分被扣出,形成一个非矩形的区域


移动和关闭不规则窗口
'''

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class AbnormityWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("异形窗口")
        #设置掩码
        self.pix = QBitmap('./images/mask.png')
        self.resize(self.pix.size())
        self.setMask(self.pix)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_drag = True

            self.m_DragPosition = event.globalPos() - self.pos()
            self.setCursor(QCursor(Qt.OpenHandCursor))
            print(event.globalPos())  #
            print(event.pos())
            print(self.pos())
        #点击鼠标右键,关闭窗口
        if event.button() == Qt.RightButton:
            self.close()

    def mouseMoveEvent(self, QMouseEvent):
        #鼠标左键,移动窗体
        if Qt.LeftButton and self.m_drag:
            # 当左键移动窗体修改偏移值
            # QPoint
            # 实时计算窗口左上角坐标
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)


    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False
        self.setCursor(QCursor(Qt.ArrowCursor))
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(0,0,self.pix.width(),self.pix.height(),QPixmap('./images/screen1.jpg'))
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = AbnormityWindow()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p129 实现异形窗口动画效果

'''
不规则窗体的动画实现

'''

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPixmap, QPainter, QCursor
from PyQt5.QtCore import Qt, QTimer


class AnimationWindows(QWidget):
    def __init__(self, parent=None):
        super(AnimationWindows, self).__init__(parent)
        self.i = 1
        self.mypix()
        self.timer = QTimer()
        self.timer.setInterval(500)  # 500毫秒
        self.timer.timeout.connect(self.timeChange)
        self.timer.start()

    # 显示不规则 pic
    def mypix(self):
        #通过定时器循环显示图片,实现动画效果
        self.update()
        if self.i == 5:
            self.i = 1
        self.mypic = {1: './images/left.png', 2: "./images/up.png", 3: './images/right.png', 4: './images/down.png'}
        self.pix = QPixmap(self.mypic[self.i])
        self.resize(self.pix.size())
        self.setMask(self.pix.mask())
        self.dragPosition = None

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()

            self.setCursor(QCursor(Qt.CustomCursor))
    #鼠标移动事件
    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_drag:
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)

    #鼠标释放事件
    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False
        self.setCursor(QCursor(Qt.ArrowCursor))
    #绘制事件
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(), self.pix)

    # 鼠标双击事件
    def mouseDoubleClickEvent(self, event):
        if event.button() == 1:
            self.i += 1
            self.mypix()

    # 每500毫秒修改paint
    def timeChange(self):
        self.i += 1
        self.mypix()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = AnimationWindows()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p130 装载Gif动画文件

'''

装载Gif动画

QMovie
'''

import sys
from PyQt5.QtWidgets import QApplication,  QLabel  ,QWidget
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QMovie

class LoadingGif(QWidget):
    def __init__(self):
        super().__init__()
        self.label = QLabel("",self)
        self.setFixedSize(128,128)
        #隐藏标题栏
        self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint)
        #通过QMove实现gif动画效果
        self.movie = QMovie('./images/loading.gif')
      
        self.label.setMovie(self.movie)
        self.movie.start()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = LoadingGif()
    form.show()
    sys.exit(app.exec_())


运行结果:

在这里插入图片描述

p131 使用QSS为标签和按钮添加背景图

'''

使用QSS为标签和按钮添加背景图

'''

from PyQt5.QtWidgets import *
import sys

class LabelButtonBackground(QWidget):
    def __init__(self):
        super().__init__()
        label1 = QLabel(self)
        label1.setToolTip('这是一个文本标签')
        label1.setStyleSheet('QLabel{border-image:url(./images/python.jpg);}')

        label1.setFixedWidth(476)
        label1.setFixedHeight(259)

        btn1 = QPushButton(self)
        btn1.setObjectName('btn1')
        btn1.setMaximumSize(48,48)
        btn1.setMinimumSize(48,48)
		
        #按钮未按与按下显示不同背景图
        style = '''
        
            #btn1{
                border-radius:4px;
                background-image:url('./images/add.png');
            }
            #btn1:Pressed {
                background-image:url('./images/addhover.png');
            }
        '''
        btn1.setStyleSheet(style)

        vbox = QVBoxLayout()
        vbox.addWidget(label1)
        vbox.addStretch()
        vbox.addWidget(btn1)

        self.setLayout(vbox)
        self.setWindowTitle('使用QSS为标签和按钮添加背景图')


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = LabelButtonBackground()
    form.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p132 缩放图片

'''

缩放图片

QImage.scaled

'''

from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import Qt
import sys


class ScaleImage(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("图片大小缩放例子")
        filename = './images/Cloudy_72px.png'
        img = QImage(filename)
        label1 = QLabel(self)
        #设置尺寸
        label1.setFixedWidth(200)
        label1.setFixedHeight(200)
        #缩放与让图片尽可能平滑显示
        result = img.scaled(label1.width(),label1.height(),Qt.IgnoreAspectRatio,Qt.SmoothTransformation)
        label1.setPixmap(QPixmap.fromImage(result))

        vbox = QVBoxLayout()
        vbox.addWidget(label1)

        self.setLayout(vbox)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = ScaleImage()
    win.show()
    sys.exit(app.exec_())


运行结果:

在这里插入图片描述

p133 创建透明和半透明窗口

'''

创建透明窗口
setWindowOpacity(num):来实现
num: 0到1,1表示不透明,0表示完全透明
'''

from PyQt5.Qt import *
import sys

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = QMainWindow()
    win.setWindowTitle('窗口的透明度设置')
    # 0到1,1表示不透明,0表示完全透明
    win.setWindowOpacity(0.5)

    button = QPushButton('我的按钮',win)

    win.resize(400,200)
    win.show()
    sys.exit(app.exec())

运行结果:

在这里插入图片描述

p134 装载QSS文件

"""QSS代码:"""
QMainWindow{
    border-image:url(./images/python.jpg);
}

QToolTip {
   border:1px solid rgb(45,45,45);
   background:white;
   color:red
}


"""装载代码:"""
'''

装载QSS文件

'''

import sys
from PyQt5.QtWidgets import *
from CommonHelper import CommonHelper

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.resize(477, 258)
        self.setWindowTitle("加载QSS文件")
        btn = QPushButton()
        btn.setText('装载QSS文件')
        btn.setToolTip('提示文本')

        vbox = QVBoxLayout()
        vbox.addWidget(btn)
        btn.clicked.connect(self.onClick)
        self.setLayout(vbox)

        widget  = QWidget(self)
        self.setCentralWidget(widget)
        widget.setLayout(vbox)

    def onClick(self):
        styleFile = './style.qss'
        qssStyle = CommonHelper.readQSS(styleFile)
        win.setStyleSheet(qssStyle)


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

    win.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p135 用动画效果改变窗口尺寸

'''

用动画效果改变窗口尺寸


QPropertyAnimation




'''

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys


class AnimWindow(QWidget):
    def __init__(self):
        super(AnimWindow, self).__init__()
        self.OrigHeight = 50
        self.ChangeHeight = 150
        self.setGeometry(QRect(500, 400, 150, self.OrigHeight))
        self.btn = QPushButton('展开', self)
        self.btn.setGeometry(10, 10, 60, 35)
        self.btn.clicked.connect(self.change)
    def change(self):
        currentHeight = self.height()
        if self.OrigHeight == currentHeight:
            startHeight = self.OrigHeight
            endHeight = self.ChangeHeight
            self.btn.setText('收缩')
        else:
            startHeight = self.ChangeHeight
            endHeight= self.OrigHeight
            self.btn.setText('展开')

        self.animation = QPropertyAnimation(self,b'geometry') #第二个参数表明是按照坐标修改
        self.animation.setDuration(500)
        self.animation.setStartValue(QRect(500,400,150,startHeight))
        self.animation.setEndValue(QRect(500,400,150,endHeight))
        self.animation.start()



if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = AnimWindow()
    window.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p136 用动画效果–不同速度移动窗口

'''

用动画效果一不同速度移动窗口

'''

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys

app = QApplication(sys.argv)

#创建两个窗口
window1 = QMainWindow()
window1.show()
window2 = QMainWindow()
window2.show()

#按照坐标系实现动画效果
animation1 = QPropertyAnimation(window1, b'geometry')
animation2 = QPropertyAnimation(window2, b'geometry')

group = QParallelAnimationGroup()  # 并行
# group = QSequentialAnimationGroup()  # 串行

group.addAnimation(animation1)
group.addAnimation(animation2)

#时间间隔3000毫秒
animation1.setDuration(3000)
animation1.setStartValue(QRect(0,0,100,30))
animation1.setEndValue(QRect(250,250,100,30))
#动画特效
animation1.setEasingCurve(QEasingCurve.OutBounce)

animation2.setDuration(4000)
animation2.setStartValue(QRect(250,150,100,30))
animation2.setEndValue(QRect(850,250,100,30))
animation2.setEasingCurve(QEasingCurve.CosineCurve)

group.start()

sys.exit(app.exec())


运行结果:

在这里插入图片描述

p137 用pyinstaller打包PyQt5应用


p138 操作SQLite数据库

'''

操作SQLite数据库

'''

import sys

from PyQt5.QtSql import QSqlDatabase,QSqlQuery
#QSqlDatabase:数据库通用接口,QSqlQuery:执行sql语句
def createDB():
    #设置添加数据库的种类
    db = QSqlDatabase.addDatabase('QSQLITE')
    # 指定SQLite数据库的文件名
    db.setDatabaseName('./db/database.db')
    #判断数据库是否可以打开
    if not db.open():
        print('无法建立与数据库的连接')
        return False
    query = QSqlQuery()
    #exec()方法中嵌入sql语句并执行
    query.exec('create table people(id int primary key,name varchar(10),address varchar(50))')
    #插入数据
    query.exec('insert into people values(1,"李宁","Shenyang")')
    query.exec('insert into people values(2,"超人","克星")')
    #数据库关闭
    db.close()
    return True

if __name__ == '__main__':
    createDB()

运行结果:

在这里插入图片描述

p139 使用可视化的方式对SQLite数据库进行增,删,改,查操作

'''

使用可视化的方式对SQLite数据库进行增、删、改、查操作

#采用列表控件显示数据库中的数据
QTableView
#采用此模块从数据库文件中获取数据
QSqlTableModel


'''
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtSql import *

def initializeModel(model):
    #设置表
    model.setTable('people')
    #设置编辑策略
    model.setEditStrategy(QSqlTableModel.OnFieldChange)
    #数据装载
    model.select()
    #设置字段头,Horizontal:设置列,前面数字代表列索引
    model.setHeaderData(0, Qt.Horizontal,'ID')
    model.setHeaderData(1, Qt.Horizontal, '姓名')
    model.setHeaderData(2, Qt.Horizontal, '地址')
#创建视图(显示界面)
def createView(title,model):
    view = QTableView()
    #装入数据
    view.setModel(model)
    #设置标题
    view.setWindowTitle(title)
    return view
def findrow(i):
    #当前行
    delrow = i.row()
    print('del row=%s' % str(delrow))
def addrow():
    #数据库里添加
    ret = model.insertRows(model.rowCount(),1) #1代表一行
    print('insertRow=%s' % str(ret))
if __name__ == '__main__':
    app = QApplication(sys.argv)
    #设置数据库类型
    db = QSqlDatabase.addDatabase('QSQLITE')
    #建立数据库
    db.setDatabaseName('./db/database.db')
    #创建model,用来装载数据
    model = QSqlTableModel()
    delrow = -1
    initializeModel(model)
    view = createView("展示数据",model)
    #点击打印对应行的数据
    view.clicked.connect(findrow)

    dlg = QDialog()
    layout = QVBoxLayout()
    layout.addWidget(view)
    addBtn = QPushButton('添加一行')
    addBtn.clicked.connect(addrow)

    delBtn = QPushButton('删除一行')
    #删除一行
    delBtn.clicked.connect(lambda :model.removeRow(view.currentIndex().row()))
    layout.addWidget(view)
    layout.addWidget(addBtn)
    layout.addWidget(delBtn)
    dlg.setLayout(layout)
    dlg.setWindowTitle("Database Demo")
    dlg.resize(500,400)
    dlg.show()
    sys.exit(app.exec())

p140 分页显示数据

'''

分页显示数据

limit n,m

limit 10,20


'''

import sys
import re
from PyQt5.QtWidgets import*
from PyQt5.QtCore import Qt
from PyQt5.QtSql import *




class DataGrid(QWidget):
    def createTableAndInit(self):
        # 添加数据库
        self.db = QSqlDatabase.addDatabase('QSQLITE')
        # 设置数据库名称
        self.db.setDatabaseName('./db/database.db')
        # 判断是否打开
        if not self.db.open():
            return False

        # 声明数据库查询对象
        query = QSqlQuery()
        # 创建表
        query.exec("create table student(id int primary key, name vchar, sex vchar, age int, deparment vchar)")

        # 添加记录
        query.exec("insert into student values(1,'张三1','男',20,'计算机')")
        query.exec("insert into student values(2,'李四1','男',19,'经管')")
        query.exec("insert into student values(3,'王五1','男',22,'机械')")
        query.exec("insert into student values(4,'赵六1','男',21,'法律')")
        query.exec("insert into student values(5,'小明1','男',20,'英语')")
        query.exec("insert into student values(6,'小李1','女',19,'计算机')")
        query.exec("insert into student values(7,'小张1','男',20,'机械')")
        query.exec("insert into student values(8,'小刚1','男',19,'经管')")
        query.exec("insert into student values(9,'张三2','男',21,'计算机')")
        query.exec("insert into student values(10,'张三3','女',20,'法律')")
        query.exec("insert into student values(11,'王五2','男',19,'经管')")
        query.exec("insert into student values(12,'张三4','男',20,'计算机')")
        query.exec("insert into student values(13,'小李2','男',20,'机械')")
        query.exec("insert into student values(14,'李四2','女',19,'经管')")
        query.exec("insert into student values(15,'赵六3','男',21,'英语')")
        query.exec("insert into student values(16,'李四2','男',19,'法律')")
        query.exec("insert into student values(17,'小张2','女',22,'经管')")
        query.exec("insert into student values(18,'李四3','男',21,'英语')")
        query.exec("insert into student values(19,'小李3','女',19,'法律')")
        query.exec("insert into student values(20,'王五3','女',20,'机械')")
        query.exec("insert into student values(21,'张三4','男',22,'计算机')")
        query.exec("insert into student values(22,'小李2','男',20,'法律')")
        query.exec("insert into student values(23,'张三5','男',19,'经管')")
        query.exec("insert into student values(24,'小张3','女',20,'计算机')")
        query.exec("insert into student values(25,'李四4','男',22,'英语')")
        query.exec("insert into student values(26,'赵六2','男',20,'机械')")
        query.exec("insert into student values(27,'小李3','女',19,'英语')")
        query.exec("insert into student values(28,'王五4','男',21,'经管')")

        return True

    def __init__(self):
        super().__init__()
        self.setWindowTitle("分页查询例子")
        self.resize(750, 300)
        self.createTableAndInit()

        # 当前页
        self.currentPage = 0
        # 总页数
        self.totalPage = 0
        # 总记录数
        self.totalRecrodCount = 0
        # 每页显示记录数
        self.PageRecordCount = 6

        self.initUI()

    def initUI(self):
        # 创建窗口
        self.createWindow()
        # 设置表格
        self.setTableView()

        # 信号槽连接
        self.prevButton.clicked.connect(self.onPrevButtonClick)
        self.nextButton.clicked.connect(self.onNextButtonClick)
        self.switchPageButton.clicked.connect(self.onSwitchPageButtonClick)

    def closeEvent(self, event):
        # 关闭数据库
        self.db.close()

    # 创建窗口
    def createWindow(self):
        # 操作布局
        operatorLayout = QHBoxLayout()
        self.prevButton = QPushButton("前一页")
        self.nextButton = QPushButton("后一页")
        self.switchPageButton = QPushButton("Go")
        self.switchPageLineEdit = QLineEdit()
        self.switchPageLineEdit.setFixedWidth(40)

        switchPage = QLabel("转到第")
        page = QLabel("页")
        operatorLayout.addWidget(self.prevButton)
        operatorLayout.addWidget(self.nextButton)
        operatorLayout.addWidget(switchPage)
        operatorLayout.addWidget(self.switchPageLineEdit)
        operatorLayout.addWidget(page)
        operatorLayout.addWidget(self.switchPageButton)
        operatorLayout.addWidget(QSplitter())

        # 状态布局
        statusLayout = QHBoxLayout()
        self.totalPageLabel = QLabel()
        self.totalPageLabel.setFixedWidth(70)
        self.currentPageLabel = QLabel()
        self.currentPageLabel.setFixedWidth(70)

        self.totalRecordLabel = QLabel()
        self.totalRecordLabel.setFixedWidth(70)

        statusLayout.addWidget(self.totalPageLabel)
        statusLayout.addWidget(self.currentPageLabel)
        statusLayout.addWidget(QSplitter())
        statusLayout.addWidget(self.totalRecordLabel)

        # 设置表格属性
        self.tableView = QTableView()
        # 表格宽度的自适应调整
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # 创建界面
        mainLayout = QVBoxLayout(self);
        mainLayout.addLayout(operatorLayout);
        mainLayout.addWidget(self.tableView);
        mainLayout.addLayout(statusLayout);
        self.setLayout(mainLayout)

    # 设置表格
    def setTableView(self):

        # 声明查询模型
        self.queryModel = QSqlQueryModel(self)
        # 设置当前页
        self.currentPage = 1
        # 得到总记录数
        self.totalRecrodCount = self.getTotalRecordCount()
        # 得到总页数
        self.totalPage = self.getPageCount()
        # 刷新状态
        self.updateStatus()
        # 设置总页数文本
        self.setTotalPageLabel()
        # 设置总记录数
        self.setTotalRecordLabel()

        # 记录查询
        self.recordQuery(0)
        # 设置模型
        self.tableView.setModel(self.queryModel)

        print('totalRecrodCount=' + str(self.totalRecrodCount))
        print('totalPage=' + str(self.totalPage))

        # 设置表格表头
        self.queryModel.setHeaderData(0, Qt.Horizontal, "编号")
        self.queryModel.setHeaderData(1, Qt.Horizontal, "姓名")
        self.queryModel.setHeaderData(2, Qt.Horizontal, "性别")
        self.queryModel.setHeaderData(3, Qt.Horizontal, "年龄")
        self.queryModel.setHeaderData(4, Qt.Horizontal, "院系")

    # 得到记录数
    def getTotalRecordCount(self):
        self.queryModel.setQuery("select * from student")
        rowCount = self.queryModel.rowCount()
        print('rowCount=' + str(rowCount))
        return rowCount

    # 得到页数
    def getPageCount(self):
        if self.totalRecrodCount % self.PageRecordCount == 0:
            return (self.totalRecrodCount / self.PageRecordCount)
        else:
            return (self.totalRecrodCount / self.PageRecordCount + 1)

    # 记录查询
    def recordQuery(self, limitIndex):
        szQuery = ("select * from student limit %d,%d" % (limitIndex, self.PageRecordCount))
        print('query sql=' + szQuery)
        self.queryModel.setQuery(szQuery)

    # 刷新状态
    def updateStatus(self):
        szCurrentText = ("当前第%d页" % self.currentPage)
        self.currentPageLabel.setText(szCurrentText)

        # 设置按钮是否可用
        if self.currentPage == 1:
            self.prevButton.setEnabled(False)
            self.nextButton.setEnabled(True)
        elif self.currentPage == self.totalPage:
            self.prevButton.setEnabled(True)
            self.nextButton.setEnabled(False)
        else:
            self.prevButton.setEnabled(True)
            self.nextButton.setEnabled(True)

    # 设置总数页文本
    def setTotalPageLabel(self):
        szPageCountText = ("总共%d页" % self.totalPage)
        self.totalPageLabel.setText(szPageCountText)

    # 设置总记录数
    def setTotalRecordLabel(self):
        szTotalRecordText = ("共%d条" % self.totalRecrodCount)
        print('*** setTotalRecordLabel szTotalRecordText=' + szTotalRecordText)
        self.totalRecordLabel.setText(szTotalRecordText)

    # 前一页按钮按下
    def onPrevButtonClick(self):
        print('*** onPrevButtonClick ');
        limitIndex = (self.currentPage - 2) * self.PageRecordCount
        self.recordQuery(limitIndex)
        self.currentPage -= 1
        self.updateStatus()

    # 后一页按钮按下
    def onNextButtonClick(self):
        print('*** onNextButtonClick ');
        limitIndex = self.currentPage * self.PageRecordCount
        self.recordQuery(limitIndex)
        self.currentPage += 1
        self.updateStatus()

    # 转到页按钮按下
    def onSwitchPageButtonClick(self):
        # 得到输入字符串
        szText = self.switchPageLineEdit.text()


        # 得到页数
        pageIndex = int(szText)
        # 判断是否有指定页
        if pageIndex > self.totalPage or pageIndex < 1:
            QMessageBox.information(self, "提示", "没有指定的页面,请重新输入")
            return

        # 得到查询起始行号
        limitIndex = (pageIndex - 1) * self.PageRecordCount

        # 记录查询
        self.recordQuery(limitIndex);
        # 设置当前页
        self.currentPage = pageIndex
        # 刷新状态
        self.updateStatus();


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 创建窗口
    example = DataGrid()
    # 显示窗口
    example.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述

p141 使用PyQtGraph进行数据可视化


p142 项目实战:天气信息查询


张三5’,‘男’,19,‘经管’)")
query.exec(“insert into student values(24,‘小张3’,‘女’,20,‘计算机’)”)
query.exec(“insert into student values(25,‘李四4’,‘男’,22,‘英语’)”)
query.exec(“insert into student values(26,‘赵六2’,‘男’,20,‘机械’)”)
query.exec(“insert into student values(27,‘小李3’,‘女’,19,‘英语’)”)
query.exec(“insert into student values(28,‘王五4’,‘男’,21,‘经管’)”)

    return True

def __init__(self):
    super().__init__()
    self.setWindowTitle("分页查询例子")
    self.resize(750, 300)
    self.createTableAndInit()

    # 当前页
    self.currentPage = 0
    # 总页数
    self.totalPage = 0
    # 总记录数
    self.totalRecrodCount = 0
    # 每页显示记录数
    self.PageRecordCount = 6

    self.initUI()

def initUI(self):
    # 创建窗口
    self.createWindow()
    # 设置表格
    self.setTableView()

    # 信号槽连接
    self.prevButton.clicked.connect(self.onPrevButtonClick)
    self.nextButton.clicked.connect(self.onNextButtonClick)
    self.switchPageButton.clicked.connect(self.onSwitchPageButtonClick)

def closeEvent(self, event):
    # 关闭数据库
    self.db.close()

# 创建窗口
def createWindow(self):
    # 操作布局
    operatorLayout = QHBoxLayout()
    self.prevButton = QPushButton("前一页")
    self.nextButton = QPushButton("后一页")
    self.switchPageButton = QPushButton("Go")
    self.switchPageLineEdit = QLineEdit()
    self.switchPageLineEdit.setFixedWidth(40)

    switchPage = QLabel("转到第")
    page = QLabel("页")
    operatorLayout.addWidget(self.prevButton)
    operatorLayout.addWidget(self.nextButton)
    operatorLayout.addWidget(switchPage)
    operatorLayout.addWidget(self.switchPageLineEdit)
    operatorLayout.addWidget(page)
    operatorLayout.addWidget(self.switchPageButton)
    operatorLayout.addWidget(QSplitter())

    # 状态布局
    statusLayout = QHBoxLayout()
    self.totalPageLabel = QLabel()
    self.totalPageLabel.setFixedWidth(70)
    self.currentPageLabel = QLabel()
    self.currentPageLabel.setFixedWidth(70)

    self.totalRecordLabel = QLabel()
    self.totalRecordLabel.setFixedWidth(70)

    statusLayout.addWidget(self.totalPageLabel)
    statusLayout.addWidget(self.currentPageLabel)
    statusLayout.addWidget(QSplitter())
    statusLayout.addWidget(self.totalRecordLabel)

    # 设置表格属性
    self.tableView = QTableView()
    # 表格宽度的自适应调整
    self.tableView.horizontalHeader().setStretchLastSection(True)
    self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

    # 创建界面
    mainLayout = QVBoxLayout(self);
    mainLayout.addLayout(operatorLayout);
    mainLayout.addWidget(self.tableView);
    mainLayout.addLayout(statusLayout);
    self.setLayout(mainLayout)

# 设置表格
def setTableView(self):

    # 声明查询模型
    self.queryModel = QSqlQueryModel(self)
    # 设置当前页
    self.currentPage = 1
    # 得到总记录数
    self.totalRecrodCount = self.getTotalRecordCount()
    # 得到总页数
    self.totalPage = self.getPageCount()
    # 刷新状态
    self.updateStatus()
    # 设置总页数文本
    self.setTotalPageLabel()
    # 设置总记录数
    self.setTotalRecordLabel()

    # 记录查询
    self.recordQuery(0)
    # 设置模型
    self.tableView.setModel(self.queryModel)

    print('totalRecrodCount=' + str(self.totalRecrodCount))
    print('totalPage=' + str(self.totalPage))

    # 设置表格表头
    self.queryModel.setHeaderData(0, Qt.Horizontal, "编号")
    self.queryModel.setHeaderData(1, Qt.Horizontal, "姓名")
    self.queryModel.setHeaderData(2, Qt.Horizontal, "性别")
    self.queryModel.setHeaderData(3, Qt.Horizontal, "年龄")
    self.queryModel.setHeaderData(4, Qt.Horizontal, "院系")

# 得到记录数
def getTotalRecordCount(self):
    self.queryModel.setQuery("select * from student")
    rowCount = self.queryModel.rowCount()
    print('rowCount=' + str(rowCount))
    return rowCount

# 得到页数
def getPageCount(self):
    if self.totalRecrodCount % self.PageRecordCount == 0:
        return (self.totalRecrodCount / self.PageRecordCount)
    else:
        return (self.totalRecrodCount / self.PageRecordCount + 1)

# 记录查询
def recordQuery(self, limitIndex):
    szQuery = ("select * from student limit %d,%d" % (limitIndex, self.PageRecordCount))
    print('query sql=' + szQuery)
    self.queryModel.setQuery(szQuery)

# 刷新状态
def updateStatus(self):
    szCurrentText = ("当前第%d页" % self.currentPage)
    self.currentPageLabel.setText(szCurrentText)

    # 设置按钮是否可用
    if self.currentPage == 1:
        self.prevButton.setEnabled(False)
        self.nextButton.setEnabled(True)
    elif self.currentPage == self.totalPage:
        self.prevButton.setEnabled(True)
        self.nextButton.setEnabled(False)
    else:
        self.prevButton.setEnabled(True)
        self.nextButton.setEnabled(True)

# 设置总数页文本
def setTotalPageLabel(self):
    szPageCountText = ("总共%d页" % self.totalPage)
    self.totalPageLabel.setText(szPageCountText)

# 设置总记录数
def setTotalRecordLabel(self):
    szTotalRecordText = ("共%d条" % self.totalRecrodCount)
    print('*** setTotalRecordLabel szTotalRecordText=' + szTotalRecordText)
    self.totalRecordLabel.setText(szTotalRecordText)

# 前一页按钮按下
def onPrevButtonClick(self):
    print('*** onPrevButtonClick ');
    limitIndex = (self.currentPage - 2) * self.PageRecordCount
    self.recordQuery(limitIndex)
    self.currentPage -= 1
    self.updateStatus()

# 后一页按钮按下
def onNextButtonClick(self):
    print('*** onNextButtonClick ');
    limitIndex = self.currentPage * self.PageRecordCount
    self.recordQuery(limitIndex)
    self.currentPage += 1
    self.updateStatus()

# 转到页按钮按下
def onSwitchPageButtonClick(self):
    # 得到输入字符串
    szText = self.switchPageLineEdit.text()


    # 得到页数
    pageIndex = int(szText)
    # 判断是否有指定页
    if pageIndex > self.totalPage or pageIndex < 1:
        QMessageBox.information(self, "提示", "没有指定的页面,请重新输入")
        return

    # 得到查询起始行号
    limitIndex = (pageIndex - 1) * self.PageRecordCount

    # 记录查询
    self.recordQuery(limitIndex);
    # 设置当前页
    self.currentPage = pageIndex
    # 刷新状态
    self.updateStatus();

if name == ‘main’:
app = QApplication(sys.argv)
# 创建窗口
example = DataGrid()
# 显示窗口
example.show()
sys.exit(app.exec_())


运行结果:

[外链图片转存中...(img-UQAU1Nal-1620820621239)]

### p141 使用PyQtGraph进行数据可视化

```python

p142 项目实战:天气信息查询


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值