在较为大型复杂,功能较多的应用程序中,我们通常继承QMainWindow类来进行开发。该主窗口为搭建应用用户界面提供了非常好的框架,请看下图:
可以看出该主窗口类为我们提供了菜单栏(Menu Bar)、工具栏(Tool Bar)、控件停靠区域(Dock Widgets)和状态栏(Status Bar),我们可以往其中加入很多自己想要的东西,这也使得我们可以快速地开发一个功能复杂并且界面友好的应用程序。
本章主要介绍菜单栏、工具栏和状态栏,控件停靠区域会放在后续章节。
23.1 记事本应用
接下来我们完成一个简易的记事本应用来了解一下QMainWindow的用法(其实就是对上一章22.2节中的程序再进行扩展):
(Mac上的菜单栏在屏幕左上方)
为保证代码敲击流畅,请先在程序中导入以下模块:
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__()
接着我们开始添加菜单栏、工具栏和状态栏:
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,该类通常与菜单栏和工具栏搭配使用。可以将一个动作看作一种命令,每当用户点击某个动作时,就会触发某种命令,程序从而执行相应的命令。那现在我们就要实例化几个动作:
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()
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)
这里一共实例化了11个动作,分别为:新建new_action、打开open_action、保存save_action、另存为save_as_action、关闭close_action、剪切cut_action、复制copy_action、粘贴paste_action、字体改变font_action、颜色改变color_action以及关于about_action。
既然是记事本的话,那肯定要有文本编辑器,所以在类的初始化函数中当然还要实例化一个QTextEdit控件:
self.text_edit = QTextEdit(self)
有剪切复制粘贴功能的话就让我们自然而然的想到了剪贴板以及QMimeData类 :
self.mime_data = QMimeData()
self.clipboard = QApplication.clipboard()
接下来我们往初始化函数中再添加以下代码:
self.setCentralWidget(self.text_edit) # 1
self.resize(450, 600)
self.menu_init() # 2
self.toolbar_init()
self.status_bar_init()
self.action_init()
self.text_edit_int()
1. 调用QMainWindow的setCentralWidget()方法可以设置主窗口的中央控件,这里我们将文本编辑框text_edit设置为中央控件。调用resize()方法将窗口设置到合适的大小;
2. 在代码量比较多的情况下,将各个对象分开来设置会让代码更加清晰,如果都同时挤在__init__()中的话会显得非常混乱,也不方便日后维护。
我们接下来看一下menu_init()函数,在这里我们将相应的动作添加到了菜单栏中:
def menu_init(self):
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)
可以看出我们调用addAction()方法就可以将动作添加进去。addSeparator()方法顾名思义就是加一个分割条,也就是让close_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)
接着是状态栏,状态栏设置非常简单,我们只