PyQt基础
参考
https://blog.csdn.net/qq_51712954/article/details/124049242 – 还没看
https://space.bilibili.com/457643342
https://blog.csdn.net/m0_57021623/article/details/123459038 – 还没看
概念
QtCore 包含了核心的非GUI模块,主要和时间、文件文件夹、数据流、进程线程有关
QtGui 包含了窗口系统、事件处理、2D图像、绘图、文字等
Qtwidgets 包含了一系列创建桌面应用的Ui元素
窗口
Qwidget
控件和窗口的父类
QMainWindow
QWidget
的子类,包括菜单栏、工具栏、状态栏、中间部分
QDialog
对话框窗口的基类
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QMainWindow
from PyQt5.QtWidgets import QMenuBar,QMenu
from PyQt5.QtWidgets import QToolBar,QStatusBar,QDockWidget
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtCore import Qt as qt
class MyWindow(QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.ui_init()
def ui_init(self):
self.resize(500,500)
self.setWindowTitle("main window")
self.menubar=QMenuBar()
self.setMenuBar(self.menubar)
self.file_menu=QMenu()
self.edit_menu=QMenu()
self.file_menu=self.menubar.addMenu("文件")
self.edit_menu=self.menubar.addMenu("编辑")
self.file_menu.addAction("新建")
self.file_menu.addAction("打开")
self.file_menu.addAction("关闭")
self.docWidget=QDockWidget("浮动窗口")
self.addDockWidget(qt.LeftDockWidgetArea,self.docWidget)
self.textEdit=QTextEdit()
self.setCentralWidget(self.textEdit)
if __name__ == '__main__':
app=QApplication(sys.argv)
w=MyWindow()
w.show()
app.exec_()
信号与槽函数
# 创建信号函数
signal_function = pyqtSignal(args)
# 关联
对象.信号.connect(槽函数)
# 触发
对象.信号.emit(args)
# 槽函数
slot_function(args)
自定义信号与槽函数
pyqt的自定义信号 必须为类属性,不能放在其他方法中
import sys
import time
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtWidgets import QPushButton
class MyWindow(QWidget):
# pyqt的自定义信号 必须为类属性,不能放在其他方法中
my_signal = pyqtSignal(str)
def __init__(self):
super(MyWindow, self).__init__()
self.ui_init()
def ui_init(self):
self.resize(300, 200)
btn = QPushButton("start", self)
btn.setGeometry(100, 150, 100, 30)
btn.clicked.connect(self.check)
self.my_signal.connect(self.my_slot)
def my_slot(self, msg):
print(msg)
def check(self):
for i, ip in enumerate([f"192.168.1.{x}" for x in range(1, 255)]):
print(f'ip:{ip}')
if i % 5 == 0:
self.my_signal.emit(f"{ip}"+"check")
time.sleep(0.01)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWindow()
w.show()
app.exec_()
ui
ui 属性
ui=loadUi('./demo1.ui')
print(ui)
for k,v in ui.__dict__.items():
print(k,v)
# version 1
from PyQt5 import uic
if __name__=='__main__':
app.QApplication(sys.argv)
ui=uic.loadui('ui_filename')
ui.show()
app.exec_()
# version 2
class MyWindow(QWidget):
def __init__(self):
self.ui=uic.loadui('ui_filename')
if __name__=='__main__':
app.QApplication(sys.argv)
w=MyWindow()
w.ui.show()
app.exec_()
ui 与 代码的信号槽函数
直接利用ui文件
import sys
from PyQt5.QtCore import pyqtSignal,Qt
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtWidgets import QPushButton,QLabel,QLineEdit
from PyQt5.uic import loadUi
class MyWindow(QWidget):
# # pyqt的自定义信号 必须为类属性,不能放在其他方法中
# my_signal = pyqtSignal(str)
def __init__(self):
super(MyWindow, self).__init__()
self.ui=loadUi('./demo1.ui')
self.ui_init()
def ui_init(self):
self.ui.pushButton_2.clicked.connect(self.log_in)
def log_in(self):
print(f'{self.ui.lineEdit.text()}')
print(f'{self.ui.lineEdit_2.text()}')
self.ui.textBrowser.setText("用户登录中...")
self.ui.textBrowser.setText(self.ui.lineEdit.text())
self.ui.textBrowser.setText(self.ui.lineEdit_2.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWindow()
w.ui.show()
app.exec_()
ui转py文件
version 1 方法 不如上面的 loadui的方法 不推荐
直接看下面version 2方法
# version 1
# 完全基于ui设计 -- 不推荐
import ui2py
if __name__=='__main__':
app = QApplication(sys.argv) # 创建应用程序对象
w = MyWindow() # 创建主窗口
ui = ui2py.Ui_MainWindow()
ui.setupUi(w)
w.show() # 显示主窗口
sys.exit(app.exec_()) # 在主线程中退出
ui转py文件 – 推荐方法
利用继承关系
import sys
from PyQt5.QtCore import pyqtSignal,Qt
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtWidgets import QPushButton,QLabel,QLineEdit
from PyQt5.uic import loadUi
import demo1
class MyWindow(QWidget,demo1.Ui_Form):
# # pyqt的自定义信号 必须为类属性,不能放在其他方法中
# my_signal = pyqtSignal(str)
def __init__(self):
super(MyWindow, self).__init__()
self.setupUi(self)
self.ui_init()
def ui_init(self):
# self.ui.pushButton_2.clicked.connect(self.log_in)
self.pushButton_2.clicked.connect(self.log_in)
def log_in(self):
print(f'{self.lineEdit.text()}')
print(f'{self.lineEdit_2.text()}')
self.textBrowser.setText("用户登录中...")
self.textBrowser.setText(self.lineEdit.text())
self.textBrowser.setText(self.lineEdit_2.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWindow()
w.show()
app.exec_()
控件
通用函数
setParent() # 指定窗口
setGeometry() # 指定大小和位置
QDesktopWdiget
与屏幕相关
QWidget
# 屏幕相关
center_pointer=QDesktopWidget().availableGeometry().center()
x=center_pointer.x()
y=center_pointer.y()
print(x,y)
print(w.frameGeometry())
print(w.frameGeometry().getRect())
print(QDesktopWidget.screenGeometry(widget=w))
# print(QDesktopWidget.frameGeometry())
# print(QDesktopWidget.availableGeometry())
_,_,width,height=w.frameGeometry().getRect()
w.move(x-width/2,y-height/2)
QPushbButton
指定窗口
# version1
btn=QPushButton('关闭',parent=w)
#version2
btn=QPushButton("开始")
btn.setParent(w)
QLabel
label=QLabel('文本',parent=w)
label.setGeometry(*(20,20),*(30,30)) # 设置起始位置和宽高
# 获取文本
label.text()
QLineEdit
edit=QLineEdit(w)
edit.setPlaceholderText('输入账号')
edit.setGeometry(55,20,300,30)
# 获取输入框中的数据
edit.text()
界面相关
布局
QBoxLayout
QHBoxLayout
QVBoxLayout
import sys
from PyQt5.QtWidgets import QWidget,QApplication
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QPushButton,QLabel
class MyWindow(QWidget):
def __init__(self):
super().__init__() # python3.x
# super(MyWindow, self).__init__() # python2.x
self.resize(300,300)
self.setWindowTitle("main window")
# 创建一个布局器,是一种约束
self.layout=QVBoxLayout()
# layout=QVBoxLayout()
# 将按钮设置在当前的布局器中
btn1=QPushButton('start')
self.layout.addWidget(btn1)
# layout.addWidget(btn1)
btn2 = QPushButton('close')
self.layout.addWidget(btn2)
# layout.addWidget(btn2)
# 让当前的窗口,约束为当前的布局器
# 布局器已经在当前的窗口中了,所以按钮不用在设置为当前窗口
self.setLayout(self.layout)
# self.setLayout(layout)
if __name__ == '__main__':
app=QApplication(sys.argv)
w=MyWindow()
w.show()
app.exec_()
多个布局
一个widget只能有一个布局器,但是布局器可以嵌套
利用QGroupBox
和QLayout
import sys
from PyQt5.QtWidgets import QWidget,QApplication
from PyQt5.QtWidgets import QVBoxLayout,QGroupBox,QHBoxLayout
from PyQt5.QtWidgets import QPushButton,QLabel
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.ui_init()
def ui_init(self):
container=QVBoxLayout()
# 子层1
box1=QGroupBox()
v_layout=QVBoxLayout()
btn1=QPushButton("btn1")
btn2=QPushButton("btn2")
btn3=QPushButton("btn3")
v_layout.addWidget(btn1)
v_layout.addWidget(btn2)
v_layout.addWidget(btn3)
box1.setLayout(v_layout)
# 子层2
box2=QGroupBox()
h_layout=QHBoxLayout()
btn4=QPushButton("btn4")
btn5=QPushButton("btn5")
h_layout.addWidget(btn4)
h_layout.addWidget(btn5)
box2.setLayout(h_layout)
# 外层
container.addWidget(box1)
container.addWidget(box2)
self.setLayout(container)
if __name__ == '__main__':
app=QApplication(sys.argv)
w=MainWindow()
w.show()
app.exec_()
grid布局
import sys
from PyQt5.QtWidgets import QWidget,QApplication
from PyQt5.QtWidgets import QVBoxLayout,QGroupBox,QHBoxLayout,QGridLayout
from PyQt5.QtWidgets import QPushButton,QLabel,QLineEdit
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.data = {
0: ["7", "8", "9", "+", "("],
1: ["4", "5", "6", "-", ")"],
2: ["1", "2", "3", "*", "<-"],
3: ["0", ".", "=", "/", "C"]}
self.ui_init()
def ui_init(self):
self.setWindowTitle('calculator')
layout=QVBoxLayout()
# 输入项
edit=QLineEdit() # 实例化一个控件
edit.setPlaceholderText("input content...")
layout.addWidget(edit)
grid=QGridLayout()
for row,content in self.data.items():
for col,item in enumerate(content):
btn=QPushButton(item)
grid.addWidget(btn,int(row),int(col))
layout.addLayout(grid)
self.setLayout(layout)
if __name__ == '__main__':
app=QApplication(sys.argv)
w=MainWindow()
w.show()
app.exec_()
设置弹簧
弹簧有执行顺序,也就是弹簧在代码中的不同位置会导致不同控件之间的伸缩不同
addStrech(1) addStrech(2) 说明俩个弹簧之间的比例是1:2
# 创建一个布局器,是一种约束
self.layout=QVBoxLayout()
# layout=QVBoxLayout()
# 在button1 之前设置弹簧
self.layout.addStretch()
# 将按钮设置在当前的布局器中
btn1=QPushButton('start')
self.layout.addWidget(btn1)
# layout.addWidget(btn1)
# 在button2 之前设置弹簧
self.layout.addStretch()
btn2 = QPushButton('close')
self.layout.addWidget(btn2)
# layout.addWidget(btn2)
# 让当前的窗口,约束为当前的布局器
# 布局器已经在当前的窗口中了,所以按钮不用在设置为当前窗口
self.setLayout(self.layout)
# self.setLayout(layout)
设置图标
from PyQt5.QtGui import QIcon
w.setWindowIcon(QIcon("ico.png/.ico"))