RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1113094
Accepted
Venot
Venot
Asked:2020-04-20 23:07:33 +0000 UTC2020-04-20 23:07:33 +0000 UTC 2020-04-20 23:07:33 +0000 UTC

QMainWindow 和 QWidget 有什么区别?

  • 772

我开始熟悉PyQt5QMainWindow并遇到了一个误解,小部件和小部件有什么区别QWidget?
还有这样一个问题,我有一个显示的类QWidget,但是是否可以创建一个类QMainWindow并在那里放置各种创建的小部件?

python
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    S. Nick
    2020-04-20T23:53:32Z2020-04-20T23:53:32Z

    主窗口QMainWindow 在更大、更复杂、更强大的应用程序中,我们通常继承自QMainWindow开发类。这个主窗口为构建应用程序的用户界面提供了很好的基础。

    主窗口类QMainWindow为我们提供

    • 菜单栏, Menu Bar

    • 工具栏,Toolbars

    • 小部件Dock和

    • 状态栏, Status Bar

      我们可以根据需要添加任意数量。此外,它使我们能够快速开发功能复杂且方便的应用程序。

    Блокнот/记事本 一个简单的记事本应用程序,了解如何使用QMainWindow

    import sys
    from PyQt5.QtGui import QIcon
    from PyQt5.QtCore import QMimeData
    from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QAction, QFileDialog, QMessageBox,\
                                QFontDialog, QColorDialog
    
    
    class Demo(QMainWindow):
        # В начале класса мы устанавливаем несколько переменных класса, которые используются
        # для определения того, был ли сохранен текст, сохраняется ли это в первый раз,
        # и для сохранения пути к файлу:
        is_saved = True
        is_saved_first = True
        path = ''
    
        def __init__(self):
            super(Demo, self).__init__()
    
            # Затем мы начинаем добавлять строку меню, панель инструментов и строку состояния:
            self.file_menu = self.menuBar().addMenu('File')
            self.edit_menu = self.menuBar().addMenu('Edit')
            self.help_menu = self.menuBar().addMenu('Help')
    
            self.file_toolbar = self.addToolBar('File')
            self.edit_toolbar = self.addToolBar('Edit')
    
            self.status_bar = self.statusBar()
    
            # Далее нам нужно только добавить различные действия к строке меню и панели инструментов, 
            # то есть QAction. Этот класс обычно используется с панелью меню и панелью инструментов. 
            # Вы можете думать о действии как о команде. Всякий раз, когда пользователь нажимает 
            # на действие, запускается определенная команда, и программа выполняет соответствующую команду. 
            # Теперь нам нужно создать несколько действий:
    
            self.new_action     = QAction('New', self)
            self.open_action    = QAction('Open', self)
            self.save_action    = QAction('Save', self)
            self.save_as_action = QAction('Save As', self)
            self.close_action   = QAction('Close', self)
            self.cut_action     = QAction('Cut', self)
            self.copy_action    = QAction('Copy', self)
            self.paste_action   = QAction('Paste', self)
            self.font_action    = QAction('Font', self)
            self.color_action   = QAction('Color', self)
            self.about_action   = QAction('Qt', self)
    
            # Поскольку это Notepad, должен быть текстовый редактор, поэтому, конечно,
            # в функции инициализации класса должен быть создан экземпляр элемента управления QTextEdit:
            self.text_edit = QTextEdit(self)
    
            # С помощью функции вырезания и вставки мы естественно думаем 
            # о буфере обмена и классе QMimeData:
            self.mime_data = QMimeData()                    # QMimeData
            self.clipboard = QApplication.clipboard()       # буфере обмена
    
            # Вызвать метод setCentralWidget() класса QMainWindow, чтобы установить
            # центральный элемент управления главного окна, 
            # в котором мы устанавливаем поле редактирования текста text_edit для центрального 
            # элемента управления. 
            self.setCentralWidget(self.text_edit)
            # Вызовите метод resize(), чтобы установить для окна соответствующий размер;
            self.resize(450, 600)
    
            self.menu_init()
            # После того, как строка меню установлена, мы можем установить панель инструментов:
            self.toolbar_init()
            # Настройка строки состояния очень проста. 
            self.status_bar_init()
    
            self.action_init()    # установить действия
    
            self.text_edit_int()  
    
        def menu_init(self):
            """ добавляем соответствующее действие в строку меню: """
    
            # Видно, что мы можем добавлять к нему действия, вызывая метод addAction(). 
            # Метод addSeparator(), как следует из названия, добавляет разделитель, что означает,
            # что close_action отделено от четырех вышеуказанных действий, что выглядит более организованным.
    
            self.file_menu.addAction(self.new_action)
            self.file_menu.addAction(self.open_action)
            self.file_menu.addAction(self.save_action)
            self.file_menu.addAction(self.save_as_action)
            self.file_menu.addSeparator()
            self.file_menu.addAction(self.close_action)
    
            self.edit_menu.addAction(self.cut_action)
            self.edit_menu.addAction(self.copy_action)
            self.edit_menu.addAction(self.paste_action)
            self.edit_menu.addSeparator()
            self.edit_menu.addAction(self.font_action)
            self.edit_menu.addAction(self.color_action)
    
            self.help_menu.addAction(self.about_action)
    
        def toolbar_init(self):
            self.file_toolbar.addAction(self.new_action)
            self.file_toolbar.addAction(self.open_action)
            self.file_toolbar.addAction(self.save_action)
            self.file_toolbar.addAction(self.save_as_action)
    
            self.edit_toolbar.addAction(self.cut_action)
            self.edit_toolbar.addAction(self.copy_action)
            self.edit_toolbar.addAction(self.paste_action)
            self.edit_toolbar.addAction(self.font_action)
            self.edit_toolbar.addAction(self.color_action)
    
        def status_bar_init(self):
            # Нам просто нужно вызвать метод showMessage() и передать состояние,
            # которое программа хочет отобразить при открытии программы.
            self.status_bar.showMessage('Ready to compose')
    
        def action_init(self):
            # Передайте параметр QIcon через метод setIcon(), чтобы установить значок действия.
            #    Метод setShortCut() используется для установки сочетания клавиш. 
            #      Здесь мы устанавливаем сочетание клавиш нового действия на Ctrl + N.
            #      Тогда нажатие Ctrl+N эквивалентно нажатию этого действия (независимо от платформы, 
            #      здесь используется Ctrl равномерно. (Даже на Mac, но после запуска программы пользователи
            #      Mac должны нажать Ctrl + N). 
            #    Метод setToolTip() можно использовать для установки небольшого всплывающего приглашения. 
            #      Когда указатель мыши находится над действием, будет отображаться соответствующее
            #      приглашение (конечно, мы также можем использовать этот метод для других объектов, 
            #      таких как QPushButton). 
            #    Метод setStatusTip() предназначен для установки информации в строке состояния. 
            #      Когда курсор мыши находится над действием, строка состояния отображает 
            #      соответствующую информацию. 
            #  Наконец, мы связываем сработавший сигнал new_action с пользовательской функцией слота:
    
            self.new_action.setIcon(QIcon('images/new.ico'))
            self.new_action.setShortcut('Ctrl+N')
            self.new_action.setToolTip('Create a new file')
            self.new_action.setStatusTip('Create a new file')
            self.new_action.triggered.connect(self.new_func)
    
            self.open_action.setIcon(QIcon('images/open.png'))
            self.open_action.setShortcut('Ctrl+O')
            self.open_action.setToolTip('Open an existing file')
            self.open_action.setStatusTip('Open an existing file')
            self.open_action.triggered.connect(self.open_file_func)
    
            self.save_action.setIcon(QIcon('images/save.png'))
            self.save_action.setShortcut('Ctrl+S')
            self.save_action.setToolTip('Save the file')
            self.save_action.setStatusTip('Save the file')
            self.save_action.triggered.connect(lambda: self.save_func(self.text_edit.toHtml()))
    
            self.save_as_action.setIcon(QIcon('img/save_as.png'))
            self.save_as_action.setShortcut('Ctrl+A')
            self.save_as_action.setToolTip('Save the file to a specified location')
            self.save_as_action.setStatusTip('Save the file to a specified location')
            self.save_as_action.triggered.connect(lambda: self.save_as_func(self.text_edit.toHtml()))
    
            self.close_action.setIcon(QIcon('img/exit.png'))    # close.ico
            self.close_action.setShortcut('Ctrl+E')
            self.close_action.setToolTip('Close the window')
            self.close_action.setStatusTip('Close the window')
            self.close_action.triggered.connect(self.close_func)
    
            self.cut_action.setIcon(QIcon('img/cut.png'))
            self.cut_action.setShortcut('Ctrl+X')
            self.cut_action.setToolTip('Cut the text to clipboard')
            self.cut_action.setStatusTip('Cut the text')
            self.cut_action.triggered.connect(self.cut_func)
    
            self.copy_action.setIcon(QIcon('img/copy.png'))
            self.copy_action.setShortcut('Ctrl+C')
            self.copy_action.setToolTip('Copy the text')
            self.copy_action.setStatusTip('Copy the text')
            self.copy_action.triggered.connect(self.copy_func)
    
            self.paste_action.setIcon(QIcon('img/paste.png'))
            self.paste_action.setShortcut('Ctrl+V')
            self.paste_action.setToolTip('Paste the text')
            self.paste_action.setStatusTip('Paste the text')
            self.paste_action.triggered.connect(self.paste_func)
    
            self.font_action.setIcon(QIcon('img/font.png'))
            self.font_action.setShortcut('Ctrl+T')
            self.font_action.setToolTip('Change the font')
            self.font_action.setStatusTip('Change the font')
            self.font_action.triggered.connect(self.font_func)
    
            self.color_action.setIcon(QIcon('img/color.png'))
            self.color_action.setShortcut('Ctrl+R')
            self.color_action.setToolTip('Change the color')
            self.color_action.setStatusTip('Change the color')
            self.color_action.triggered.connect(self.color_func)
    
            self.about_action.setIcon(QIcon('img/about.png'))
            self.about_action.setShortcut('Ctrl+Q')
            self.about_action.setToolTip('What is Qt?')
            self.about_action.setStatusTip('What is Qt?')
            self.about_action.triggered.connect(self.about_func)
    
        # В конце у нас остается только поле ввода текста QTextEdit, оставленное неустановленным.
        # Подключите сигнал textChanged к функции слота. 
        # В функции slot(text_changed_func) мы можем установить переменную self.is_saved:
        def text_edit_int(self):
            self.text_edit.textChanged.connect(self.text_changed_func)
    
        def text_changed_func(self):
            if self.text_edit.toPlainText():
                self.is_saved = False
            else:
                self.is_saved = True
    
        # Перед созданием нового файла нам нужно определить, сохранен ли текущий текст. 
        # Если нет, появится всплывающее окно с вопросом, хотите ли вы сохранить его. 
        # Если вы нажмете Да, вы вызовете функцию save_func() для его сохранения. 
        # Если вы нажмете Нет, чтобы сохранить, он будет очищен. 
        # Если вы нажмете `Отмена` для отмены, никакие действия не будут предприняты, 
        #   если они были сохранены, вы можете просто очистить поле для редактирования текста;
    
        def new_func(self):
            if not self.is_saved:
                choice = QMessageBox.question(self, '', 'Do you want to save the text?',
                                              QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                if choice == QMessageBox.Yes:
                    self.save_func()
                    self.text_edit.clear()
                elif choice == QMessageBox.No:
                    self.text_edit.clear()
                else:
                    pass
            else:
                self.text_edit.clear()
    
        # Метод установки действия open_action похож, мы в основном рассмотрим функцию подключенного слота:
        # Логика очень похожа на новое действие, за исключением того, что операция очистки поля 
        # редактирования текста заменяется операцией открытия диалогового окна файла;
        def open_file_func(self):
            if not self.is_saved:
                choice = QMessageBox.question(self, '', 'Do you want to save the text?',
                                              QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                if choice == QMessageBox.Yes:
                    self.save_func()
                    file, _ = QFileDialog.getOpenFileName(self, 'Open File', './', 'Files (*.html *.txt *.log)')
                    if file:
                        with open(file, 'r') as f:
                            self.text_edit.clear()
                            self.text_edit.setText(f.read())
                            self.is_saved = True
                elif choice == QMessageBox.No:
                    file, _ = QFileDialog.getOpenFileName(self, 'Open File', './', 'Files (*.html *.txt *.log)')
                    if file:
                        with open(file, 'r') as f:
                            self.text_edit.clear()
                            self.text_edit.setText(f.read())
                            self.is_saved = True
                else:
                    pass
            else:
                file, _ = QFileDialog.getOpenFileName(self, 'Open File', './', 'Files (*.html *.txt *.log)')
                if file:
                    with open(file, 'r') as f:
                        self.text_edit.clear()
                        self.text_edit.setText(f.read())
                        self.is_saved = True
    
        # Функции слотов 
        def save_func(self, text):
            if self.is_saved_first:
                self.save_as_func(text)
            else:
                with open(self.path, 'w') as f:
                    f.write(text)
                self.is_saved = True
    
        def save_as_func(self, text):
            self.path, _ = QFileDialog.getSaveFileName(self, 'Save File', './', 'Files (*.html *.txt *.log)')
            if self.path:
                with open(self.path, 'w') as f:
                    f.write(text)
                self.is_saved = True
                self.is_saved_first = False
    
        # Функция close_func() ниже аналогична методу реализации события закрытия окна. 
        # Обратите внимание, что поскольку в нашем блокноте используется цвет, мы не можем вызвать 
        # метод toPlainText() класса QTextEdit, поскольку этот метод получает чистый текст, 
        # цвет будет потерян. Метод toHtml() должен быть вызван для сохранения цвета;
        def close_func(self):
            if not self.is_saved:
                choice = QMessageBox.question(self, 'Save File', 'Do you want to save the text?',
                                              QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                if choice == QMessageBox.Yes:
                    self.save_func(self.text_edit.toHtml())
                    self.close()
                elif choice == QMessageBox.No:
                    self.close()
                else:
                    pass
    
        def closeEvent(self, QCloseEvent):
            if not self.is_saved:
                choice = QMessageBox.question(self, 'Save File', 'Do you want to save the text?',
                                              QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                if choice == QMessageBox.Yes:
                    self.save_func(self.text_edit.toHtml())
                    QCloseEvent.accept()
                elif choice == QMessageBox.No:
                    QCloseEvent.accept()
                else:
                    QCloseEvent.ignore()
    
        # Функция слота, связанная с помощью cut_action, выглядит следующим образом:
        # Метод self.text_edit.textCursor() может получить текущий указатель 
        #   текстового поля редактирования (тип QTextCursor), а затем вызвать метод selection(), 
        #   чтобы получить содержимое, в настоящий момент выбранное указателем, но типом в данный 
        #   момент является QTextDocumentFragment, мы Вам нужно вызвать метод toHtml(), 
        #   чтобы получить текстовое содержимое. 
        # Когда пользователь режет, обрезанный текст должен исчезнуть, 
        #   поэтому вызовите метод removeSelectedText() QTextCursor.
    
        def cut_func(self):
            self.mime_data.setHtml(self.text_edit.textCursor().selection().toHtml())
            self.clipboard.setMimeData(self.mime_data)
            self.text_edit.textCursor().removeSelectedText()
    
        # Функция слота copy_action выглядит следующим образом, метод тот же, за исключением того, 
        # что текст не нужно удалять в это время:
        def copy_func(self):
            self.mime_data.setHtml(self.text_edit.textCursor().selection().toHtml())
            self.clipboard.setMimeData(self.mime_data)
    
        # В слоте функции paste_action нам просто нужно вызвать метод insetHtml() 
        # для вставки текста в буфер обмена (этот метод вставит текст в позицию указателя):
        def paste_func(self):
            self.text_edit.insertHtml(self.clipboard.mimeData().html())
    
        def font_func(self):
            font, ok = QFontDialog.getFont()
            if ok:
                self.text_edit.setFont(font)
    
        def color_func(self):
            color = QColorDialog.getColor()
            if color.isValid():
                self.text_edit.setTextColor(color)
    
        # Слот-функция, связанная с about_action, является самой простой, 
        # просто откройте окно сообщения о Qt:
        def about_func(self):
            QMessageBox.aboutQt(self, 'About Qt')
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        demo = Demo()
        demo.show()
        sys.exit(app.exec_())
    

    在此处输入图像描述

    • 4

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5