Table of Contents
PyQt5 Open File Dialog and Text Editor
A small text editor is a good first PyQt5 project because it uses several common Qt ideas: a main window, a central widget, menus, actions, and a file dialog.
The example below creates a simple editor that can open a text file, display it in a QTextEdit, edit the content, and save it back to disk.
Example
import sys
from PyQt5.QtWidgets import (
QAction,
QApplication,
QFileDialog,
QMainWindow,
QMessageBox,
QTextEdit,
)
class TextEditor(QMainWindow):
def __init__(self):
super().__init__()
self.current_file = None
self.editor = QTextEdit()
self.setCentralWidget(self.editor)
self.init_ui()
def init_ui(self):
self.setWindowTitle("PyQt5 Text Editor")
self.resize(800, 600)
open_action = QAction("Open", self)
open_action.setShortcut("Ctrl+O")
open_action.triggered.connect(self.open_file)
save_action = QAction("Save", self)
save_action.setShortcut("Ctrl+S")
save_action.triggered.connect(self.save_file)
save_as_action = QAction("Save As", self)
save_as_action.setShortcut("Ctrl+Shift+S")
save_as_action.triggered.connect(self.save_file_as)
exit_action = QAction("Exit", self)
exit_action.setShortcut("Ctrl+Q")
exit_action.triggered.connect(self.close)
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(open_action)
file_menu.addAction(save_action)
file_menu.addAction(save_as_action)
file_menu.addSeparator()
file_menu.addAction(exit_action)
def open_file(self):
file_name, _ = QFileDialog.getOpenFileName(
self,
"Open File",
"",
"Text Files (*.txt);;Python Files (*.py);;All Files (*)",
)
if not file_name:
return
try:
with open(file_name, "r", encoding="utf-8") as file:
self.editor.setPlainText(file.read())
except OSError as error:
QMessageBox.critical(self, "Open Error", str(error))
return
self.current_file = file_name
self.setWindowTitle(f"PyQt5 Text Editor - {file_name}")
def save_file(self):
if self.current_file is None:
self.save_file_as()
return
try:
with open(self.current_file, "w", encoding="utf-8") as file:
file.write(self.editor.toPlainText())
except OSError as error:
QMessageBox.critical(self, "Save Error", str(error))
def save_file_as(self):
file_name, _ = QFileDialog.getSaveFileName(
self,
"Save File",
"",
"Text Files (*.txt);;Python Files (*.py);;All Files (*)",
)
if not file_name:
return
self.current_file = file_name
self.save_file()
self.setWindowTitle(f"PyQt5 Text Editor - {file_name}")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TextEditor()
window.show()
sys.exit(app.exec_())
How It Works
QMainWindow gives the application a standard window structure. The QTextEdit widget is placed in the center of the window with setCentralWidget().
QAction objects define the menu commands. Each action is connected to a method with the signal-slot mechanism:
open_action.triggered.connect(self.open_file)
The file dialog returns two values: the selected file path and the selected filter. In this example, only the path is needed:
file_name, _ = QFileDialog.getOpenFileName(self, "Open File")
If the user cancels the dialog, file_name is empty, so the function returns without doing anything.
Running the Program
Install PyQt5 if it is not already available:
pip install PyQt5
Save the script as text_editor.py, then run:
python text_editor.py
This is still a minimal editor. Useful next steps would be adding unsaved-change warnings, line numbers, recent files, and support for different encodings.
