Hello mọi người!
Hiện tại mình đang làm 1 cái text editor nhỏ gọn có tên là Krystal và mình làm trên mạng. Link tutorial ở đây nếu như bạn cần.
Krystal về cơ bản đã khá hoàn thiện rồi. Nhưng chỉ có 1 vấn đề duy nhất, đó là ở tính năng Save
và Save As
của nó. Khi mình thử save 1 file có tên là test.txt
thông qua Krystal thì nó báo lỗi như sau:
expected str, bytes or os.PathLike object, not NoneType
Screenshot:
Mình gặp cái lỗi này không chỉ 1, mà là bất kì lần nào mình follow theo tutorial của trang web trên. Mà khi thử chạy code của nó (trang web có tính năng tải project bằng file zip) thì lại không sao cả. Mình không biết phải fix lỗi như thế nào. Nhờ ai đó giúp mình với.
Note: Project này sử dụng PyQt5
để tạo GUI. Nếu muốn run project thì nên tải lib PyQt5
thông qua pip
để chạy project.
Toàn bộ code:
# Import thư viện PyQt5 và thư viện sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
# class MainWindow, window chính của program
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
# Resize cửa sổ
self.resize(700, 500)
# Thêm phần editor để edit file vào trong window
self.editor = QPlainTextEdit()
self.setCentralWidget(self.editor)
# path của file
self.path = None
# Thêm menu 'File' và 'Path' vào trong
FileMenu = self.menuBar().addMenu("&File")
EditMenu = self.menuBar().addMenu("&Edit")
# Declare các commands nằm trong 2 menu
Undo = QAction("Undo", self)
Undo.triggered.connect(self.editor.undo)
Redo = QAction("Redo", self)
Redo.triggered.connect(self.editor.redo)
Cut = QAction("Cut", self)
Cut.triggered.connect(self.editor.cut)
Copy = QAction("Copy", self)
Copy.triggered.connect(self.editor.copy)
Paste = QAction("Paste", self)
Paste.triggered.connect(self.editor.paste)
SelectAll = QAction("Select All", self)
SelectAll.triggered.connect(self.editor.selectAll)
Open = QAction("Open File...", self)
Open.triggered.connect(self.openFile)
Save = QAction("Save", self)
Save.triggered.connect(self.saveFile)
SaveAs = QAction("Save As...", self)
SaveAs.triggered.connect(self.saveAsFile)
# Thêm các edit commands vào 'Edit' menu
EditMenu.addAction(Undo)
EditMenu.addAction(Redo)
EditMenu.addSeparator()
EditMenu.addAction(Cut)
EditMenu.addAction(Copy)
EditMenu.addAction(Paste)
EditMenu.addAction(SelectAll)
# Thêm các file commands vào 'File' menu
FileMenu.addAction(Open)
FileMenu.addAction(Save)
FileMenu.addAction(SaveAs)
#Show window
self.show()
# Ném vào user 1 cửa sổ báo error
def Critical(self, message):
mb = QMessageBox()
mb.setWindowTitle("Error")
mb.setText(message)
mb.exec_()
# Function dùng để mở file
def openFile(self):
path, _ = QFileDialog.getOpenFileName(self, "Open File", "",
"All files (*.*)")
if path:
try:
with open(path, "rU") as f:
text = f.read()
except Exception as e:
self.Critical(str(e))
else:
self.path = path
self.editor.setPlainText(text)
# Function dùng để save file
def saveFile(self):
if self.path is None:
return self.saveAsFile()
self.saveToPath(self.path)
# Function save file nhưng dưới dạng save as
def saveAsFile(self):
path, _ = QFileDialog.getSaveFileName(self, "Save", "", "All files(*.*)")
if not path:
return
self.saveToPath(self.path)
# Dùng để thực hiện quá trình file
def saveToPath(self, path):
text = self.editor.toPlainText()
try:
with open(path, 'w') as f:
f.write(text)
except Exception as e:
self.Critical(str(e))
else:
self.path = path
# biến app, đóng vai trò kích hoạt chương trình
app = QApplication(sys.argv)
app.setApplicationName("Krystal") # Set name cho app
# Window chính
window = MainWindow()
# Khởi động app
app.exec_()