- 1 晚上一个小项目
- 2 刘金玉编程学习过程
- 2.1 补充pyuic命令解析
- 2.2 PyQt5与Qtdesigner的一些对照分析
- 2.3 PyQt5设置窗体图标
- 2.4 PyQt5显示提示框
- 2.5 PyQt5类封装
- 2.6 PyQt5消息盒子QMesageBox
- 2.7 PyQt5窗体居中和布局
- 2.8 PyQt5窗体的绝对布局和相对布局
- 2.9 PyQt5按钮控件QPushButton应用案例,程序三原色
- 2.10 PyQt5单行文本框QLineEdit文本改变事件
- 2.11 PyQt5复选框QCheckBox控件状态事件应用
- 2.12 PyQt5滑块控件QSlider应用
今晚上跑了一个Pycharm上的Qt-5的翻译代码,记录如下
test.py由designer生成自己再改动一下
from PyQt5 import QtCore, QtGui, QtWidgets
from fanyi import Fanyi
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1027, 816)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setGeometry(QtCore.QRect(350, 120, 171, 71))
self.textBrowser.setStyleSheet("background-color: rgb(107, 255, 193);")
self.textBrowser.setObjectName("textBrowser")
self.layoutWidget = QtWidgets.QWidget(self.centralwidget)
self.layoutWidget.setGeometry(QtCore.QRect(340, 550, 331, 31))
self.layoutWidget.setObjectName("layoutWidget")
self.gridLayout_4 = QtWidgets.QGridLayout(self.layoutWidget)
self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
self.gridLayout_4.setObjectName("gridLayout_4")
self.pushButton_3 = QtWidgets.QPushButton(self.layoutWidget)
self.pushButton_3.setObjectName("pushButton_3")
self.gridLayout_4.addWidget(self.pushButton_3, 0, 0, 1, 1)
self.pushButton_2 = QtWidgets.QPushButton(self.layoutWidget)
self.pushButton_2.setObjectName("pushButton_2")
self.gridLayout_4.addWidget(self.pushButton_2, 0, 1, 1, 1)
self.layoutWidget1 = QtWidgets.QWidget(self.centralwidget)
self.layoutWidget1.setGeometry(QtCore.QRect(180, 270, 625, 233))
self.layoutWidget1.setObjectName("layoutWidget1")
self.gridLayout_3 = QtWidgets.QGridLayout(self.layoutWidget1)
self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
self.gridLayout_3.setObjectName("gridLayout_3")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.textEdit = QtWidgets.QTextEdit(self.layoutWidget1)
self.textEdit.setObjectName("textEdit")
self.gridLayout.addWidget(self.textEdit, 1, 0, 1, 1)
self.label = QtWidgets.QLabel(self.layoutWidget1)
self.label.setStyleSheet("background-color: rgb(255, 216, 119);n"
"font: 18pt "楷体";")
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.gridLayout_3.addLayout(self.gridLayout, 0, 0, 1, 1)
self.pushButton = QtWidgets.QPushButton(self.layoutWidget1)
self.pushButton.setObjectName("pushButton")
self.gridLayout_3.addWidget(self.pushButton, 0, 1, 1, 1)
self.gridLayout_2 = QtWidgets.QGridLayout()
self.gridLayout_2.setObjectName("gridLayout_2")
self.textEdit_2 = QtWidgets.QTextEdit(self.layoutWidget1)
self.textEdit_2.setObjectName("textEdit_2")
self.gridLayout_2.addWidget(self.textEdit_2, 1, 0, 1, 1)
self.label_2 = QtWidgets.QLabel(self.layoutWidget1)
self.label_2.setStyleSheet("background-color: rgb(152, 176, 255);n"
"font: 18pt "隶书";n"
"background-color: rgb(255, 225, 107);")
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
self.gridLayout_3.addLayout(self.gridLayout_2, 0, 2, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1027, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.pushButton_2.clicked.connect(self.textEdit_2.close)
self.pushButton_3.clicked.connect(self.textEdit.clear)
self.pushButton_3.clicked.connect(self.textEdit_2.clear)
self.pushButton.clicked.connect(self.translation)
QtCore.QmetaObject.connectSlotsByName(MainWindow)
def translation(self):
if self.textEdit.toPlainText()=='':
context='None'
else:
context= self.textEdit.toPlainText()
st=Fanyi(context)
self.textEdit_2.setText(st)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.textBrowser.setHtml(_translate("MainWindow", "n"
"n"
"p, li { white-space: pre-wrap; }n"
"n"
"爬虫翻译
"))
self.pushButton_3.setText(_translate("MainWindow", "清除所有文本"))
self.pushButton_2.setText(_translate("MainWindow", "关闭窗口"))
self.label.setText(_translate("MainWindow", "请输入翻译内容"))
self.pushButton.setText(_translate("MainWindow", "翻译"))
self.label_2.setText(_translate("MainWindow", "翻译结果"))
fanyi.py 有道翻译代码块,只能翻译一句话
# -*- coding:utf-8 -*-
import requests
# 把代码封装成函数更python
def Fanyi(word):
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
data = {'i': word,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTIME',
'typoResult': 'false'}
# 将需要post的内容,以字典的形式记录在data内。
r = requests.post(url, data=data)
# post需要输入两个参数,一个url,一个是data,返回的是一个Response对象
answer = r.json()
result = answer['translateResult'][0][0]['tgt']
# print('"'+ word + '"的翻译结果:' + result + 'n')
return result
# if __name__=="__main__": #自己设计输入结束的条件,原谅我懒弄了个死循环
# Fanyi(input('请输入:'))
run_test.py 主程序代码块。
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
import test
if __name__=='__main__':
app=QApplication(sys.argv)
mainW=QMainWindow()
ui=test.Ui_MainWindow()
ui.setupUi(mainW)
mainW.show()
sys.exit(app.exec_())
最后界面
| 函数或语句 | 功能 |
|---|---|
| move(x,y) | 移动窗体 |
| resize(w,h) | 调整窗体大小 |
| exec_() | 表示程序界面监听事件的开始,是一个死循环 |
| 类库或类包 | 功能 |
|---|---|
| QtWidgets | 管理各控件的一个基类 |
| QApplication | 应用程序类 |
| QtGui | 设置图标、字体等的类包 |
| sys | Python系统类库 |
设置窗体标题
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "佳明"))
或者在前面
Form.setWindowTitle("世界")
设置图标
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon # 注意此处继续导入类库
Form.setWindowIcon(QIcon("img\fig1.png")) # 自己选择放置位置
图标较好的下载位置:iconfont,下载尽量使用png或者gif,可使得图片背景透明.
在项目中,我们往往将所有图标放到同一个文件夹中,然后通过同一个相对路径进行调用.
设置两个窗口不同图标所有代码
# new1.py
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(622, 511)
Form.setWindowTitle("世界")
self.retranslateUi(Form)
QtCore.QmetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
# run_new1.py
import sys
from PyQt5.QtWidgets import QApplication,QWidget
import new1
from PyQt5.QtGui import QIcon
if __name__=='__main__':
app=QApplication(sys.argv)
mainW=QWidget()
ui=new1.Ui_Form()
ui.setupUi(mainW)
mainW.setWindowIcon(QIcon("img\fig1.png"))
mainW2=QWidget()
ui2=new1.Ui_Form()
ui2.setupUi(mainW2)
mainW2.setWindowIcon(QIcon("img\fig2.png"))
mainW.show()
mainW2.show()
sys.exit(app.exec_())
通过QWidget的setWindowlcon设置出来的窗体的图标,可以是每个窗体一个图标.
通过Qapplication的setWindowlcon设置出来的窗体的图标,可以是每个窗体用一样的图标
如果把框体没有单独设置窗体图标,那么使用Qapplication的setWindowlcon会统一设置
# mainW2.setWindowIcon(QIcon("img\fig2.png"))
app.setWindowIcon(QIcon("img\fig1.png"))
2.4 PyQt5显示提示框
使用函数setToolTip,基本上所有的控件和窗体都有这个函数.
使用格式: 控件对象.setToolTip(“需要提示的字符串”)
按钮和控件都是作为类的存在
小技巧:系统中文件查找加可以搜索所有包含这个关键词的所有文件*
如何查找所需要的类?
我们可以在Pycharm上,通过Ctrl+PyQt5到其代码,再右键__init__.py,open in File Path找到PyQt5文件安装所在位置.
然后利用模糊查找找到我们所需要的类的位置.
后到程序中去找到对应类.
下面为 显示提示框代码 run_new1.py。
# 需要导入QToolTip类库,通过QToolTip的setFont方法设置文字样式
# 需要导入Qfont类库,实例化Qfont类进行文字样式设置,这个显示样式的设置是在全局样式中呈现效果的
import sys, new1
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton,QToolTip
from PyQt5.QtGui import QIcon, QFont
if __name__=='__main__':
app=QApplication(sys.argv)
QToolTip.setFont(QFont('隶书',40))
W=QWidget()
ui=new1.Ui_Form()
ui.setupUi(W)
W.setWindowIcon(QIcon("img\fig1.png"))
W.setToolTip("你忘记吃饭了")
# 实例化一个按钮(按钮文字,父容器)
btn=QPushButton("老师",W) # 此按钮类最终是继承了QWidget这个类型
btn.move(250,250) # 对按钮在父容器中的位置进行控制
btn.setToolTip("我知道你吃了饭")
btn.setFont(QFont('隶书',33))
W.show()
sys.exit(app.exec_())
2.5 PyQt5类封装
作为优秀的程序员应当擅于类封装.
同时我们要会用纯代码来写PyQt5程序.
一个很粗略的自定义类
class Myclass(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# self.move(20,20)
# self.resize(300,300)
self.setGeometry(20,20,300,300)
btn=QPushButton("老师",self)
btn.move(50,50)
btn.clicked.connect(self.close)
self.show()
if __name__ == "__main__" :
app=QApplication(sys.argv)
mc=Myclass()
app.exec_() # 死循环监听窗体上所有信号
窗体上对GUI的行为都是对某个事件的行为,GUI被事件驱动.
其它方式编程做相应改写即可.
信号槽的简单使用:
格式:信号源.信号.connect(槽)
格式解释:信号源(按钮)信号(clicked)connect(某个事件方法)
注意在绑定信号槽的过程中,我们的槽方法不能加括号.
目标效果:点击按钮出现消息选择框,再选择下一个按钮.
不同图标的消息类别:带有图标的消息盒子,图标可以是问号question,信息information,警告warning,当然也可以自定义其它
思路:
前面程序当点击关闭按钮的时候,执行的是窗体的关闭,而窗体的关闭等同于点击窗体右上角的关闭X的自带按钮的效果,这个效果是QWidget基类所实现的.
那么我们可以重写父类的关闭实现方法来实现其它关闭效果.
下面进入到QWidget里面查找close方法并做相应复制后改写.
如何阻止事件关闭.
event.accept() 同意操作
event.ignore() 忽略操作
主要代码
import sys
from PyQt5.QtWidgets import QApplication, QMessageBox,QWidget,QPushButton,QToolTip
from PyQt5.QtGui import QIcon, QFont
class Myclass(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
QToolTip.setFont(QFont('隶书', 40))
self.setGeometry(500,250,622, 511)
self.setWindowTitle("世界")
self.setWindowIcon(QIcon("img\fig1.png"))
self.setToolTip("你忘记吃饭了")
btn = QPushButton("老师", self) # 此按钮类最终是继承了QWidget这个类型
btn.move(300,300)
btn.setToolTip("我知道你吃了饭")
btn.setFont(QFont('隶书', 33))
btn.clicked.connect(self.close)
self.show()
def closeEvent(self, event): # 重写后名称可自己定义,这里为event
print("你的名字:")
# 重写关闭事件,最后一个为默认,格式:(self,消息标题,消息内容,默认按钮),最后返回一个选中结果
result=QMessageBox.question(self,"温馨提示您:","您真的要关闭窗体吗?",QMessageBox.Yes|QMessageBox.No,QMessageBox.Yes)
if result==QMessageBox.Yes:
event.accept()
else:
event.ignore()
QMessageBox.information(self,"消息","谢谢!")
if __name__=="__main__":
app=QApplication(sys.argv)
ui=Myclass()
app.exec_()
2.7 PyQt5窗体居中和布局
默认情况下,窗体位置居中.
标签文本控件 导入类库QLabel
lbl=QLabel("你快乐吗?",self)
利用width手动设计居中效果
if __name__=="__main__":
app=QApplication(sys.argv)
dk=app.desktop()
ui=Myclass()
ui.move(dk.width()/3,50) # 桌面居中
ui.move(dk.width()/2-ui.width()/2,50) # 水平居中
# 同样使用.height()算高度
app.exec_()
绝对布局:直接通过move到某个像素点的位置,好处是非常灵活.
2.8 PyQt5窗体的绝对布局和相对布局相对布局是指布局中的控件可以随着窗体的变化而变化,布局中控件之间的距离可以按照比例来调节.
导入类QVBoxLayout,QHBoxLayout,QGridLayout来进行垂直布局、水平布局、网格布局
这里面我们使用了QLineEdit 单行输入文本框
水平布局,后面几种均为相对布局.
self.setGeometry(app.desktop().width()/2-self.width()/2,50,400,300)
lelcode=QLabel("验证码",self)
lecode=QLineEdit(self)
btncode=QPushButton("验证",self)
hlayout=QHBoxLayout(self) # 所有控件只能在水平方向排列
hlayout.addWidget(lelcode)
hlayout.addWidget(lecode)
hlayout.addWidget(btncode)
垂直布局
lelcode=QLabel("验证码",self)
lecode=QLineEdit(self)
btncode=QPushButton("验证",self)
vlayout=QVBoxLayout(self)
vlayout.addWidget(lelcode)
vlayout.addWidget(lecode)
vlayout.addWidget(btncode)
vlayout.addStretch() # 弹簧,比例为空白部分
网格布局
lbltitle=QLabel("标题")
blauthor=QLabel("作者")
lblcontent=QLabel("内容")
letitle=QLineEdit()
leauthor=QLineEdit()
lecontent=QTextEdit()
grid=QGridLayout(self)
# grid.setSpacing(20) # 设置空格,此外还有很多额外设置
grid.addWidget(lbltitle,0,0)
grid.addWidget(letitle,0,1)
grid.addWidget(lblauthor,1,0)
grid.addWidget(leauthor,1,1)
grid.addWidget(lblcontent,2,0)
grid.addWidget(lecontent,2,1)
多行文本框有很多基本的功能.
制作三原色可调换界面.
思路:
(一)制作界面采用PyQt5进行布局
(二)采用盒子布局的方法进行界面布局
(三)按钮的状态功能加入
(四)设置Qframe的背景颜色
(五)设置按钮的点击事件
(六)设置三原色的情况,最终还是要通过改变Qframe的样式来实现颜色变化
完整代码如下,背景颜色可随着按钮点击不同而变化。
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton,Qframe,QVBoxLayout,QHBoxLayout
from PyQt5.QtGui import QColor
class Myclass(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("我的三原色")
# 下面设置类中全局变量,此中红、绿、蓝取值范围为0-255
self.color=QColor(0,0,0)
dk=app.desktop()
self.setGeometry(dk.width()/4-self.width()/4,200,400,300)
btnRed=QPushButton("红")
# 使用 setCheckable方法可以设置按钮是否可以选中与不选中的状态切换,默认情况下此方法设置的值为False
btnRed.setCheckable(True)
# 槽函数的定义要看我们的信号源是否有参数,信号源中有参数的部分的信号参数需要使用中括号
btnRed.clicked[bool].connect(self.setColor)
btnGreen = QPushButton("绿")
btnGreen.setCheckable(True)
btnGreen.clicked[bool].connect(self.setColor)
btnBlue = QPushButton("蓝")
btnBlue.setCheckable(True)
btnBlue.clicked[bool].connect(self.setColor)
vlo=QVBoxLayout() # 垂直方向
vlo.addWidget(btnRed)
vlo.addWidget(btnGreen)
vlo.addWidget(btnBlue)
# 框架容器 Qframe,必须使用类库 Qframe,这里面水平右侧隔开一段空白
# 初始化为上面语句,父容器可以采用后期添加到盒式布局的方式进行设置,也可以在初始化时设置
# 父容器的设置会影响子容器的生命周期
self.myframe=Qframe()
# 控件设置CSS风格,可以通过setStylesheet方法来设置,此法几乎在所有QWidget的控件上都能实现
# 设置默认背景颜色(myframe部分),这里{}里面为一个字符串,书写风格 “要控制的控件标签或行为{属性:值}”
self.myframe.setStyleSheet("QWidget{background-color:%s}"%self.color.name())
hlo=QHBoxLayout(self) # 水平方向
hlo.addLayout(vlo)
hlo.addWidget(self.myframe)
self.show()
def setColor(self,p): # 实际上这里的p是bool值,表示点了按钮后的按钮状态
# 通过 sender 函数来实现传递参数控件作用
b=self.sender()
# print(b.text()) # 这里b.text()为红、绿、蓝三种属性
# 根据是否选中按钮来决定颜色的值是否拥有
if p:
v=255
else:
v=0
# 根据按钮的文字来决定哪个参数被赋值为255或者0
if b.text()=="红":
self.color.setRed(v)
elif b.text()=="绿":
self.color.setGreen(v)
elif b.text()=="蓝":
self.color.setBlue(v)
# color.name为16进制存储
self.myframe.setStyleSheet("QWidget{background-color:%s}" % self.color.name())
if __name__ == "__main__":
app=QApplication(sys.argv)
mc=Myclass()
app.exec_()
其为单行文本框,对应于文本改变事件textChanged,结合信号槽.
标签使用QLabel,默认宽度为固定的.当标签文本内容超过标签宽度的显示区域时,超出部分的内容就会进行遮挡,此时我们可以考虑让标签的内容进行区域自适应,使用adjustsize.
完整代码如下。
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLineEdit,QLabel
class Myclass(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("美丽的世界")
self.setGeometry(400,100,400,300)
self.lbl=QLabel("显示区",self)
self.lbl.move(50,50)
le=QLineEdit(self)
# 注意信号在传参时要将小括号改为中括号
le.textChanged[str].connect(self.ljmTxt)
self.show()
def ljmTxt(self,s):
# print(s) # 信号一旦改变就会整串的输出最新文本
self.lbl.setText(s)
self.lbl.adjustSize()
if __name__=="__main__":
app=QApplication(sys.argv)
mc=Myclass()
app.exec_()
2.11 PyQt5复选框QCheckBox控件状态事件应用
状态复选框应用.
我们案例中的Qframe实际上本质是一个QWidget.
使用stateChanged信号,可以传递整型参数.
通过self对象的sender方法就可以区分不同控件传过来的参数.
完整代码。
import sys
from PyQt5.QtWidgets import QApplication,QWidget,Qframe,QCheckBox
from PyQt5.QtCore import Qt
class Myclass(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("美丽的世界")
self.setGeometry(400,100,400,300)
myframel=Qframe(self) # 外面是一个frame,里面有两个按钮
self.ck1=QCheckBox("跳舞",myframel) # 设置复选框
self.ck1.stateChanged[int].connect(self.myState) # 此时当选中时传入2,取消勾选时传入0
self.ck2=QCheckBox("唱歌",myframel)
self.ck2.stateChanged[int].connect(self.myState)
self.ck2.move(0,30)
myframel.move(50,50) # 两个同时移动
self.show()
def myState(self,a):
s=self.sender() # s实为不同的地址
if a==Qt.Checked: # 写成 Qt.Checked能更方便阅读代码
print(s.text())
else:
print("取消"+s.text())
if __name__=="__main__":
app=QApplication(sys.argv)
mc=Myclass()
app.exec_()
注:Qt中有很多枚举类表示,比如该案例中选中复选框使用2对应表示Qt.Checked,写成枚举类型的好处是方便我们阅读代码.



