Resumo : neste tutorial, você aprenderá como usar a QMenu
classe PyQt para criar um menu para a aplicação.
Introdução à classe PyQt QMenu
A QMenu
classe permite criar um widget de menu em barras de menu, menus de contexto e menus pop-up. Este tutorial se concentra em como usar a QMenu
classe para criar menus em barras de menus.
Para criar um menu e adicioná-lo a uma barra de menu, siga estas etapas:
- Obtenha a barra de menu da janela principal chamando o
menuBar()
método doQMainWindow
objeto. - Adicione um menu à barra de menus usando o
método. OaddMenu()
retorna uma nova instância daaddMenu()
QMenu
classe.
A seguir mostramos como adicionar três menus à barra de menus da janela principal, incluindo Arquivo, Editar e Ajuda:
menu_bar = self.menuBar()
file_menu = menu_bar.addMenu('&File')
edit_menu = menu_bar.addMenu('&Edit')
help_menu = menu_bar.addMenu('&Help')
Linguagem de código: Python ( python )
Observe que o e comercial ( &
) define um atalho para ir para o menu ao pressionar a Alt
tecla. Por exemplo, para ir para o menu Arquivo, pressione o atalho de teclado Alt-F.
Depois de ter um menu, você pode adicionar itens a ele. Normalmente, você cria um QAction
e usa o addAction()
método do QMenu
objeto para adicionar ações ao menu.
Para adicionar um separador entre itens de menu, você usa o addSeparator()
método do QMenu
objeto.
Exemplo de PyQt QMenu
Criaremos um aplicativo editor de texto para demonstrar como usar a QMenu
classe:
Observe que os ícones usados neste aplicativo são do site icon8.com . Além disso, você pode baixá- los aqui .
Aqui está o programa completo:
import sys
from pathlib import Path
from PyQt6.QtWidgets import QApplication, QMainWindow, QTextEdit, QFileDialog, QMessageBox, QWidget, QVBoxLayout
from PyQt6.QtGui import QIcon, QAction
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowIcon(QIcon('./assets/editor.png'))
self.setGeometry(100, 100, 500, 300)
m = 30
self.title = 'Editor'
self.filters = 'Text Files (*.txt)'
self.set_title()
self.path = None
self.text_edit = QTextEdit(self)
# self.setCentralWidget(self.text_edit)
container = QWidget(self)
container.setLayout(QVBoxLayout())
container.layout().addWidget(self.text_edit)
self.setCentralWidget(container)
# container.setContentsMargins(5, 5, 5, 5)
menu_bar = self.menuBar()
file_menu = menu_bar.addMenu('&File')
edit_menu = menu_bar.addMenu('&Edit')
help_menu = menu_bar.addMenu('&Help')
# new menu item
new_action = QAction(QIcon('./assets/new.png'), '&New', self)
new_action.setStatusTip('Create a new document')
new_action.setShortcut('Ctrl+N')
new_action.triggered.connect(self.new_document)
file_menu.addAction(new_action)
# open menu item
open_action = QAction(QIcon('./assets/open.png'), '&Open...', self)
open_action.triggered.connect(self.open_document)
open_action.setStatusTip('Open a document')
open_action.setShortcut('Ctrl+O')
file_menu.addAction(open_action)
# save menu item
save_action = QAction(QIcon('./assets/save.png'), '&Save', self)
save_action.setStatusTip('Save the document')
save_action.setShortcut('Ctrl+S')
save_action.triggered.connect(self.save_document)
file_menu.addAction(save_action)
file_menu.addSeparator()
# exit menu item
exit_action = QAction(QIcon('./assets/exit.png'), '&Exit', self)
exit_action.setStatusTip('Exit')
exit_action.setShortcut('Alt+F4')
exit_action.triggered.connect(self.quit)
file_menu.addAction(exit_action)
# edit menu
undo_action = QAction(QIcon('./assets/undo.png'), '&Undo', self)
undo_action.setStatusTip('Undo')
undo_action.setShortcut('Ctrl+Z')
undo_action.triggered.connect(self.text_edit.undo)
edit_menu.addAction(undo_action)
redo_action = QAction(QIcon('./assets/redo.png'), '&Redo', self)
redo_action.setStatusTip('Redo')
redo_action.setShortcut('Ctrl+Y')
redo_action.triggered.connect(self.text_edit.redo)
edit_menu.addAction(redo_action)
about_action = QAction(QIcon('./assets/about.png'), 'About', self)
help_menu.addAction(about_action)
about_action.setStatusTip('About')
about_action.setShortcut('F1')
# status bar
self.status_bar = self.statusBar()
self.show()
def set_title(self, filename=None):
title = f"{filename if filename else 'Untitled'} - {self.title}"
self.setWindowTitle(title)
def confirm_save(self):
if not self.text_edit.document().isModified():
return True
message = f"Do you want to save changes to {self.path if self.path else 'Untitled'}?"
MsgBoxBtn = QMessageBox.StandardButton
MsgBoxBtn = MsgBoxBtn.Save | MsgBoxBtn.Discard | MsgBoxBtn.Cancel
button = QMessageBox.question(
self, self.title, message, buttons=MsgBoxBtn
)
if button == MsgBoxBtn.Cancel:
return False
if button == MsgBoxBtn.Save:
self.save_document()
return True
def new_document(self):
if self.confirm_save():
self.text_edit.clear()
self.set_title()
def save_document(self):
# save the currently openned file
if (self.path):
return self.path.write_text(self.text_edit.toPlainText())
# save a new file
filename, _ = QFileDialog.getSaveFileName(
self, 'Save File', filter=self.filters
)
if not filename:
return
self.path = Path(filename)
self.path.write_text(self.text_edit.toPlainText())
self.set_title(filename)
def open_document(self):
filename, _ = QFileDialog.getOpenFileName(self, filter=self.filters)
if filename:
self.path = Path(filename)
self.text_edit.setText(self.path.read_text())
self.set_title(filename)
def quit(self):
if self.confirm_save():
self.destroy()
if __name__ == '__main__':
try:
import ctypes
myappid = 'mycompany.myproduct.subproduct.version'
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
finally:
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
Linguagem de código: Python ( python )
Como funciona.
Primeiro, crie a janela principal usando a QMainWindow
classe:
class MainWindow(QMainWindow):
Linguagem de código: Python ( python )
Segundo, defina o ícone e a geometria da janela:
self.setWindowIcon(QIcon('./assets/editor.png'))
self.setGeometry(100, 100, 500, 300)
Linguagem de código: Python ( python )
Terceiro, inicialize os filtros do arquivo de texto e o título da janela e chame o set_title()
método para definir o título da janela:
self.filters = 'Text Files (*.txt)'
self.title = 'Editor'
self.set_title()
Linguagem de código: Python ( python )
O
método aceita um nome de arquivo. Se o nome do arquivo for omitido, o set_title()
método define o título da janela como set_title()
Untitled - Editor
. Caso contrário, ele define o título da janela usando o formato filename - Editor
:
def set_title(self, filename=None):
title = f"{filename if filename else 'Untitled'} - {self.title}"
self.setWindowTitle(title)
Linguagem de código: Python ( python )
Por exemplo, ao iniciar o programa pela primeira vez ou criar um novo arquivo, o título da janela será:
Se você abrir um arquivo, por exemplo, C:/temp/ test.txt
, o título da janela mudará para:
Quarto, inicialize uma variável que conterá o caminho do arquivo que está sendo aberto para edição:
self.path = None
Linguagem de código: Python ( python )
Observe que usaremos a Path
classe do pathlib
módulo para gerenciar o caminho do arquivo, lendo um arquivo de texto e gravando no arquivo de texto.
Quinto, crie um QTextEdit
widget e defina-o como widget central da janela principal:
self.text_edit = QTextEdit(self)
self.setCentralWidget(self.text_edit)
Linguagem de código: Python ( python )
Sexto, crie um QMenuBar
objeto chamando o menuBar()
método do QMainWindow
objeto:
menu_bar = self.menuBar()
Linguagem de código: Python ( python )
Sétimo, crie ações novas, abrir, salvar e sair e adicione-as ao file_menu
método addAction()
.
# new menu item
new_action = QAction(QIcon('./assets/new.png'), '&New', self)
new_action.setStatusTip('Create a new document')
new_action.setShortcut('Ctrl+N')
new_action.triggered.connect(self.new_document)
file_menu.addAction(new_action)
# open menu item
open_action = QAction(QIcon('./assets/open.png'), '&Open...', self)
open_action.triggered.connect(self.open_document)
open_action.setStatusTip('Open a document')
open_action.setShortcut('Ctrl+O')
file_menu.addAction(open_action)
# save menu item
save_action = QAction(QIcon('./assets/save.png'), '&Save', self)
save_action.setStatusTip('Save the document')
save_action.setShortcut('Ctrl+S')
save_action.triggered.connect(self.save_document)
file_menu.addAction(save_action)
file_menu.addSeparator()
# exit menu item
exit_action = QAction(QIcon('./assets/exit.png'), '&Exit', self)
exit_action.setStatusTip('Exit')
exit_action.setShortcut('Alt+F4')
exit_action.triggered.connect(self.quit)
file_menu.addAction(exit_action)
Linguagem de código: Python ( python )
Isso resultará no seguinte menu:
Oitavo, crie ações de desfazer e refazer e adicione-as ao menu de edição:
# edit menu
undo_action = QAction(QIcon('./assets/undo.png'), '&Undo', self)
undo_action.setStatusTip('Undo')
undo_action.setShortcut('Ctrl+Z')
undo_action.triggered.connect(self.text_edit.undo)
edit_menu.addAction(undo_action)
redo_action = QAction(QIcon('./assets/redo.png'), '&Redo', self)
redo_action.setStatusTip('Redo')
redo_action.setShortcut('Ctrl+Y')
redo_action.triggered.connect(self.text_edit.redo)
edit_menu.addAction(redo_action)
Linguagem de código: Python ( python )
Isso resultará no seguinte menu Editar:
Nono, crie a ação about e adicione-a ao menu Ajuda:
about_action = QAction(QIcon('./assets/about.png'), 'About', self)
help_menu.addAction(about_action)
about_action.setStatusTip('About')
about_action.setShortcut('F1')
Linguagem de código: Python ( python )
Isso resultará no seguinte menu:
Décimo, adicione a barra de status à janela principal usando o statusBar()
método do QMainWindow
objeto:
self.status_bar = self.statusBar()
Linguagem de código: Python ( python )
Observe que você aprenderá mais sobre o widget da barra de status no QStatusBar
tutorial .
Décimo primeiro, defina o confirm_save()
método que avisa ao usuário se deseja salvar o documento ou não. Se o usuário clicar no botão Sim, chame o save_document()
método para salvar o texto do QTextEdit
widget em um arquivo.
O confirm_save()
método retorna False
se o usuário clicar no botão Cancelar ou True
se o usuário clicar no botão Yes
ou :No
def confirm_save(self):
if not self.text_edit.document().isModified():
return True
message = f"Do you want to save changes to {self.path if self.path else 'Untitled'}?"
MsgBoxBtn = QMessageBox.StandardButton
MsgBoxBtn = MsgBoxBtn.Save | MsgBoxBtn.Discard | MsgBoxBtn.Cancel
button = QMessageBox.question(
self, self.title, message, buttons=MsgBoxBtn
)
if button == MsgBoxBtn.Cancel:
return False
if button == MsgBoxBtn.Save:
self.save_document()
return True
Linguagem de código: Python ( python )
Décimo segundo, defina o new_document()
método que será executado quando o usuário selecionar o item de menu Novo:
def new_document(self):
if self.confirm_save():
self.text_edit.setText('')
self.set_title()
Linguagem de código: Python ( python )
O new_document()
método chama o confirm_save()
método para salvar o documento e deixar o texto em QTextEdit
branco. Além disso, redefine o título da janela principal.
Décimo terceiro, defina o save_document()
método para salvar o texto do QTextEdit
widget em um arquivo de texto:
def save_document(self):
# save the currently openned file
if (self.path):
return self.path.write_text(self.text_edit.toPlainText())
# save a new file
filename, _ = QFileDialog.getSaveFileName(
self, 'Save File', filter=self.filters
)
if not filename:
return
self.path = Path(filename)
self.path.write_text(self.text_edit.toPlainText())
self.set_title(filename)
Linguagem de código: Python ( python )
Se o usuário abrir um arquivo, então self.path
is not None
, ele obtém o texto do QTextEdit
widget chamando o toPlainText()
método e salva o texto no arquivo especificado pelo objeto Path usando o write_text()
método.
Se o usuário não abriu um arquivo, o método mostra uma caixa de diálogo Salvar arquivo usando QFileDialog
e grava o texto no arquivo que está aberto no momento.
Décimo quarto, defina o open_document()
método que mostra a caixa de diálogo Abrir arquivo e carrega o conteúdo de um arquivo de texto no QTextEdit
widget:
def open_document(self):
filename, _ = QFileDialog.getOpenFileName(self, filter=self.filters)
if filename:
self.path = Path(filename)
self.text_edit.setText(self.path.read_text())
self.set_title(filename)
Linguagem de código: Python ( python )
Como o nome do arquivo muda, ele chama o set_title()
método para definir o título do arquivo QMainWindow
.
Décimo quinto, defina o quit()
método que será executado quando o usuário selecionar o item de menu Sair:
def quit(self):
if self.confirm_save():
self.destroy()
Linguagem de código: Python ( python )
Finalmente, se você executar o programa no Windows, a barra de tarefas não exibirá o ícone da janela principal corretamente. Para corrigir isso, você usa o seguinte código:
import ctypes
myappid = 'mycompany.myproduct.subproduct.version'
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
Linguagem de código: JavaScript ( javascript )
Se você executar o programa no macOS ou Linux, este código gerará um erro de importação. Portanto, nós o envolvemos em um try
bloco:
try:
import ctypes
myappid = 'mycompany.myproduct.subproduct.version'
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
finally:
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
Linguagem de código: JavaScript ( javascript )
Resumo
- Qt usa a
QMenu
classe para representar um widget de menu. - Use o
menuBar()
métodoQMainWindow
para criar uma barra de menu eaddMenu()
o método para adicionar uma nova barra de menu. - Use o
addAction()
método doQMenu
objeto para adicionar um item a um menu.