python【第十三篇】 圖形界面編程之PyQt5


PyQt5安裝

pip install pyqt5

第一個gui程序

語法一

import sys

from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    # 創建QApplication類的實例
    app = QApplication(sys.argv)
    # 創建一個窗口
    w = QWidget()
    # 設置窗口的尺寸
    w.resize(600, 300)
    # 移動窗口
    w.move(300, 300)

    # 設置窗口的標題
    w.setWindowTitle('第一個基於PyQt5的桌面應用')
    # 顯示窗口
    w.show()

    # 進入程序的主循環、並通過exit函數確保主循環安全結束
    sys.exit(app.exec_())

語法二

import sys
from PyQt5.QtWidgets import QApplication, QWidget


class FirstMainWin(QWidget):
    def __init__(self):
        super(FirstMainWin, self).__init__()

        # 設置主窗口的標題
        self.setWindowTitle('第一個主窗口應用')
        # 設置窗口的尺寸
        self.resize(400, 300)


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

    sys.exit(app.exec_())

安裝和配置Qt Designer

安裝Anconda

anaconda自帶Qt  

Pycharm 配置Qt

Qt Designer快速入門

1.ui文件

1.創建住窗口

2.創建組件

左側工具欄,右側屬性欄,中間窗口欄

(拖動左側到的組件中間可創建組件)

3.保存qt文件.ui

2.ui轉py

命令方式:

python -m PyQt5.uic.pyuic demo.ui -o demo.py 

Pycharm方式:  

-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py 

 

基礎窗口控件

 

QLabel控件

'''
QLabel控件

setAlignment():設置文本的對齊方式

setIndent():設置文本縮進

text():獲取文本內容

setBuddy():設置伙伴關系

setText():設置文本內容

selectedText():返回所選擇的字符

setWordWrap():設置是否允許換行

QLabel常用的信號(事件):
1.  當鼠標滑過QLabel控件時觸發:linkHovered
2.  當鼠標單擊QLabel控件時觸發:linkActivated

'''

import sys
from PyQt5.QtWidgets import QVBoxLayout, QMainWindow, QApplication, QLabel, QWidget
from PyQt5.QtGui import QPixmap, QPalette
from PyQt5.QtCore import Qt


class QLabelDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        label1 = QLabel(self)
        label2 = QLabel(self)
        label3 = QLabel(self)
        label4 = QLabel(self)

        label1.setText("<font color=yellow>這是一個文本標簽.</font>")
        label1.setAutoFillBackground(True)
        palette = QPalette()
        palette.setColor(QPalette.Window, Qt.blue)  # 設置背景色
        label1.setPalette(palette)
        label1.setAlignment(Qt.AlignCenter)

        label2.setText("<a href='#'>歡迎使用Python  GUI程序</a>")

        label3.setAlignment(Qt.AlignCenter)

        label3.setToolTip('這是一個圖片標簽')

        label3.setPixmap(QPixmap("./images/python.jpg"))
        # 如果設為True,用瀏覽器打開網頁,如果設為False,調用槽函數
        label4.setOpenExternalLinks(True)

        label4.setText("<a href='https://item.jd.com/12417265.html'>感謝關注《Python從菜鳥到高手》</a>")

        label4.setAlignment(Qt.AlignRight)

        label4.setToolTip('這是一個超級鏈接')

        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.setWindowTitle('QLabel控件演示')

    def linkHovered(self):
        print('當鼠標滑過label2標簽時,觸發事件')

    def linkClicked(self):
        print('當鼠標單擊label4標簽時,觸發事件')


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

 

'''

QLabel與伙伴控件

mainLayout.addWidget(控件對象,rowIndex,columnIndex,row,column)

'''

from PyQt5.QtWidgets import *
import sys

class QLabelBuddy(QDialog) :
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('QLabel與伙伴控件')

        nameLabel = QLabel('&Name',self)
        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_())
QLabelBuddy

QLineEdit控件

'''

QLineEdit控件與回顯模式

基本功能:輸入單行的文本

EchoMode(回顯模式)

4種回顯模式

1. Normal
2. NoEcho
3. Password
4. PasswordEchoOnEdit


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()

        normalLineEdit = QLineEdit()
        noEchoLineEdit = QLineEdit()
        passwordLineEdit = QLineEdit()
        passwordEchoOnEditLineEdit = QLineEdit()

        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_())
回顯模式

'''

現在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_())
校驗器

'''

用掩碼限制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
        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_())
掩碼限制輸入

'''

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
        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_())
綜合案例

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,世界你好嗎?')

    def onClick_ButtonToText(self):
        print(self.textEdit.toPlainText())

    def onClick_ButtonHTML(self):
        self.textEdit.setHtml('<font color="blue" size="5">Hello World</font>')

    def onClick_ButtonToHTML(self):
        print(self.textEdit.toHtml())


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

QPushButton控件

'''

按鈕控件(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個按鈕')
        self.button1.setText('First Button1')
        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('不可用的按鈕')
        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):
        if self.button1.isChecked():
            print('按鈕1已經被選中')
        else:
            print('按鈕1未被選中')

    def whichButton(self, btn):
        print('被單擊的按鈕是<' + btn.text() + '>')


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

QRadioButton控件

'''

單選按鈕控件(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')
        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_())
QRadioButtonDemo

QCheckBox控件

'''

復選框控件(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_())
QCheckBoxDemo

QComboBox控件

'''

下拉列表控件(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()
        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):
        self.label.setText(self.cb.currentText())
        self.label.adjustSize()

        for count in range(self.cb.count()):
            print('item' + str(count) + '=' + self.cb.itemText(count))

        print('current index', i, 'selection changed', self.cb.currentText())


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

QSpinBox控件

'''
計數器控件(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):
        self.label.setText('當前值:' + str(self.sb.value()))

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

QSlider控件

'''

滑塊控件(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):
        print('當前值:%s' % self.sender().value())
        size = self.sender().value()
        self.label.setFont(QFont('Arial', size))


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

對話框

通用對話框

'''

對話框: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_())
QDialogDemo

消息對話框

'''

消息對話框: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, '關於', '這是一個關於對話框')
        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_())
QMessageBox

輸入對話框

'''

輸入對話框: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)

    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_())
QInputDialogDemo

字體對話框 

'''

字體對話框: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()
        if ok:
            self.fontLabel.setFont(font)


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

顏色對話框

'''

顏色對話框: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)
        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_())
QColorDialogDemo

文件對話框

'''

文件對話框:QFileDialog

'''

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):
        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_())
QFileDialogDemo

表格與樹

表格控件

'''

顯示二維表數據(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)

        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)
        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_())
TableView

擴展的表格控件

'''

擴展的表格控件(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_())
TableWidget

樹控件

'''

樹控件(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_())
QTreeWidget
'''

為樹節點添加響應事件

'''
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())
        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_())
TreeEvent
'''

添加、修改和刪除樹控件中的節點

'''

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_())
ModifyTree

容器控件

QTabWidget

'''

選項卡控件: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_())
TabWidget.py

QStackedWidget

'''


堆棧窗口控件(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_())
QStackedWidget.py

QDockWidget

'''


停靠控件(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())

        self.items.setFloating(True)    # 一開始就處於懸浮狀態

        self.addDockWidget(Qt.RightDockWidgetArea,self.items)    # 默認停靠在右側




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

QMdiArea 

'''

容納多文檔的窗口

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.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_())
MultiWindows.py

QScrollBar 

'''

滾動條控件(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)
        palette.setColor(QPalette.Foreground, c)
        self.label.setPalette(palette)

    def sliderMoved1(self):
        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_())
ScrollBar.py

多線程 

QTimer

'''

動態顯示當前時間

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):
        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_())
ShowTime.py

窗口定時關閉 QTimer.singleShot

'''

讓程序定時關閉

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()
    QTimer.singleShot(5000,app.quit)

    sys.exit(app.exec_())
AutoCloseWindow.py

自定義多線程QThread

'''

使用線程類(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秒
            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)  # 連接信號,則觸發函數countTime
        self.workThread.end.connect(self.end)  # 連接信號,則觸發函數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_())
Counter.py

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()
        self.browser.load(QUrl('https://www.jd.com'))
        self.setCentralWidget(self.browser)


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

裝載本地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()
        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_())
裝載本地Web頁面

python與JS交互

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試頁面</title>
    <script>
        function fullname(value) {
            alert("<" + value +">")
            var firstname = document.getElementById('firstname').value;
            var lastname = document.getElementById('lastname').value;

            var fullname = firstname + ' ' + lastname;

            document.getElementById('fullname').value = fullname;
            document.getElementById('submit-btn').style.display = 'block';
            return fullname;
        }

    </script>
</head>
<body>
    <form>
        <label>First Name:</label>
        <input type="text" name="firstname" id="firstname"></input>
        <br/>
        <label>Last Name:</label>
        <input type="text" name="lastname" id="lastname"></input>
        <br/>
        <label>Full Name:</label>
        <input type="text" name="fullname" id="fullname"></input>
        <br/>
        <input  style="display:none;" type="submit" id="submit-btn" />
    </form>
</body>
</html>
tt.html
'''

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_())
PyQtCallJS

布局

'''
絕對布局

'''

import sys, math
from PyQt5.QtWidgets import *


class AbsoluteLayout(QWidget):
    def __init__(self):
        super(AbsoluteLayout, self).__init__()
        self.setWindowTitle("絕對布局")

        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_())
絕對布局
'''

水平盒布局(QHBoxLayout)



'''

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(40)
        self.setLayout(hlayout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = HBoxLayout()
    main.show()
    sys.exit(app.exec_())
水平盒布局
'''

設置控件的對齊方式



'''

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_())
設置控件的對齊方式
'''

設置伸縮量(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()

        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_())
設置伸縮量
'''

設置伸縮量(addStretch)



'''

import sys,math
from PyQt5.QtWidgets import *


class Stretch(QWidget) :
    def __init__(self):
        super(Stretch,self).__init__()
        self.setWindowTitle("設置伸縮量")
        self.resize(800,100)
        btn1 = QPushButton(self)
        btn2 = QPushButton(self)
        btn3 = QPushButton(self)
        btn4 = QPushButton(self)
        btn5 = QPushButton(self)
        btn1.setText("按鈕1")
        btn2.setText("按鈕2")
        btn3.setText("按鈕3")
        btn4.setText("按鈕4")
        btn5.setText("按鈕5")

        layout = QHBoxLayout()

        layout.addStretch(0)
        layout.addWidget(btn1)
        layout.addWidget(btn2)
        layout.addWidget(btn3)
        layout.addWidget(btn4)
        layout.addWidget(btn5)

        btnOK = QPushButton(self)
        btnOK.setText("確定")
        btnCancel = QPushButton(self)
        btnCancel.setText("取消")
        layout.addStretch(1)

        layout.addWidget(btnOK)
        layout.addWidget(btnCancel)
        self.setLayout(layout)







if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Stretch()
    main.show()
    sys.exit(app.exec_())
設置伸縮量2
'''

讓按鈕永遠在窗口右下角


'''

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_())
設置伸縮量之讓按鈕永遠在窗口右下角

 

'''

垂直盒布局(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_())
垂直盒布局
'''

柵格布局:實現計算器UI

'''

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', '.', '=', '+']

        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_())
柵格布局
'''

柵格布局:表單設計

'''

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_())
柵格布局:表單設計
'''

表單布局(QFormLayout)

'''

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_())
表單布局
'''

拖動控件之間的邊界(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_())
拖動控件之間的邊界

信號槽

'''

信號(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_())
信號(Signal)與槽(Slot)
'''

自定義信號

pyqtSignal()

'''

from PyQt5.QtCore import *


class MyTypeSignal(QObject):
    # 定義一個信號
    sendmsg = pyqtSignal(object)

    # 發送3個參數的信號
    sendmsg1 = pyqtSignal(str, int, int)

    def run(self):
        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)

    send.run()
    send.run1()

    send.sendmsg.disconnect(slot.get)
    send.run()
自定義信號
'''
信號與槽自動連接

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")  # 1.
        self.okButton1 = QPushButton("cancel", self)
        self.okButton1.setObjectName("cancelButton")
        layout = QHBoxLayout()
        layout.addWidget(self.okButton)
        self.setLayout(layout)
        QtCore.QMetaObject.connectSlotsByName(self)     # 2.
        # self.okButton.clicked.connect(self.on_okButton_clicked)

    @QtCore.pyqtSlot()
    def on_okButton_clicked(self):  # 2.
        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_())
信號與槽自動連接
'''

使用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
        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_())
為槽函數傳參之lambda
'''

使用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_())
為槽函數傳數之Partial
'''

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):  # 覆蓋
        if e.key() == Qt.Key_Escape:
            self.close()
        elif e.key() == Qt.Key_Alt:
            self.setWindowTitle("按下Alt鍵")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = OverrideSlot()
    form.show()
    sys.exit(app.exec_())
覆蓋槽函數

操作數據庫 

'''

操作SQLite數據庫

'''

import sys

from PyQt5.QtSql import QSqlDatabase, QSqlQuery


def createDB():
    db = QSqlDatabase.addDatabase('QSQLITE')
    # 指定SQLite數據庫的文件名
    db.setDatabaseName('./db/database.db')
    if not db.open():
        print('無法建立與數據庫的連接')
        return False
    query = QSqlQuery()
    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()
連接表
'''

使用可視化的方式對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()
    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)
    print('insertRow=%s' % str(ret))
    
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    db = QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName('./db/database.db')
    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())
增、刪、改、查
'''

分頁顯示數據

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_())
分頁顯示數據

項目實戰

天氣查詢

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'WeatherWin.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(450, 347)
        self.groupBox = QtWidgets.QGroupBox(Form)
        self.groupBox.setGeometry(QtCore.QRect(10, 10, 431, 251))
        self.groupBox.setObjectName("groupBox")
        self.weatherComboBox = QtWidgets.QComboBox(self.groupBox)
        self.weatherComboBox.setGeometry(QtCore.QRect(60, 30, 131, 21))
        self.weatherComboBox.setObjectName("weatherComboBox")
        self.weatherComboBox.addItem("")
        self.weatherComboBox.addItem("")
        self.weatherComboBox.addItem("")
        self.resultText = QtWidgets.QTextEdit(self.groupBox)
        self.resultText.setGeometry(QtCore.QRect(10, 60, 411, 181))
        self.resultText.setObjectName("resultText")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(20, 30, 72, 21))
        self.label.setObjectName("label")
        self.queryBtn = QtWidgets.QPushButton(Form)
        self.queryBtn.setGeometry(QtCore.QRect(90, 300, 93, 28))
        self.queryBtn.setObjectName("queryBtn")
        self.clearBtn = QtWidgets.QPushButton(Form)
        self.clearBtn.setGeometry(QtCore.QRect(230, 300, 93, 28))
        self.clearBtn.setObjectName("clearBtn")

        self.retranslateUi(Form)
        self.clearBtn.clicked.connect(Form.clearResult)
        self.queryBtn.clicked.connect(Form.queryWeather)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.groupBox.setTitle(_translate("Form", "查詢城市天氣"))
        self.weatherComboBox.setItemText(0, _translate("Form", "北京"))
        self.weatherComboBox.setItemText(1, _translate("Form", "天津"))
        self.weatherComboBox.setItemText(2, _translate("Form", "上海"))
        self.label.setText(_translate("Form", "城市"))
        self.queryBtn.setText(_translate("Form", "查詢"))
        self.clearBtn.setText(_translate("Form", "清空"))
WeatherWin.py
'''
項目實戰:天氣信息查詢

'''

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from WeatherWin import Ui_Form
import requests


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)

    def queryWeather(self):
        cityName = self.ui.weatherComboBox.currentText()
        cityCode = self.transCityName(cityName)

        rep = requests.get('http://www.weather.com.cn/data/sk/' + cityCode + '.html')
        rep.encoding = 'utf-8'
        print(rep.json())

        msg1 = '城市: %s' % rep.json()['weatherinfo']['city'] + '\n'
        msg2 = '風向: %s' % rep.json()['weatherinfo']['WD'] + '\n'
        msg3 = '溫度: %s' % rep.json()['weatherinfo']['temp'] + '' + '\n'
        msg4 = '風力: %s' % rep.json()['weatherinfo']['WS'] + '\n'
        msg5 = '濕度: %s' % rep.json()['weatherinfo']['SD'] + '\n'
        result = msg1 + msg2 + msg3 + msg4 + msg5
        self.ui.resultText.setText(result)

    def transCityName(self, cityName):
        cityCode = ''
        if cityName == '北京':
            cityCode = '101010100'
        elif cityName == '天津':
            cityCode = '101030100'
        elif cityName == '上海':
            cityCode = '101020100'

        return cityCode

    def clearResult(self):
        print('* clearResult  ')
        self.ui.resultText.clear()


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

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM