9.4 새 파일 열기
728x90

1. 목표
더보기
새 파일 메뉴를 눌렀을 때
- 현재 문서가 수정되어 있다면 먼저 저장 여부를 묻고
- 취소를 누르면 아무 일도 하지 않고
- 계속 진행을 선택하면 에디터를 깨끗한 새 문서 상태로 초기화한다.
저장 기능은 이전 단계에서 구현한 Qt 스타일 파일 저장 함수와
(QFile, QIODevice, QDir, QTextStream 기반)인 save_file 을 재사용한다.
2. 전체 로직
더보기
# mainwindow.py
from PySide6.QtWidgets import QMainWindow, QFileDialog, QMessageBox
from PySide6.QtCore import QFile, QIODevice, QDir, QTextStream
from ui_form import Ui_MainWindow
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.current_file = ''
self.ui.actionNew.triggered.connect(self.file_new)
self.ui.actionSave.triggered.connect(self.save_file)
def file_new(self):
if not self.maybe_save():
return
self.ui.textEdit.clear()
self.current_file = ''
self.ui.textEdit.document().setModified(False)
self.setWindowTitle('제목 없음 - 메모장')
def maybe_save(self) -> bool:
if not self.ui.textEdit.document().isModified():
return True
ret = QMessageBox.warning(
self,
'문서 저장',
'문서가 수정되었습니다.\n변경 내용을 저장하시겠습니까',
QMessageBox.StandardButton.Save
| QMessageBox.StandardButton.Discard
| QMessageBox.StandardButton.Cancel
)
if ret == QMessageBox.StandardButton.Save:
return self.save_file()
if ret == QMessageBox.StandardButton.Cancel:
return False
return True
def save_file(self) -> bool:
filename, _ = QFileDialog.getSaveFileName(
self,
'파일 저장',
QDir.homePath(),
'Text Files (*.txt);;All Files (*)'
)
if not filename:
return False
file = QFile(filename)
if not file.open(QIODevice.WriteOnly | QIODevice.Text):
QMessageBox.critical(self, '오류', f'파일을 열 수 없습니다:\n{file.errorString()}')
return False
stream = QTextStream(file)
stream << self.ui.textEdit.toPlainText()
file.close()
self.current_file = filename
QMessageBox.information(self, '저장 성공', f'파일이 저장되었습니다.\n\n{filename}')
return True
# main.py
import sys
from PySide6.QtWidgets import QApplication
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())
3. 필요한 import + 주석 설명
더보기
동일
4. 메뉴 액션과 슬롯 연결하기 (actionNew ↔ file_new)
더보기


class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# 현재 열려 있는 파일 경로를 기억하기 위한 멤버 변수
# 새 문서 상태에서는 빈 문자열로 둔다
self.current_file = ''
# 9.3 에서 이미 구현한 파일 저장 기능과 연결
# 새 파일을 만들 때 수정 내용 저장 여부를 묻기 위해 save_file 을 재사용한다
self.ui.actionSave.triggered.connect(self.save_file)
# 9.4 새 파일 열기 기능
# 메뉴의 새 파일 액션을 file_new 메서드에 연결한다
self.ui.actionNew.triggered.connect(self.file_new)
여기서 중요한 점은
새 파일 동작이 단독으로 존재하는 것이 아니라
반드시 save_file, maybe_save 와 함께 돌아간다는 점이다.
5. 실제 새 파일 열기 기능 구현 함수
더보기


5.1 새 파일 처리 함수 file_new

def file_new(self):
# 새 파일을 만들기 전에
# 현재 문서에 저장되지 않은 변경 사항이 있다면
# 먼저 저장 여부를 물어야 한다
if not self.maybe_save():
# maybe_save 가 False 를 반환하면
# 사용자가 저장 취소를 선택한 것이므로
# 새 파일 생성도 취소한다
return
# 여기까지 왔다면
# 1) 변경 사항이 없었거나
# 2) 변경 사항을 이미 저장했거나
# 3) 변경 사항을 버리겠다고 선택한 상태이다
# 에디터 내용을 지워서 완전히 새 문서 상태로 만든다
self.ui.textEdit.clear()
# 현재 파일 경로도 초기화한다
# 빈 문자열은 아직 디스크에 저장되지 않은 새 문서라는 의미로 사용한다
self.current_file = ''
# 수정 상태 플래그를 초기화한다
self.ui.textEdit.document().setModified(False)
# 창 제목을 새 문서임을 알 수 있도록 변경한다
self.setWindowTitle('제목 없음 - 메모장')
5.2 저장 여부를 묻는 함수 maybe_save

def maybe_save(self) -> bool:
# 문서가 수정되지 않았다면
# 바로 계속 진행해도 되므로 True 를 반환한다
if not self.ui.textEdit.document().isModified():
return True
# 여기까지 왔다는 것은
# textEdit 내용이 마지막 저장 이후로 변경되었다는 의미이다
# 사용자에게 변경 내용을 저장할지 물어본다
ret = QMessageBox.warning(
self,
'문서 저장',
'문서가 수정되었습니다.\n변경 내용을 저장하시겠습니까',
QMessageBox.StandardButton.Save
| QMessageBox.StandardButton.Discard
| QMessageBox.StandardButton.Cancel
)
# 저장 버튼을 눌렀다면
# save_file 을 호출해서 실제로 저장을 시도한다
# save_file 이 True 를 반환하면 계속 진행 가능
if ret == QMessageBox.StandardButton.Save:
return self.save_file()
# 취소 버튼을 눌렀다면
# 호출한 쪽에서 작업을 중단해야 하므로 False 를 반환한다
if ret == QMessageBox.StandardButton.Cancel:
return False
# 나머지 경우는 버리기 버튼을 누른 경우이므로
# 저장하지 않고 계속 진행해도 된다
return True
6. 실행
6. 실행 테스트
7.학습 주요 포인트
더보기
1 새 파일 기능의 핵심 구조
- 단순히 textEdit 를 clear 하는 것이 전부가 아니다.
- 반드시 다음 순서를 따라야 안전하다.
1 수정 여부 확인 maybe_save
2 사용자가 저장 또는 버리기 를 선택하면 새 문서로 초기화
3 취소를 선택하면 아무 것도 하지 않음
2 수정 여부 검사와 document modified 플래그
- QTextDocument 의 isModified 를 사용하면
에디터가 마지막 저장 이후로 변경되었는지 쉽게 확인할 수 있다. - 새 문서를 만들거나 저장을 완료한 뒤에는
setModified False 로 상태를 초기화해야 한다.
3 maybe_save 의 반환값 의미
- True 계속 진행해도 괜찮다.
새 파일 만들기, 프로그램 종료 등 다음 작업을 수행할 수 있다. - False 사용자가 취소를 눌렀으므로
호출한 쪽에서는 작업을 중단해야 한다.
4 Qt 파일 I O 와의 연계
- 새 파일 기능 자체는 디스크 I O 를 직접 사용하지 않지만
내부적으로 save_file 을 호출할 수 있으므로
저장 로직은 QFile, QIODevice, QTextStream 으로 구현되어 있어야
Qt 의 다른 부분과 자연스럽게 연결된다.
5 current_file 멤버의 역할
- 현재 열려 있는 파일의 경로를 저장하기 위해 사용한다.
- 새 파일일 경우 빈 문자열로 두어
아직 디스크에 저장되지 않은 문서라는 것을 표시할 수 있다. - 이후 단계에서
이미 파일 이름이 있는 경우에는 바로 덮어쓰기 저장을 하는 등
더 진화된 저장 로직을 만들 수 있다.
단계별 완성 파일





