4.1 PyQt5基本窗口控件
4.1.1 QMainWindow
QMainWindow、QWidget 和QDialog三个类都是用来创建窗口的,可以直接使用,也可以继承后再使用。
QMainWindow窗口可以包含菜单栏、工具栏、状态栏、标题栏等,是最常见的窗口形式,也可以说是GUI程序的主窗口,如图4-1 所示。
QDialog是对话框窗口的基类。对话框主要用来执行短期任务,或者与用户进行互动,它可以是模态的,也可以是非模态的。QDialog 窗口没有菜单栏、工具栏、状态栏等,如图4-2所示。
如果是主窗口,就使用QMainWindow类;如果是对话框,就使用QDialog 类;如果不确定,或者有可能作为顶层窗口,也有可能嵌入到其他窗口中,那么就使用QWidget类。
4.1.2创建主窗口
如果一个窗口包含一个或多个窗口,那么这个窗口就是父窗口,被包含的窗口则是子窗口。没有父窗口的窗口是顶层窗口,QMainWindow就是一个 顶层窗口,它可以包含很多界面元素,如菜单栏、工具栏、状态栏、子窗口等。
在PyQt中,在主窗口(QMainWindow) 中会有一个控件(QWidget) 占位符来占着中心窗口,可以使用setCentralWidget()来 设置中心窗口,如图4-3所示。
4.1.3案例-创建主窗口
import sys
from PyQt5.QtWidgets import QMainWindow , QApplication
from PyQt5.QtGui import QIcon
class MainWidget(QMainWindow):
def __init__(self,parent=None):
super(MainWidget,self).__init__(parent) # 初始化窗口
# 设置主窗体标签
self.setWindowTitle("QMainWindow 例子") # setWindowTitle()显示窗口名称
self.resize(400, 400) # 设置窗口大小
self.status = self.statusBar() # statusBar()创建状态栏
self.status.showMessage("这是状态栏提示",5000) # status.showMessage是信息显示栏,显示字迹:"这是状态栏提示",显示时间5秒。
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./images/cartoon1.ico"))
main = MainWidget()
main.show()
sys.exit(app.exec_())
4.1.4案例-主窗口居中显示
QMainWindow利用QDesktopWidget类来实现主窗口居中显示。
from PyQt5.QtWidgets import QDesktopWidget, QApplication ,QMainWindow
import sys
class Winform( QMainWindow):
def __init__(self, parent=None):
super( Winform, self).__init__(parent)
self.setWindowTitle('主窗口放在屏幕中间例子')
self.resize(370, 250) # 设置窗口大小
self.center()
def center(self):
screen = QDesktopWidget().screenGeometry() # 计算显示屏幕大小:屏幕宽*屏幕高;
size = self.geometry() # 获取窗口大小
self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) # 移动道窗口中间
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Winform()
win.show()
sys.exit(app.exec_())
4.1.5关闭主窗口
from PyQt5.QtWidgets import QMainWindow,QHBoxLayout, QPushButton , QApplication, QWidget
import sys
class WinForm(QMainWindow):
def __init__(self, parent=None):
super(WinForm, self).__init__(parent)
self.resize(330, 100)
self.setWindowTitle('关闭主窗口例子')
self.button1 = QPushButton('关闭主窗口')
self.button1.clicked.connect(self.onButtonClick) # 将clicked信号与ButtonClick槽函数
layout = QHBoxLayout()
layout.addWidget(self.button1)
main_frame = QWidget()
main_frame.setLayout(layout)
self.setCentralWidget(main_frame)
def onButtonClick(self ):
#sender 是发送信号的对象,此处发送信号的对象是button1按钮
sender = self.sender()
print( sender.text() + ' 被按下了' )
qApp = QApplication.instance()
qApp.quit()
if __name__ == "__main__":
app = QApplication(sys.argv)
form = WinForm()
form.show()
sys.exit(app.exec_())
在槽函数onButtonClick()里获得QApplication类的对象,调用它的quit()函数来关闭窗口,在槽函数里还可以获得发送信号的对象,在本例中发送信号对象是名字为“关闭主窗口”的按钮控件,然后就可以通过按钮的text()函数获得按钮的显示名称。
4.2QWidget
基础窗口控件QWidget类是所有用户界面对象的基类,所有的窗口和控件都直接或间接继承QWidget类。
窗口控件(Widget, 简称“控件”)是在PyQt中建立界面的主要元素。
在PyQt中把没有嵌入到其他控件中的控件称为窗口,一般窗口都有边框、标题栏。窗口是指程序的整体界面,可以包含标题栏、菜单栏、工具栏、关闭按钮、最小化按钮、最大化按钮等;控件是指按钮、复选框、文本框、表格、进度条等这些组成程序的基本元素。一个程序可以有多个窗口,一个窗口也可以有多个控件。
4.2.1 窗口坐标系统
PyQt使用统一的坐标系统来定位窗口控件的位置和大小。具体的坐标系统如
以屏幕的左上角为原点,即(0, 0)点,从左向右为x轴正向,从上向下为y轴正向,整个屏幕的坐标系统就用来定位顶层窗口的。
此外,在窗口内部也有自己的坐标系统,该坐标系统仍然以左上角作为原点,从左向右为x轴正向,从上向下为y轴正向,原点、x轴、y轴围成的区域叫作ClientArea (客户区),在客户区的周围则是标题栏( Window Title)和边框(Frame)。
QWidget直接提供的成员函数:x()、y()获得窗口左上角的坐标,width()、height()获得客户区的宽度和高度。
QWidget的geometry()提供的成员函数: x()、y()获得客户区左上角的坐标,width()、height()获得客户区的宽度和高度。
QWidget的frameGeometry()提供的成员函数: x()、 y()获得窗口左上角的坐标,width()、height()获得包含客户区、标题栏和边框在内的整个窗口的宽度和高度。
4.2.2常用的几何机构
不包含外边各种边框的几何结构。
包含外边各种边框的几何结构。
1、QWidget不包含边框的常用函数
一般情况下,不包含边框的部分是客户区,这里面就是我们正常操作的地方,可以添加子控件。
这部分是一个长方形,会有大小和位置。
大小就是指宽度(width)和高度(height);位置就是指这个长方形在屏幕上的位置。
在Qt中保存这个长方形使用的是QRect类,这个类也有自己的大小和位置。
要改变其大小和位置,可以使用如下几个函数。
(1)改变客户区的面积
Qwidget.resize(width,height) # 改变宽度,改变高度
QWidget.resize(QSize)
(2)获得客户区的大小
Qwidget.size()
(3)获得客户区的宽度和高度
Qwidget.width ()
Qwidget.height ()
(4)设置客户区的宽度和高度
QWidget.setFixedwidth(int width) # 使用这个函数,客户区的高度就是固定的,不可以改变,只可以改变宽度。
QWidget.setFixedHeight(int height) # 这时候宽度就是固定的,不可以改变,但是可以改变高度。
QWidget.setFixedsize(QSize size)
QWidget.setFixedsize(int width,int height)
通过上面这两个函数,高度和宽度都是固定的,不可以通过鼠标来改变窗口的宽度和高度。如果要同时改变客户区的大小和位置,需要用到以下函数。
Qwidget.setGeometry(int x, inty, int width, int height) ;
Qwidget.setGeometry(QRect rect)
# x和y对应的就是x和y坐标。可以不单独设置x和y坐标。
2、QWidget 包含边框的常用函数
QWidget包含边框,这个边框有大小和位置,是窗口在屏幕上显示的整个区域。
这里没有设置这个边框大小的函数,因为通过上面不包含边框函数的设置,就可以设置包含边框的大小了。通过下面的函数,可以获得整个窗口的位置和大小。
(1)获得窗口的大小和位置
QWidget. frameGeometry()
(2)设置窗口的位置
Qwidget.move(int x, inty)
Qwidget. move (QPoint point )
(3)获得窗口左,上角的坐标
Qwidget.pos ()
from PyQt5.QtWidgets import QApplication ,QWidget ,QPushButton
import sys
app = QApplication(sys.argv)
widget = QWidget()
btn = QPushButton( widget )
btn.setText("Button")
#以QWidget左上角为(0, 0)点
btn.move(20, 20)
#不同操作系统可能对窗口最小宽度有规定,若设置宽度小于规定值,则会以规定值进行显示
widget.resize(300, 200)
#以屏幕左上角为(0, 0)点
widget.move(250, 200)
widget.setWindowTitle('PyQt坐标系统例子')
widget.show()
print("#1 QWidget")
print("widget.x()=%d" % widget.x() )
print("widget.y()=%d" % widget.y() )
print("widget.width()=%d" % widget.width() )
print("widget.height()=%d" % widget.height() )
print("#2 QWidget.geometry")
print("widget.geometry().x()=%d" % widget.geometry().x() )
print("widget.geometry().y()=%d" % widget.geometry().y() )
print("widget.geometry().width()=%d" % widget.geometry().width() )
print("widget.geometry().height()=%d" % widget.geometry().height() )
print("widget.size().width() =%d" % widget.size().width() )
print("widget.size().height() =%d" % widget.size().height() )
print("#3 QWidget.frameGeometry")
print("widget.frameGeometry().width()=%d" % widget.frameGeometry().width() )
print("widget.frameGeometry().height()=%d" % widget.frameGeometry().height() )
print("widget.pos().x()=%d" % widget.pos().x() )
print("widget.pos().y()=%d" % widget.pos().y() )
sys.exit(app.exec_())
结果
#1 QWidget
widget.x()=250
widget.y()=200
widget.width()=300
widget.height()=200
#2 QWidget.geometry
widget.geometry().x()=251
widget.geometry().y()=238
widget.geometry().width()=300
widget.geometry().height()=200
widget.size().width() =300
widget.size().height() =200
#3 QWidget.frameGeometry
widget.frameGeometry().width()=302
widget.frameGeometry().height()=239
widget.pos().x()=250
widget.pos().y()=200
4.2.3创建第一个 PyQt 5应用
案例4-5建立一个主 窗口
import sys
from PyQt5.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
window = QWidget()
window.resize(300, 200)
window.move(250, 150)
window.setWindowTitle('Hello PyQt5')
window.show()
sys.exit(app.exec_())
# -*- coding: UTF-8 -*-
这行代码是为了避免在所生成的PyQt程序中出现中文乱码问题。
# 这两行代码用来载入必需的模块。在Qt5中使用的基本的GUI窗口控件都在PyQt5.QtWidgets模块中。
import sys
from PyQt5.QtWidgets import QApplication, QWidget
# 每一个PyQt5 程序都需要有一个QApplication 对象,QApplication 类包含在QTWidgets模块中。
# sys.argv 是-一个命令行参数列表。Python
# 脚本可以从Shell中执行,比如双击.py 脚本文件,通过参数来选择启动脚本的方式。
app = QApplication(sys.argv)
# QWidget控件是PyQt5中所有用户界面类的父类。这里使用了没有参数的默认构造函数,它没有继承其他类。我们称没有父类的控件为窗口。
# 需要注意的是,窗口和控件都继承自QWidget类,如果不为控件指定一个父对象,那么该控件就会被当作窗口处理,这时setWindowTitle() 和setWindowlcon() 函数就会生效。
window = QWidget()
# 设置窗口大小,宽300像素,
window.resize(300, 200)
# 使用move()方法可以设置窗口初始化的位置(x,y)。
window.move(250, 150)
# 这行代码用来设置窗口控件的标题,该标题将在窗口的标题栏中显示。
window.setWindowTitle('Hello PyQt5')
# show()将窗口空间显示在屏幕上
window.show()
# 最后进入该程序的主循环。
# 事件处理从本行代码开始,主循环接收事件消息并将其分发给程序的各个控件。如果调用exit()或 主控件被销毁,主循环就会结束。
# 使用sys.exit()方 法退出可以确保程序完整地结束,在这种情况下系统的环境变量会记录程序是如何退出的。
sys.exit(app.exec_())
4.2.4为应用设置程序图标
为PyQt5应用添加个性化图标。
使用的图标,都是从casyicon网站(http://www.easyicon.net/)免费下载的。easyicon网站提供了超过50万个PNG、ICO、ICNS 格式的图标搜索、图标下载服务,可以免费使用。
案例4-6设置程序图标 .
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget , QApplication
#1
# 在面向对象编程中最重要的是类、属性和方法。
# 在第1组代码中,创建了一个名为Icon的新类,该类继承自QWidget类,因此必须调用两个构造函数一Icon的构造函数和继承类QWidget的构造函数。
class Icon(QWidget):
def __init__(self, parent = None):
super(Icon,self).__init__(parent)
self.initUI()
#2
# 在第2组代码中,定义了初始化界面方法initUIO,使用QWidget类的setGeometry()方法完成了两个功能一设置窗口在屏幕上的位置和设置窗口本身的大小。
# 它的前两个参数是窗口在屏幕上的x和y坐标:后两个参数是窗口本身的宽度和高度。
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('演示程序图标例子')
self.setWindowIcon(QIcon('./images/cartoon1.ico'))
# 使用setWindowIcon(方法来设置程序图标,它需要一个QIcon类型的对象作为参数。
# 在调用QIcon构造函数时,我们需要提供图标路径(相对路径或绝对路径)。
# 同时注意,使用QIcon类型必须导入此模块: from PyQt5.QtGui import QIcon。
if __name__ == '__main__':
app = QApplication(sys.argv)
icon = Icon()
icon.show()
sys.exit(app.exec_())
4.2.5显示气泡提示信息
import sys
from PyQt5.QtWidgets import QWidget, QToolTip , QApplication
from PyQt5.QtGui import QFont
class Winform(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# 通过此行语句设置气泡提示信息的字体与字号大小。
QToolTip.setFont(QFont('SansSerif', 10))
# 要创建工具提示,则需要调用setToolTip(方法,该方法接受富文本格式的参数。
self.setToolTip('这是一个<b>气泡提示</b>')
self.setGeometry(200, 300, 400, 400)
self.setWindowTitle('气泡提示demo')
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Winform()
win.show()
sys.exit(app.exec_())
4.3 QLabel
QLabel对象作为一个占位符可以显示不可编辑的文本或图片,也可以放置一个GIF动画,还可以被用作提示标记为其他控件。纯文本、链接或富文本可以显示在标签上。
案例4-7显示 QLabel标签
打开外部链接
在这个例子中,QLabel对象label2 和label4 包含超链接的标题。label4 的letOpenExternalLinks被设置为True,因此,如果点击这个标签,则相关的URL将在浏览器中打开。将label4的linkHovered信号连接到link_ _clicked (函数,所以,当用鼠标点击它时,这个函数将被执行。
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QApplication, QLabel ,QWidget, QVBoxLayout
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap ,QPalette
import sys
class WindowDemo(QWidget):
def __init__(self ):
super().__init__()
label1 = QLabel(self)
label2 = QLabel(self)
label3 = QLabel(self)
label4 = QLabel(self)
#1
label1.setText("这是一个文本标签。")
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"))
label4.setText("<A href='http://www.cnblogs.com/wangshuo1/'>欢迎访问左士阳的小屋</a>")
label4.setAlignment( Qt.AlignRight)
label4.setToolTip('这是一个超链接标签')
#2
vbox = QVBoxLayout()
vbox.addWidget(label1)
vbox.addStretch()
vbox.addWidget(label2)
vbox.addStretch()
vbox.addWidget( label3 )
vbox.addStretch()
vbox.addWidget( label4)
#3
label1.setOpenExternalLinks(True)
# 打开允许访问超链接,默认是不允许,需要使用 setOpenExternalLinks(True)允许浏览器访问超链接
label4.setOpenExternalLinks( False )
# 点击文本框绑定槽事件
label4.linkActivated.connect( link_clicked )
# 划过文本框绑定槽事件
label2.linkHovered.connect( link_hovered )
label1.setTextInteractionFlags( Qt.TextSelectableByMouse )
self.setLayout(vbox)
self.setWindowTitle("QLabel 例子")
def link_hovered():
print("当鼠标滑过label-2标签时,触发事件。")
def link_clicked():
print("当鼠标点击label-4标签时,触发事件。" )
if __name__ == "__main__":
app = QApplication(sys.argv)
win = WindowDemo()
win.show()
sys.exit(app.exec_())
案例4-8QLabel标签快捷键的使用
from PyQt5.QtWidgets import *
import sys
class QlabelDemo(QDialog):
def __init__(self ):
super().__init__()
self.setWindowTitle('Qlabel 例子')
nameLb1 = QLabel('&Name', self)
nameEd1 = QLineEdit( self )
nameLb1.setBuddy(nameEd1)
nameLb2 = QLabel('&Password', self)
nameEd2 = QLineEdit( self )
nameLb2.setBuddy(nameEd2)
btnOk = QPushButton('&OK')
btnCancel = QPushButton('&Cancel')
mainLayout = QGridLayout(self)
mainLayout.addWidget(nameLb1,0,0)
mainLayout.addWidget(nameEd1,0,1,1,2)
mainLayout.addWidget(nameLb2,1,0)
mainLayout.addWidget(nameEd2,1,1,1,2)
mainLayout.addWidget(btnOk,2,1)
mainLayout.addWidget(btnCancel,2,2)
def link_hovered():
print("当鼠标滑过label-2标签时,触发事件。")
def link_clicked():
print("当鼠标点击label-4标签时,触发事件。" )
if __name__ == "__main__":
app = QApplication(sys.argv)
labelDemo = QlabelDemo()
labelDemo.show()
sys.exit(app.exec_())