PyQt5之窗口类型

[TOC]


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

一 写在开头

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_())

转载于:https://www.cnblogs.com/laizhenghong2012/p/10085089.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值