注:原创不易,转载请务必注明原作者和出处,感谢支持!

一 写在开头

1.1 本文内容

本文的主要内容:PyQt中的窗口部件:QMainWindow,QWidget,QDialog。

上述三种窗口部件都是用来创建窗口的,可以直接使用,也可以继承后再使用。它们的异同如下:

  • QMainWindow窗口可以包含菜单栏、工具栏、状态栏、标题栏等,是最常见的窗口形式,是GUI程序的主窗口。
  • QDialog是对话框窗口的基类。对话框主要用来执行短期任务,或者与用户进行互动,它可以是模态的,也可是非模态的。QDialog窗口没有菜单栏、工具栏、状态栏等。
  • QWidget即可以用来作为顶层窗口(QMainWindow),可以嵌入到其他窗口中。

三者之间的继承关系如下图:

graph TD;
QWidget-->QMainWindow;
QWidget-->QDialog;

二 QMainWindow

2.1 知识铺垫

何为顶层窗口?如果一个窗口包含一个或多个窗口,那么这个窗口就是父窗口,被包含的窗口则是子窗口。没有父窗口的窗口则是顶层窗口。QMainWindow就是一个顶层窗口,它可以包含很多界面元素,如菜单栏、工具栏、状态栏、子窗口等等。QMainWindow元素布局如下图(来自Qt文档)。

QMainWindow常用的方法有:

方法 描述
addToolBar() 添加工具栏
centralWidget() 返回窗口中心的控件,未设置时返回NULL
menuBar() 返回主窗口的菜单栏
setCentralWidget() 设置窗口中心的控件
setStatusBar() 设置状态栏
statusBar() 获得状态栏对象后,调用状态栏对象的showMessage()方法显示状态栏信息

2.2 QMainWindow实例

什么也不设置的“空白”QMainWindow,代码及效果图如下所示。

#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
from PyQt5.QtWidgets import QApplication, QMainWindow if __name__ == '__main__':
app = QApplication(sys.argv)
w = QMainWindow()
w.show()
sys.exit(app.exec_())

我们通过一个仿照Windows系统的中记事本程序的小实例来了解QMainWindow的使用。

# text-editor.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
import webbrowser
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMainWindow, QTextEdit, QAction, QApplication, \
QMessageBox, QFileDialog, QDesktopWidget class TextEditor(QMainWindow):
'''
TextEditor : 一个简单的记事本程序
'''
def __init__(self):
super().__init__()
self.copiedText = ''
self.initUI() # 初始化窗口界面
def initUI(self):
# 设置中心窗口部件为QTextEdit
self.textEdit = QTextEdit()
self.setCentralWidget(self.textEdit)
self.textEdit.setText('') # 定义一系列的Action
# 退出
exitAction = QAction(QIcon('./images/exit.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close) # 新建
newAction = QAction(QIcon('./images/new.png'), 'New', self)
newAction.setShortcut('Ctrl+N')
newAction.setStatusTip('New application')
newAction.triggered.connect(self.__init__) # 打开
openAction = QAction(QIcon('./images/open.png'), 'Open', self)
openAction.setShortcut('Ctrl+O')
openAction.setStatusTip('Open Application')
openAction.triggered.connect(self.open) # 保存
saveAction = QAction(QIcon('./images/save.png'), 'Save', self)
saveAction.setShortcut('Ctrl+S')
saveAction.setStatusTip('Save Application')
saveAction.triggered.connect(self.save) # 撤销
undoAction = QAction(QIcon('./images/undo.png'), 'Undo', self)
undoAction.setShortcut('Ctrl+Z')
undoAction.setStatusTip('Undo')
undoAction.triggered.connect(self.textEdit.undo) # 重做
redoAction = QAction(QIcon('./images/redo.png'), 'Redo', self)
redoAction.setShortcut('Ctrl+Y')
redoAction.setStatusTip('Redo')
redoAction.triggered.connect(self.textEdit.redo) # 拷贝
copyAction = QAction(QIcon('./images/copy.png'), 'Copy', self)
copyAction.setShortcut('Ctrl+C')
copyAction.setStatusTip('Copy')
copyAction.triggered.connect(self.copy) # 粘贴
pasteAction = QAction(QIcon('./images/paste.png'), 'Paste', self)
pasteAction.setShortcut('Ctrl+V')
pasteAction.setStatusTip('Paste')
pasteAction.triggered.connect(self.paste) # 剪切
cutAction = QAction(QIcon('./images/cut.png'), 'Cut', self)
cutAction.setShortcut('Ctrl+X')
cutAction.setStatusTip('Cut')
cutAction.triggered.connect(self.cut) # 关于
aboutAction = QAction(QIcon('./images/about.png'), 'About', self)
aboutAction.setStatusTip('About')
aboutAction.triggered.connect(self.about) # 添加菜单
# 对于菜单栏,注意menuBar,menu和action三者之间的关系
# 首先取得QMainWindow自带的menuBar:menubar = self.menuBar()
# 然后在menuBar里添加Menu:fileMenu = menubar.addMenu('&File')
# 最后在Menu里添加Action:fileMenu.addAction(newAction)
menubar = self.menuBar() fileMenu = menubar.addMenu('&File')
fileMenu.addAction(newAction)
fileMenu.addAction(openAction)
fileMenu.addAction(saveAction)
fileMenu.addAction(exitAction) editMenu = menubar.addMenu('&Edit')
editMenu.addAction(undoAction)
editMenu.addAction(redoAction)
editMenu.addAction(cutAction)
editMenu.addAction(copyAction)
editMenu.addAction(pasteAction) helpMenu = menubar.addMenu('&Help')
helpMenu.addAction(aboutAction) # 添加工具栏
# 对于工具栏,同样注意ToolBar和Action之间的关系
# 首先在QMainWindow中添加ToolBar:tb1 = self.addToolBar('File')
# 然后在ToolBar中添加Action:tb1.addAction(newAction)
tb1 = self.addToolBar('File')
tb1.addAction(newAction)
tb1.addAction(openAction)
tb1.addAction(saveAction) tb2 = self.addToolBar('Edit')
tb2.addAction(undoAction)
tb2.addAction(redoAction)
tb2.addAction(cutAction)
tb2.addAction(copyAction)
tb2.addAction(pasteAction) tb3 = self.addToolBar('Exit')
tb3.addAction(exitAction) # 添加状态栏,以显示每个Action的StatusTip信息
self.statusBar() self.setGeometry(0, 0, 600, 600)
self.setWindowTitle('Text Editor')
self.setWindowIcon(QIcon('./images/text.png'))
self.center()
self.show() # 主窗口居中显示
def center(self):
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) # 定义Action对应的触发事件,在触发事件中调用self.statusBar()显示提示信息
# 重写closeEvent
def closeEvent(self, event):
reply = QMessageBox.question(self, 'Confirm', \
'Are you sure to quit without saving ?', \
QMessageBox.Yes | QMessageBox.No, \
QMessageBox.No) if reply == QMessageBox.Yes:
self.statusBar().showMessage('Quiting...')
event.accept()
else:
event.ignore()
self.save()
event.accept() # open
def open(self):
self.statusBar().showMessage('Open Text Files')
fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
self.statusBar().showMessage('Open File')
if fname[0]:
f = open(fname[0], 'r')
with f:
data = f.read()
self.textEdit.setText(data) # save
def save(self):
self.statusBar().showMessage('Add extension to file name')
fname = QFileDialog.getSaveFileName(self, 'Save File')
if (fname[0]):
data = self.textEdit.toPlainText()
f = open(fname[0], 'w')
f.write(data)
f.close() # copy
def copy(self):
cursor = self.textEdit.textCursor()
textSelected = cursor.selectedText()
self.copiedText = textSelected # paste
def paste(self):
self.textEdit.append(self.copiedText) # cut
def cut(self):
cursor = self.textEdit.textCursor()
textSelected = cursor.selectedText()
self.copiedText = textSelected
self.textEdit.cut() # about
def about(self):
url = 'https://en.wikipedia.org/wiki/Text_editor'
self.statusBar().showMessage('Loading url...')
webbrowser.open(url) if __name__ == '__main__':
app = QApplication(sys.argv)
w = TextEditor()
sys.exit(app.exec_())

三 QWidget

QWidget类是所有用户界面对象的基类,所有的窗口和控件都直接或间接继承自QWidget类。QWidget类相关的方法。

#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QToolTip
from PyQt5.QtGui import QIcon, QFont if __name__ == '__main__':
app = QApplication(sys.argv) w = QWidget()
btn = QPushButton(w)
btn.setText('Button')
btn.move(20, 20) w.resize(300, 200)
w.move(250, 200)
w.setWindowTitle('QWidget') # setWindowIcon()用于设置应用程序图标
w.setWindowIcon(QIcon('./icon.png')) # setFont()为QToolTip设定字体
QToolTip.setFont(QFont('Monospace Regular', 20))
w.setToolTip('这是一个<b>气泡提示!</b>') w.show() print('QWidget:')
print('w.x() = %d' % w.x())
print('w.y() = %d' % w.y())
print('w.width() = %d' % w.width())
print('w.height() = %d' % w.height()) print('QWidget.geometry')
print('w.geometry().x() = %d' % w.geometry().x())
print('w.geometry().y() = %d' % w.geometry().y())
print('w.geometry().width() = %d' % w.geometry().width())
print('w.geometry().height() = %d' % w.geometry().height()) sys.exit(app.exec_())

脚本输出为:

QWidget:
w.x() = 250
w.y() = 200
w.width() = 300
w.height() = 200
QWidget.geometry
w.geometry().x() = 250
w.geometry().y() = 200
w.geometry().width() = 300
w.geometry().height() = 200

四 QDialog

QDialog的各种子类提供了各种标准对话框,比如QMessageBox, QFileDialog, QInputDialog, QFontDialog等等。它们之间的继承关系如下图所示。

graph TD;
QDialog-->QMessageBox;
QDialog-->QColorDialog;
QDialog-->QFileDialog;
QDialog-->QFontDialog;
QDialog-->QInputDialog;

4.1 QDialog

QDialog类中常用方法:

方法 描述
setWindowTitle() 设置对话框标题
setWindowModality() 设置窗口模态。取值如下:
Qt.NonModal - 非模态
Qt.WindowModal - 窗口模态
Qt.ApplicationModal - 应用程序模态
#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog
from PyQt5.QtCore import Qt class DialogWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Dialog')
self.resize(350, 300) self.btn = QPushButton(self)
self.btn.setText('弹出对话框')
self.btn.move(50, 50)
self.btn.clicked.connect(self.showDialog) self.show() def showDialog(self):
dialog = QDialog()
btn = QPushButton('ok', dialog)
btn.move(50, 50)
dialog.setWindowTitle('Dialog')
dialog.setWindowModality(Qt.ApplicationModal)
dialog.exec_() if __name__ == '__main__':
app = QApplication(sys.argv)
w = DialogWindow()
sys.exit(app.exec_())

4.2 QMessageBox

QMessageBox是一种通用的弹出式对话框,用于显示消息,允许用户通过单击不同的标准按钮对消息进行反馈。每个标准按钮都有一个预定义的文本、角色和十六进制数。QMessageBox类提供了许多常用的弹出式对话框,比如提示、警告、错误、询问、关于等对话框。这些不同类型的QMessageBox对话框只是显示时得图标不同,其他功能是一样的。QMessageBox类中常用的方法有:

方法 描述
information(QWidget parent, title, text, buttons, defaultButton) parent:父窗口
title:对话框标题
text:对话框文本
buttons:多个标准按钮
defaultButton:默认选中的标准按钮
question(QWidget parent, title, text, buttons, defaultButton) 问答对话框
warning(QWidget parent, title, text, buttons, defaultButton) 警告对话框
critical(QWidget parent, title, text, buttons, defaultButton) 严重错误对话框
about(QWidget parent, title, text) 关于对话框
setTitle() 设置标题
setText() 设置消息正文
setIcon() 设置对话框的图片

QMessageBox中的标准按钮类型有:

类型 描述
QMessageBox.Ok 确定
QMessageBox.Cancel 取消
QMessageBox.Yes
QMessageBox.No
QMessageBox.Abort 终止
QMessageBox.Retry 重试
QMessageBox.Ignore 忽略
#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
from PyQt5.QtWidgets import QApplication, QMessageBox, QWidget, QVBoxLayout, \
QPushButton class MessageBoxWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI() def initUI(self):
vbox = QVBoxLayout()
btn = QPushButton('点击弹出消息框')
btn.clicked.connect(self.showMessageBox)
vbox.addWidget(btn)
self.setLayout(vbox) self.setWindowTitle('QMessageBox')
self.resize(300, 200)
self.show() def showMessageBox(self):
QMessageBox.question(self, '标题', '正文内容', QMessageBox.Yes | \
QMessageBox.No, QMessageBox.Yes)
QMessageBox.warning(self, '标题', '正文内容', QMessageBox.Yes | \
QMessageBox.No, QMessageBox.Yes)
QMessageBox.critical(self, '标题', '正文内容', QMessageBox.Yes | \
QMessageBox.No, QMessageBox.Yes)
QMessageBox.about(self, '标题', '正文内容') if __name__ == '__main__':
app = QApplication(sys.argv)
w = MessageBoxWindow()
sys.exit(app.exec_())







4.3 QInputDialog

QInputDialog控件是一个标准对话框,由一个文本框和两个按钮(OK和Cancel)组成。当用户单击OK按钮后,在父窗口可以接受通过QInputDialog控件输入的信息。在QInputDialog控件中可以输入数字、字符串或者列表中的选择。标签用于提示必要的信息。QInputDialog类常用的方法有:

方法 描述
getInt() 从控件中获取标准整型输入
getDouble() 从控件中获取标准浮点数输入
getText() 从控件中获取标准字符串输入
getItem() 从控件中获取列表里的选项输入
#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
from PyQt5.QtWidgets import QWidget, QFormLayout, QPushButton, QLineEdit, \
QInputDialog, QApplication class InputDialogWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI() def initUI(self):
layout = QFormLayout() self.btn1 = QPushButton('获得列表里的选项')
self.btn1.clicked.connect(self.getItem)
self.le1 = QLineEdit()
layout.addRow(self.btn1, self.le1) self.btn2 = QPushButton('获得字符串')
self.btn2.clicked.connect(self.getText)
self.le2 = QLineEdit()
layout.addRow(self.btn2, self.le2) self.btn3 = QPushButton('获得整数')
self.btn3.clicked.connect(self.getInt)
self.le3 = QLineEdit()
layout.addRow(self.btn3, self.le3) self.setLayout(layout)
self.setWindowTitle('QInputDialog')
self.show() def getItem(self):
items = ('C', 'C++', 'Java', 'Python')
item, ok = QInputDialog.getItem(self, 'Select Input Dialog', \
'语言列表', items, 0, False)
if ok and item:
self.le1.setText(item) def getText(self):
text, ok = QInputDialog.getText(self, 'Text Input Dialog', \
'输入姓名:')
if ok:
self.le2.setText(str(text)) def getInt(self):
num, ok = QInputDialog.getInt(self, 'Integer Input Dialog', \
'输入数字:')
if ok:
self.le3.setText(str(num)) if __name__ == '__main__':
app = QApplication(sys.argv)
w = InputDialogWindow()
sys.exit(app.exec_())





4.4 QFontDialg

QFontDialog控件是一个常用的字体选择对话框,可以让用户选择显示文本的字体样式、字号大小和格式。

#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QFontDialog, QApplication, \
QPushButton, QLabel class FontDialogWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI() def initUI(self):
layout = QVBoxLayout()
self.btn = QPushButton('选择字体')
self.btn.clicked.connect(self.chooseFont)
self.lb = QLabel('Hello, 测试字体例子')
layout.addWidget(self.btn)
layout.addWidget(self.lb)
self.setLayout(layout)
self.setWindowTitle('FontDialog')
self.show() def chooseFont(self):
font, ok = QFontDialog.getFont()
if ok:
self.lb.setFont(font) if __name__ == '__main__':
app = QApplication(sys.argv)
w = FontDialogWindow()
sys.exit(app.exec_())



4.5 QFileDialog

QFileDialog是用于打开和保存文件的标准对话框。QFileDialog在打开文件时使用了文件过滤器,用于显示指定扩展名的文件。也可以设置使用QFileDialog打开文件时的起始目录和指定扩展名的文件。QFileDialog类的常用方法有:

方法 描述
getOpenFileName() 返回用户所选择文件的名称,并打开该文件
getSaveFileName() 使用用户选择的文件名并保存文件
setFileMode() 可以选择的文件类型,可选枚举常量有:
QFileDialog.AnyFile:任何文件
QFileDialog.ExistingFile:已存在的文件
QFileDialog.Directory:文件目录
QFileDialog.ExistingFiles:已存在的多个文件
setFilter() 设置过滤器,只显示过滤器允许的文件类型
#!/usr/bin/env python3
# -*- coding: utf-8 -*- import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton, \
QLabel, QTextEdit, QFileDialog
from PyQt5.QtCore import QDir
from PyQt5.QtGui import QPixmap class FileDialogWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI() def initUI(self):
layout = QVBoxLayout()
self.btn1 = QPushButton('加载图片')
self.btn1.clicked.connect(self.chooseImage)
self.lb = QLabel()
layout.addWidget(self.btn1)
layout.addWidget(self.lb) self.btn2 = QPushButton('加载文本文件')
self.btn2.clicked.connect(self.chooseTextFile)
self.content = QTextEdit()
layout.addWidget(self.btn2)
layout.addWidget(self.content) self.setLayout(layout)
self.setWindowTitle('FileDialg')
self.show() def chooseImage(self):
fname, _ = QFileDialog.getOpenFileName(self, 'Open file', '/home', \
"Image files (*.jpg *.png *.gif)")
self.lb.setPixmap(QPixmap(fname)) def chooseTextFile(self):
dlg = QFileDialog()
dlg.setFileMode(QFileDialog.AnyFile)
dlg.setFilter(QDir.Files)
if dlg.exec_():
fname = dlg.selectedFiles()
f = open(fname[0], 'r')
with f:
data = f.read()
self.content.setText(data) if __name__ == '__main__':
app = QApplication(sys.argv)
w = FileDialogWindow()
sys.exit(app.exec_())

PyQt5之窗口类型的更多相关文章

  1. Qt学习之路2---窗口组件及窗口类型

    窗口组件: 图形用户界面由不同的窗口和窗口组件构成: Qt以组件对象的方式,构建图形用户界面. 组件的类型包括: ---容器类(父组件):用于包含其他的界面组件 ---功能类(子组件):用于实现特定的 ...

  2. html5-6 Frame框架窗口类型

    html5-6  Frame框架窗口类型 一.总结 一句话总结: 1.点左侧的a链接如何打开右侧页面? <a href='user/index.html' target='right'>& ...

  3. QObject提供了QMetaObject元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化

    元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化其中元类又提供了:classInfo,className,构造函数, ...

  4. WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口

    原文:WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口 当我们对 Window 类型写一个附加属性的时候,在属性变更通知中我们需要判断依赖对象是否是一个窗口.但是,如果直接判断是否是 W ...

  5. wxWidgets窗口类型

    如果在创建窗口的时候你没有指定窗口的边框类型,那么在不同的平台上将会有不同的边框类型的缺省值.在windows平台上,控件边框的缺省值为 wxSUNKEN_BORDER,意为使用当前系统风格的边框.你 ...

  6. pyqt5实现窗口跳转并关闭上一个窗口

    关键在于要定义一个关闭窗体的函数colsewin() 然后将按键与该函数连接(connect)在一起即可 import sys from PyQt5.QtWidgets import QMainWin ...

  7. pyqt5 设置窗口按钮等可用与不可用

    setEnabled(True) 设置窗口或者按钮可用,Flase不可用

  8. 窗口类型(Widget, Window, Dialog, Desktop, SubWindow等等)

    http://doc.qt.io/qt-5/qwidget.html#windowFlags-prop http://doc.qt.io/qt-5/qtwidgets-widgets-windowfl ...

  9. 解决qt5窗口不刷新(测试窗口类型,测试窗口属性)

    QApplication::notify #if QT_VERSION >= 0x050000        if (QEvent::Show == pEvent->type())     ...

随机推荐

  1. Redis学习笔记(4)——Redis五大数据结构介绍以及应用场景

    出处:https://www.jianshu.com/p/f09480c05e42 Redis是典型的Key-Value类型数据库,Key为字符类型,Value的类型常用的为五种类型:String.H ...

  2. 前端——DOM

    什么是DOM? DOM是W3C(万维网联盟)的标准,是Document Object Model(文档对象模型)的缩写,它定义了访问HTML和XML文档的标准: “W3C文档对象模型(DOM)是中立于 ...

  3. error C2381: “exit”: 重定义;__declspec(noreturn) 不同

    问题: error C2381: “exit” : 重定义:__declspec(noreturn) 不同 解决办法: 调换一下头文件的包含次序: #include <GL/glut.h> ...

  4. STM32F103/429串口IAP+Ymodem升级

    起因: 串口IAP升级在正点原子的例程中有讲解,正点原子的方法是:在RAM中开辟一个120K的数据空间,用来存放bin文件,bin文件通过串口一次性发送到单片机,然后再实现程序的跳转.但是这种方法在实 ...

  5. Kafka 详解(二)------集群搭建

    这里通过 VMware ,我们安装了三台虚拟机,用来搭建 kafka集群,虚拟机网络地址如下: hostname                      ipaddress             ...

  6. Entity Framework Core系列之DbContext(添加)

    上一篇我们介绍了Entity Framework Core系列之DbContext,对DbContext有了概念上的了解,这篇将介绍DbContext添加数据 通过DbContext添加实体的主要方法 ...

  7. string find()函数

    链接 [https://www.cnblogs.com/wkfvawl/p/9429128.html]

  8. openstack搭建之-nova配置(10)

    一. base节点设置数据库 mysql -u root -proot CREATE DATABASE nova_api; CREATE DATABASE nova; CREATE DATABASE ...

  9. 控制结构(3): 状态机(state machine)

    // 上一篇:卫语句(guard clause) // 下一篇:局部化(localization) 基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构. 前情回顾 上次分析了guar ...

  10. Django rest framework(6)----序列化(2)

    为什么要序列化 django 查询数据库返回的类型是  queryset 类型 而我们和前端通信使用的大多数是json类型,这个时候我们需要把 queryset的数据类型转换成python的数据类型然 ...