zoukankan      html  css  js  c++  java
  • 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_())
    

  • 相关阅读:
    UIScrollerView遇到UINavigationController
    iOS 自动化打包
    最最基本的SQL常用命令
    导入样式表与外部样式表的区别
    jdk、jre、JVM的简单区别与联系
    JDBC驱动的四种类型
    将映射中的值进行排序并输出键
    Java优先级队列
    Java线程池
    Callable--创建有返回值的线程
  • 原文地址:https://www.cnblogs.com/laizhenghong2012/p/10085089.html
Copyright © 2011-2022 走看看