1、基础代码模板
自己写的类需要继承QWidget,来使用他的方法
super().init() #调用了父类中的初始化方法,父类中的方法都可以用了
label标签控件如果需要放在整个界面里面,需要继承父类,在类中就是self
app=QApplication(sys.argv)创建应用
window=Window() 实例化类
window.show() 显示窗口
sys.exit(app.exec_()) 表示应用app循环执行等待响应(界面操作和代码错误),如果关掉则sys.exit退出程序
from PyQt5.Qt import *
import sys
class Window(QWidget):
def __init__(self):
super().__init__() #调用了父类中的初始化方法,父类中的方法都可以用了
self.setWindowTitle("333")
self.resize(500,500)
label=QLabel(self)
label.setText("123")
app=QApplication(sys.argv)
window=Window()
window.show()
sys.exit(app.exec_())
2、控件
(1)常用控件
- 按钮
- 输入控件(键盘输入、步长调节、组合框、滑块、对话框、日期)
- 展示控件(标签[图片、GIF等]、进度条、对话框)
- 容器控件(QToolBox、QDialogButtonBox、QGroupBox)
- 结构控件(QMainWindow、QTabwidget、QStackedWidget、QSplitter)
- 滚动控件(QTextBrowser、QScrollArea、QAbstractitrmView、QMdiarea、QGraphicsView)
- 辅助控件
3、事件
- 显示和关闭(QShowEvent、QCloseEvent)
- 移动(QMoveEvent)
- 调整大小(QResizeEvent)
- 鼠标事件(QEvent、QMouseEvent)
- 键盘事件
- 焦点事件
- 拖拽事件
- 绘制事件
- 改变事件
4、按钮控件
(1)QPushButton
from PyQt5.Qt import *
import sys
app=QApplication(sys.argv)
window=QWidget()
window.resize(500,500)
window.setWindowTitle("hello")
btn=QPushButton(window) #将window作为顶层窗口,btn作为窗口下的控件
btn.setText("BUTTON")
tb=QIcon("1.png") #在图标上设置图片
btn.setIcon(tb)
#新建主菜单
menu=QMenu(window)
#子菜单,需要添加父菜单
open_recent=QMenu(menu)
open_recent.setTitle("open recently")
#设置主菜单中的名称
new_action=QAction("open",menu)
new_action2=QAction("close",menu)
#设置子菜单中的名称
open_recently=QAction("recent open",open_recent)
open_recent.addAction(open_recently)
menu.addAction(new_action) #添加到主菜单中
menu.addMenu(open_recent) #将子菜单添加到主菜单中
menu.addSeparator() #添加分隔符
menu.addAction(new_action2)
btn.setMenu(menu) #将菜单设置到按钮上
btn.setFlat(True) #设置扁平化
btn.move(50,50)
window.show()
sys.exit(app.exec_())
(2)复选框
self.cb=QCheckBox("11",self) #self为继承的父类
self.cb.setIcon(QIcon("1.png"))
设置是否有三种状态(未选中、部分选中、真的被选中)
self.cb.setTristate(True)
self.cb.setChecked(True) #初始状态为选中的
选中或者清除选中时,发射此信号到changed函数,当状态改变时,执行此函数
self.cb.stateChanged.connect(self.changed)
5、QLineEdit(输入控件)
(1)两个文本框之间赋值
通过QPushButton.pressed.connect(连接的执行函数)
app=QApplication(sys.argv)
window=QWidget()
window.resize(500,500)
window.setWindowTitle("hello")
btn=QPushButton(window)
btn.setText("hello")
btn.move(100,100)
linea=QLineEdit("你好",window)
lineb=QLineEdit("你好",window)
lineb.move(70,70)
lineb.setEchoMode(QLineEdit.Password) #NoEcho输入内容不展示,Normal明文显示,Password密码显示
def copydata():
data=linea.text() #获取文本框a中的内容
lineb.setText(data) #文本框b中输出文本框a中的内容
print(data)
btn.pressed.connect(copydata) #按下按钮执行函数
window.show()
sys.exit(app.exec_())
(2)简易登录界面,类的实现
from PyQt5.Qt import *
import sys
def check_login(account,pwd):
#把账号和密码发送给服务器,等待服务器返回结果
if account!="tyh":
return "1"
if pwd!="123":
return "2"
return "3"
class Window(QWidget):
def __init__(self):
super().__init__() #调用了父类中的初始化方法,父类中的方法都可以用了
self.setWindowTitle("Hello")
self.resize(500,500)
self.setMinimumSize(400,400)
self.setup_ui() #类实例化时自动执行,添加控件
def setup_ui(self):
self.btn = QPushButton(self)
self.btn.setText("登录")
self.btn.pressed.connect(self.login) #设置按钮响应函数,注意要加self
self.linea = QLineEdit(self)
self.lineb = QLineEdit(self)
self.linea.setPlaceholderText("请输入账号")
self.lineb.setPlaceholderText("请输入密码")
width1=self.linea.width()
height1=self.linea.height()
width2 = self.btn.width()
height2 = self.btn.height()
width=self.width()
height=self.height()
self.linea.move((width-width1)/2-20, 80)
self.lineb.move((width-width1)/2-20, 130)
self.btn.move((width-width2)/2, 210)
self.lineb.setEchoMode(QLineEdit.Password) # NoEcho输入内容不展示,Normal明文显示,Password密码显示
def login(self):
data = self.linea.text() # 获取文本框a中的内容
password = self.lineb.text()
state=check_login(data,password)
if state=="1":
print("账号错误")
self.linea.setText("")
self.linea.setFocus()
self.lineb.setText("")
return None
if state=="2":
print("密码错误")
self.lineb.setText("")
self.linea.setFocus()
return None
if state=="3":
print("登录成功")
app=QApplication(sys.argv)
window=Window()
window.show()
sys.exit(app.exec_())
(3)占位文本提示
在还未输入时,文本框中提示的字符
self.linea.setPlaceholderText("请输入账号")
self.lineb.setPlaceholderText("请输入密码")
(4)自动清除文本
如果输错了自动删除重新填写
self.lineb.setClearButtonEnabled(True)
(5)为密码文本框添加明文和密文按钮
先创建一个action,因为要在文本里面,所以以QLineEdit为父类
action=QAction(self.lineb)
action.setIcon(QIcon("1.png"))
再创建action的响应
action.triggered.connect(self.change)
定义change函数
每次按按钮先对是否为明文的状态进行判断再改变
def change(self):
if self.lineb.echoMode()==QLineEdit.Password:
self.lineb.setEchoMode(QLineEdit.Normal)
else:
self.lineb.setEchoMode(QLineEdit.Password)
(6)为账号文本框设置补全候选项
在QCompleter中设置候选的列表,因为要在账号文本框里面提供候选项,所以以账号的文本框为父类
completer=QCompleter(["tyh","hyj"],self.linea) #因为要在账号里面提供候选项,所以以账号的文本框为父类
self.linea.setCompleter(completer)
(6)设置文本只读
self.linea.setReadOnly(True)
(7)文本框信号
文本编辑时发射信号(通过用户编辑的)
self.linea.textEdited.connect(lambda val:print(val))
文本改变时发射信号(代码内部改变和用户编辑)
self.linea.textChanged.connect(lambda val:print(val))
按下回车触发信号
self.linea.returnPressed.connect(lambda :self.lineb.setFocus()) #按下回车焦点定在下一行文本框中
结束编辑(回车、Tab、切换焦点)发射信号
self.linea.editingFinished.connect(lambda :print("1"))
6、QTextEdit
(1)基类——QFrame
用来控制边框样式(凸起、凹下、阴影、线宽)
frame=QFrame(self)
frame.resize(50,50)
frame.setStyleSheet("background-color:cyan;") #设置背景颜色
frame.move(50,100)
frame.setFrameShape(QFrame.Box) #设置形状
frame.setFrameShadow(QFrame.Raised) #设置阴影
frame.setLineWidth(3) #设置线宽
frame.setMidLineWidth(3)
(2)QTextEdit
①占位文本
te=QTextEdit(self)
te.resize(100,100)
te.setPlaceholderText("hello")
- HTML
- 追加文本(append(str))
- 清空文本(clear)
②文本光标对象插入图片
te=QTextEdit(self)
te.resize(100,100)
#设置图片格式
tif=QTextImageFormat()
tif.setName("1.png")
tif.setWidth(50)
tif.setHeight(50)
#建立文本光标对象,在光标处插入图片,QTextFrameFormat.Position
tc=te.textCursor()
tc.insertImage(tif,QTextFrameFormat.FloatRight)
③文本光标对象插入列表和表格
te=QTextEdit(self)
te.resize(100,100)
#建立文本光标对象,在光标处插入图片
tc=te.textCursor()
t1=tc.insertList(QTextListFormat.ListDecimal)
t1=tc.insertTable(5,5) #插入表格
t1.appendColumns(3) #加列、加行
t1.appendRows(3)
④设置文本字符格式
te=QTextEdit(self)
te.resize(300,300)
#建立文本光标对象,在光标处插入图片
tc=te.textCursor()
tcf=QTextCharFormat() #文本字符格式对象
tcf.setFontFamily("隶书")
tcf.setFontPointSize(60)
tc.setBlockCharFormat(tcf)
7、步长调节器
(1)QAbstractSpinBox(由步长调节器和单行文本框调节和显示数据)
stepEnabled和stepBy是QAbstractSpinBox类中现有的方法,分别是控制步长能否执行和设置步长的,按按钮时触发stepBy方法
class myasb(QAbstractSpinBox):
def __init__(self,parent=None):
super().__init__(parent)
self.lineEdit().setText("0") #调用QAbstractSpinBox类中的lineEdit方法,lineEdit就是旁边的文本框
def stepEnabled(self):
current_num=int(self.text()) #读取旁边文本框的内容
if current_num==0:
return QAbstractSpinBox.StepUpEnabled #只有往上调有用
elif current_num==9:
return QAbstractSpinBox.StepDownEnabled
elif current_num<0 or current_num>9:
return QAbstractSpinBox.StepNone
else:
return QAbstractSpinBox.StepUpEnabled|QAbstractSpinBox.StepDownEnabled
def stepBy(self, steps: int):
current_num=int(self.text())+steps
self.lineEdit().setText(str(current_num))
class Window(QWidget):
def __init__(self):
super().__init__() #调用了父类中的初始化方法,父类中的方法都可以用了
self.setWindowTitle("Hello")
self.resize(400,300)
self.setMinimumSize(400,300)
self.setup_ui() #类实例化时自动执行,添加控件
def setup_ui(self):
asb=myasb(self)
asb.resize(100,30)
asb.move(100,100)
asb.setAccelerated(True) #实现按按钮加速
asb.setReadOnly(True) #设置文本只读,只能通过按钮改变无法编辑文本框
#通过按钮获取文本框中的内容
btn=QPushButton(self)
btn.move(200,200)
btn.clicked.connect(self.btn_get_text)
def btn_get_text(self):
text=self.asb.text()
print(text)
app=QApplication(sys.argv)
window=Window()
window.show()
sys.exit(app.exec_())
(2)QSpinBox
主要处理整数和离散值集
class Window(QWidget):
def __init__(self):
super().__init__() #调用了父类中的初始化方法,父类中的方法都可以用了
self.setWindowTitle("Hello")
self.resize(400,300)
self.setMinimumSize(400,300)
self.setup_ui() #类实例化时自动执行,添加控件
def setup_ui(self):
sb=QSpinBox(self)
sb.move(100,100)
# 设置最大最小值
sb.setMinimum(1)
sb.setMaximum(12)
sb.setRange(1,12)
#数值循环,降到最小值后转到最大值
sb.setWrapping(True)
#设置步长
sb.setSingleStep(2)
#加上前后缀,比如5月 sb.setPrefix()
sb.setSuffix("月")
#获取用户输入的数值
sb.setValue(4)
value=sb.value()
#信号
sb.valueChanged.connect(lambda val: print(val))
app=QApplication(sys.argv)
window=Window()
window.show()
sys.exit(app.exec_())
(3)QDoubleSpinBox用于浮点类型步长调节器
8、组合框QComboBox
组合控件,可通过下拉选择界面
(1)基本操作
cb=QComboBox(self)
#添加条目
cb.addItem("12")
cb.addItem("23")
cb.addItems(["12","5600","56"])
#插入条目
cb.insertItem(2,"555555") #在第二个条目后面插入
#删除条目
cb.removeItem(2)
#插入分割线
cb.insertSeparator(3)
#文本框是可编辑的,即输入文本后会在最后记录所添加的文本
cb.setEditable(True)
#设置最多条目数
cb.setMaxCount(6)
#设置可见的条目数
cb.setMaxVisibleItems(3)
(2)信号
cb.currentIndexChanged[str].connect() #当前选中的索引发生改变时
cb.currentTextChanged.connect() #当前文本内容发生改变时
cb.editTextChanged.connect() #编辑的文本发生改变时
9、滑块QAbstractSlider
(1)基本操作:设置最大最小值,设置步长,信号发射与接收
def setup_ui(self):
self.label=QLineEdit(self)
self.label.move(10,10)
self.sd=QSlider(self)
self.sd.move(10,50)
self.sd.setTickPosition(QSlider.TicksLeft) #设置滑块刻度线
self.sd.setMaximum(180)
self.sd.setMinimum(0)
self.sd.setValue(88)
self.sd.setSingleStep(5) #设置步长
self.label.setText(str(self.sd.value()))
self.sd.valueChanged.connect(self.get_text) #当滑块值改变时发出信号
def get_text(self):
value=self.sd.value() #读取滑块的值
print(value)
self.label.setText(str(value))
设置滑块方向:
self.sd.setOrientation(Qt.Horizontal) #调整为水平方向,默认为竖直方向
信号:
self.sd.valueChanged.connect() #当滑块对应的值改变时发出信号
self.sd.sliderPressed.connect() #当滑块被按压时发出信号
self.sd.sliderMoved.connect() #当滑块被移动时发出信号
(2)QScrollBar
sb=QScrollBar(Qt.Horizontal,self) #水平滚动条
(3)QDial
类似于汽车仪表盘的速度表
方法与上面的空间类似
qd=QDial(self)
qd.move(100,100)
qd.setNotchesVisible(True) #是否显示刻度
10、对话框控件 QDialog
11、展示控件
(1)QLabel
可以展示文本、图像、gif、富文本等
label=QLabel("你好啊",self)
label.move(100,100)
label.setStyleSheet("background-color:cyan;") #设置背景颜色
label.resize(150,150)
label.adjustSize() #调整标签适合文字的尺寸
label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) #靠右和居中
超链接:
label=QLabel("<a href='http://www.baidu.com'>百度",self)
label.setOpenExternalLinks(True)
显示图片(富文本):
label.setText("<img src='1.png' width=60 height=60>")
显示视频
movie=QMovie("路径")
label.setMovie(movie)
movie.start()
movie.setSpeed(100) #加速视频 100是一倍速 200是两倍速
(2)QLCDNumber
lcd=QLCDNumber(5,self) #显示的内容位数
lcd.move(100,100)
lcd.display("30") #显示的内容
lcd.resize(100,50)
lcd.setSegmentStyle(QLCDNumber.Flat)
(2)QProgressBar 进度条
先给定范围再设置当前值就能得到进度条
pb=QProgressBar(self)
pb.setMinimum(0)
pb.setMaximum(100)
#pb.setRange(0,100)
pb.setValue(50)
重置
pb.reset() #只重置当前值
(3)QDialog对话框
弹出的对话框
①QErrorMessage提示错误信息
em=QErrorMessage(self)
em.setWindowTitle("错误提示")
em.showMessage("你好啊") #打开并显示内容
②QProgressDialog 进度对话框
pd=QProgressDialog("xx","xx2",0,1000,self) #创建对象后会自动弹出对话框,设置按钮和对话框里面的文字内容,0-1000为数据范围
pd.setWindowTitle("111")
pd.setValue(50)
#设置最小展示时长为1s,默认为4s,如果4s内跑完就不会现实对话框
pd.setMinimumDuration(1)
pd.cancel() #取消进度条
③QMessageBox
对话框构成
mb=QMessageBox(QMessageBox.Warning,"xx1","<h2>xx2</h2>",QMessageBox.Ok|QMessageBox.Discard,self) #添加两个按钮
mb.setText("<h3>haha</h3>")
mb.setInformativeText("<h4>是否直接关闭?</h4>") #提示信息
mb.setCheckBox(QCheckBox("下次不再提醒",mb)) #在父控件mb上添加QCheckBox控件
mb.setDetailedText("hahahaahah") #详情文本
mb.setStandardButtons(QMessageBox.Yes|QMessageBox.No) #设置按钮信息 btn1=mb.addButton(QPushButton("xx1",mb),QMessageBox.YesRole) #xx1的按钮代表什么决策,是Yes还是No
要实现按钮与信号相连接,先把对话框中的按钮赋值,再比对,可以知道按的是哪个按钮
yes_btn=mb.button(QMessageBox.Yes) #mb中表示Yes的按钮赋值给yes_btn
def test(btn):
if btn==yes_btn:
print("打印了第一个按钮")
mb.buttonClicked.connect(test) #按下按钮会将该按钮对象传入test
mb.show()
12、布局管理器
QLayout:
- QBoxLayout 盒子布局
- QGridLayout 网格布局
- QStackedLayout 栈布局,堆叠布局
- QFormLayout 表单布局
步骤:
- 创建布局对象
- 设置布局对象参数:内外边界(margin)、对齐方式(aligment)
- 设置需要布局子控件的父控件
- 将布局管理器中的子控件添加到布局管理器中 (三四步可以互调)
(1)QBoxLayout
QVBoxLayout 垂直布局、QHBoxLayout水平布局
布局管理器只是个定位的策略,不是控件
所有的子类控件都可以设置布局管理器(setLayout是QWidget的方法)
子控件的大小会随着父控件变化而变化,子控件内容改变会根据变化而改变形状和位置
def setup_ui(self):
btn1=QPushButton("1")
btn2=QPushButton("2")
btn3=QPushButton("3")
# 设置垂直管理器
layout=QVBoxLayout()
layout.addWidget(btn1)
layout.addWidget(btn2)
layout.addWidget(btn3)
layout.setContentsMargins(20,30,40,50) #设置布局管理器的边界,分别为:左、上、右、下
layout.setSpacing(40) #设置布局管理器中子控件的间隔
self.setLayout(layout) #在父控件,也就是窗口中设置布局
self.setLayoutDirection(Qt.RightToLeft) #设置布局管理器中子控件的排列方向
可以在布局管理器中添加布局管理器,实现布局管理器的嵌套
使用layout.addLayout(layout1)
label1=QPushButton("1")
label2=QPushButton("2")
# 设置垂直管理器
layout=QHBoxLayout()
layout1 = QVBoxLayout()
btn1 = QPushButton("3")
btn2 = QPushButton("4")
layout1.addWidget(btn1)
layout1.addWidget(btn2)
layout.addWidget(label1)
layout.addLayout(layout1)
layout.addWidget(label2,int) #int为控件的伸缩因子,默认为0
layout.insertWidget() #插入控件
layout.insertLayout() #插入布局管理器
layout.insertSpacing(1,100) #插入空白
layout.setContentsMargins(20,30,40,50)
layout.setSpacing(40)
self.setLayout(layout)
(2)QFormLayout(两列多行布局)
name=QLabel("姓名:")
name_le=QLineEdit()
#创建布局管理器
layout=QFormLayout()
#把布局管理器赋值给父控件
self.setLayout(layout)
#将子控件交给布局管理器
layout.addWidget(name)
layout.addWidget(name_le)
①行操作 layout.addRow
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190630141227919.png
addRow中可以添加两个元素,可以是控件和控件,也可以是控件和布局管理器,如果输入的是字符串,将自动转为QLabel控件显示
name=QLabel("姓名:")
name_le=QLineEdit()
layout=QFormLayout()
self.setLayout(layout)
layout.addRow(name,name_le)
②获取控件的位置
print(layout.getWidgetPosition(name))
③移除行
layout.removeRow(0)
④设置对齐
Qt.AlignBottom居于底部、Qt.AlignLeft居于左边,Qt.AlignTop居于顶部
layout.setFormAlignment(Qt.AlignLeft|Qt.AlignVCenter) #垂直居中
⑤调整行间距和列间距
layout.setHorizontalSpacing(10) #行间距
layout.setVerticalSpacing() #列间距
(3)QGridLayout(多行多列)
name=QLabel("姓名:")
name.setStyleSheet("background-color:red;")
name_le=QLineEdit()
label=QLabel("学号:")
label.setStyleSheet("background-color:yellow;")
layout=QGridLayout()
layout.addWidget(name,1,1) #添加控件时给定第几行第几列
layout.addWidget(name_le,4,1)
layout.addWidget(label,2,1,2,2) #添加空间需要合并单元格,需要给定初始位置和所占行和列的大小
self.setLayout(layout)
添加布局管理器
layout.addLayout() #所添加的布局管理器、初始位置、所占位置
设置最小尺寸
layout.setColumnMinimumWidth(self, column: int, minSize: int)
layout.setRowMinimumHeight(self, row: int, minSize: int))
设置伸缩系数
layout.setColumnStretch()
layout.setRowStretch() #第几行 伸缩系数是多少
设置间距
layout.setSpacing(50)
(4)QStackedLayout
将控件堆叠在一起,同一时刻显示一个控件,可以切换控件
需要先把布局对象设置给需要布局的父控件、父布局,在添加控件
即:
- 创建布局管理器对象
- 把布局对象设置给需要布局的父控件、父布局
- 通过布局对象,管理布局中的子控件
name=QLabel("姓名:")
name.setStyleSheet("background-color:red;")
label=QLabel("学号:")
label.setStyleSheet("background-color:yellow;")
Slayout = QStackedLayout()
self.setLayout(Slayout)
Slayout.addWidget(name)
Slayout.addWidget(label)
设置当前的控件,用于进行控件的切换
Slayout.setCurrentWidget(label)
#移除控件后,后面的控件会移向前
Slayout.removeWidget()
13、控件的尺寸策略
QSizePolicy:
- 水平方向:策略、拉伸系数
- 垂直方向:策略、拉伸系数
分别设置水平和垂直方向的策略
label.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding)
建立策略的对象
QSizePolicy()
sp=QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding)
label.setSizePolicy(sp)
直接对控件设置尺寸,策略将不起作用
label.setFixedSize(40,40)
14、QTimer
需要在程序中周期性地进行某项操作,比如检测某种设备的状态,就会用到定时器
self.timer = QTimer(self) #初始化一个定时器
self.timer.timeout.connect(self.test) #将timeout信号连接到test()信号槽
self.timer.start(1000) #设置计时间间隔为1s并启动
15、QtDesigner
QtDesigner生成的.ui文件可以通过pyuic5工具生成.py文件
PyQt中关于QtDesigner的使用和PyCharm的配置:
(1)安装PyQt5-tools库
pip install PyQt5-tools 需要与PyQt5的版本号一致
(2)在pycharm中进行配置
①打开PyCharm,选择Settings -> Tools -> External Tools
②name:QtDesigner
③Program:PyQt5-tools下面的designer.exe (anaconda3\Lib\site-packages\pyqt5_tools)
④Working directory:工作目录
(3)打开 QtDesigner
pycharm中的Tools->External Tools->QtSesigner---->设计好后保存成ui文件到工作目录
(4)ui文件转换成py文件
在命令行中进入D:\professional_software\anaconda3\anaconda3\Scripts目录(里面有pyuic5.exe文件)
pyuic5.exe ui文件位置 -o 生成的py文件的位置 -x(-x为生成可执行文件)
16、程序打包成exe
常用的打包工具
- py2exe
- Cx_Freeze
- Pyinstaller
在命令行中用cd进入要打包的文件夹中,用pyinstaller -F -w xxx.py生成没有dos窗口的exe文件。
如果出现问题打不开exe或者闪退如下图所示,则用-D形式生成带目录的exe,进入到新目录下的exe,用命令行执行exe : .\class1.exe
在命令行中会打印错误,如果是缺少模块,可以将该模块的文件夹添加到环境变量PATH中。