Приложение неправильно сохраняет файлы, что делать?

Приложение неправильно сохраняет файлы, что делать?

Думаю дело в том, что у нас объект self.tab пересоздается и self.tab.path переопределяется, и поэтому нужно переписывать класс Widget, чтобы все заработало. Хотелось бы сохранять файлы, с помощью присвоенного path объекту, если это возможно конечно. Но я пока не понимаю как это сделать.

Пример неправильного сохранения файла:

изначально было 2 файла:

введите сюда описание изображения

введите сюда описание изображения введите сюда описание изображения

Я изменяю текст в gg.txt:

введите сюда описание изображения

И нажимаю на кнопку сохранить в меню "Файл".

В итоге получаю, что файл gg.txt не сохранился, а изменился файл hello.txt

введите сюда описание изображения

Код:

import sys
from pathlib import Path
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt5.QtWidgets import *

class Widget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.textEdit = QtWidgets.QTextEdit(self)
        v_layout = QtWidgets.QVBoxLayout(self)
        v_layout.addWidget(self.textEdit)
        self.path = ''


class App(QtWidgets.QWidget):
    def __init__(self, parent):
        super().__init__()
        self.parent = parent

    def create_file(self):
        self.tab = Widget()
        self.tab.setObjectName("tab")
        self.parent.tabWidget.addTab(self.tab, "")
        str = f"NEW {self.parent.val}"
        self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), str)
        self.parent.val += 1

    def open(self):
        path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл', '')
        if path:
            with open(path, "r") as file:
                text = file.read()
            self.tab = Widget()
            self.tab.setObjectName("tab")
            self.parent.tabWidget.addTab(self.tab, "")
            name_file = Path(path).resolve().stem
            self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), name_file)
            self.tab.path = path
            self.tab.textEdit.setText(text)


    def close_tab(self, ind):
        self.parent.tabWidget.removeTab(ind)

    def save(self):
        if not self.parent.tabWidget.count():
            return
        if self.tab.path:
            with open(self.tab.path, "w") as file:
                text = self.parent.tabWidget.currentWidget().textEdit.toPlainText()
                file.write(text)
        else:
            self.save_as()

    def save_as(self):
        path, _ = QFileDialog.getSaveFileName(self, "Save file", ".txt")
        self.tab.path = path
        text = self.parent.tabWidget.currentWidget().textEdit.toPlainText()
        name = Path(path).resolve().stem
        self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), name)
        print(self.tab.path)
        with open(path, "w") as file:
            file.write(text)

class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.app = App(self)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.tabCloseRequested.connect(self.app.close_tab)
        self.action_2.triggered.connect(self.app.create_file)
        self.action.triggered.connect(self.app.save)
        self.action_3.triggered.connect(self.app.open)
        self.val = 0

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(381, 265)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(10, 10, 361, 201))
        self.tabWidget.setObjectName("tabWidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 381, 21))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        self.menu_2 = QtWidgets.QMenu(self.menu)
        self.menu_2.setObjectName("menu_2")
        MainWindow.setMenuBar(self.menubar)
        self.action = QtWidgets.QAction(MainWindow)
        self.action.setObjectName("action")
        self.action_2 = QtWidgets.QAction(MainWindow)
        self.action_2.setObjectName("action_2")
        self.action_3 = QtWidgets.QAction(MainWindow)
        self.action_3.setObjectName("action_3")
        self.menu.addAction(self.action)
        self.menu.addAction(self.action_2)
        self.menu.addAction(self.action_3)
        self.menu.addAction(self.menu_2.menuAction())
        self.menubar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.show()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menu.setTitle(_translate("MainWindow", "Файл"))
        self.menu_2.setTitle(_translate("MainWindow", "Файлы"))
        self.action.setText(_translate("MainWindow", "Сохранить"))
        self.action_2.setText(_translate("MainWindow", "Новый файл"))
        self.action_3.setText(_translate("MainWindow", "Открыть"))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = Ui_MainWindow()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Попробуйте так:

import sys
from pathlib import Path
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt5.QtWidgets import *

class Widget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.textEdit = QtWidgets.QTextEdit(self)
        v_layout = QtWidgets.QVBoxLayout(self)
        v_layout.addWidget(self.textEdit)
        
        self.path = ''        


class App(QtWidgets.QWidget):
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        
        self._path = []                                                         # +++

    def create_file(self):
        self.tab = Widget()
        self.tab.setObjectName("tab")
        self.parent.tabWidget.addTab(self.tab, "")
        str = f"NEW {self.parent.val}"
        self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), str)
        self.parent.val += 1

    def open(self):
        path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл', '')
        if path:
            with open(path, "r") as file:
                text = file.read()
            self.tab = Widget()
            self.tab.setObjectName("tab")
            self.parent.tabWidget.addTab(self.tab, "")
            name_file = Path(path).resolve().stem
            self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), name_file)
            self.tab.path = path
            self.tab.textEdit.setText(text)
# +++            
            ind  = self.parent.tabWidget.indexOf(self.tab)                        # +++
            d = {ind: path}                                                       # +++
            self._path.append(d)                                                  # +++             
            

    def close_tab(self, ind):
        self.parent.tabWidget.removeTab(ind)

    def save(self):
        if not self.parent.tabWidget.count():
            return
            
        tabWidget_currentIndex  = self.parent.tabWidget.currentIndex()                # +++
        _ind, _path  = [                                                              # +++ 
            [i, v.get(tabWidget_currentIndex) ] for i, v in enumerate(self._path) \
                if v.get(tabWidget_currentIndex, None) is not None                    # +++
        ][0]                                                                          # +++
        
        if _path:      # self.tab.path:                                               # +++ ---
#            with open(self.tab.path, "w") as file:                                   # ---
            with open(_path, "w") as file:                                            # +++
                text = self.parent.tabWidget.currentWidget().textEdit.toPlainText()
                file.write(text)
        else:
            self.save_as()

    def save_as(self):
        path, _ = QFileDialog.getSaveFileName(self, "Save file", ".txt")
        self.tab.path = path
        text = self.parent.tabWidget.currentWidget().textEdit.toPlainText()
        name = Path(path).resolve().stem
        self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), name)
        print(self.tab.path)
        with open(path, "w") as file:
            file.write(text)

class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.app = App(self)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.tabCloseRequested.connect(self.app.close_tab)
        self.action_2.triggered.connect(self.app.create_file)
        self.action.triggered.connect(self.app.save)
        self.action_3.triggered.connect(self.app.open)
        self.val = 0

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(381, 265)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(10, 10, 361, 201))
        self.tabWidget.setObjectName("tabWidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 381, 21))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        self.menu_2 = QtWidgets.QMenu(self.menu)
        self.menu_2.setObjectName("menu_2")
        MainWindow.setMenuBar(self.menubar)
        self.action = QtWidgets.QAction(MainWindow)
        self.action.setObjectName("action")
        self.action_2 = QtWidgets.QAction(MainWindow)
        self.action_2.setObjectName("action_2")
        self.action_3 = QtWidgets.QAction(MainWindow)
        self.action_3.setObjectName("action_3")
        self.menu.addAction(self.action)
        self.menu.addAction(self.action_2)
        self.menu.addAction(self.action_3)
        self.menu.addAction(self.menu_2.menuAction())
        self.menubar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.show()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menu.setTitle(_translate("MainWindow", "Файл"))
        self.menu_2.setTitle(_translate("MainWindow", "Файлы"))
        self.action.setText(_translate("MainWindow", "Сохранить"))
        self.action_2.setText(_translate("MainWindow", "Новый файл"))
        self.action_3.setText(_translate("MainWindow", "Открыть"))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = Ui_MainWindow()
    sys.exit(app.exec_())

введите сюда описание изображения



Update

Можно ли как-то сделать с использованием path объекта (self.tab.path)?

Sorry, я был не внимателен к вашему вопросу.

_path  = self.parent.tabWidget.currentWidget().path

import sys
from pathlib import Path
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt5.QtWidgets import *

class Widget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.textEdit = QtWidgets.QTextEdit(self)
        v_layout = QtWidgets.QVBoxLayout(self)
        v_layout.addWidget(self.textEdit)
        
        self.path = ''                                                        


class App(QtWidgets.QWidget):
    def __init__(self, parent):
        super().__init__()
        self.parent = parent

    def create_file(self):
        self.tab = Widget()
        self.tab.setObjectName("tab")
        self.parent.tabWidget.addTab(self.tab, "")
        str = f"NEW {self.parent.val}"
        self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), str)
        self.parent.val += 1

    def open(self):
        path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл', '')
        if path:
            with open(path, "r") as file:
                text = file.read()
            self.tab = Widget()
            self.tab.setObjectName("tab")
            self.parent.tabWidget.addTab(self.tab, "")
            name_file = Path(path).resolve().stem
            self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), name_file)
            self.tab.path = path
            self.tab.textEdit.setText(text)

    def close_tab(self, ind):
        self.parent.tabWidget.removeTab(ind)

    def save(self):
        if not self.parent.tabWidget.count():
            return
        _path  = self.parent.tabWidget.currentWidget().path                           # +++
        if _path:      # self.tab.path:                                               # +++ ---
#            with open(self.tab.path, "w") as file:                                   # ---
            with open(_path, "w") as file:                                         
                text = self.parent.tabWidget.currentWidget().textEdit.toPlainText()
                file.write(text)
        else:
            self.save_as()

    def save_as(self):
        path, _ = QFileDialog.getSaveFileName(self, "Save file", ".txt")
        self.tab.path = path
        text = self.parent.tabWidget.currentWidget().textEdit.toPlainText()
        name = Path(path).resolve().stem
        self.parent.tabWidget.setTabText(self.parent.tabWidget.indexOf(self.tab), name)
        print(self.tab.path)
        with open(path, "w") as file:
            file.write(text)

class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.app = App(self)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.tabCloseRequested.connect(self.app.close_tab)
        self.action_2.triggered.connect(self.app.create_file)
        self.action.triggered.connect(self.app.save)
        self.action_3.triggered.connect(self.app.open)
        self.val = 0

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(381, 265)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(10, 10, 361, 201))
        self.tabWidget.setObjectName("tabWidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 381, 21))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        self.menu_2 = QtWidgets.QMenu(self.menu)
        self.menu_2.setObjectName("menu_2")
        MainWindow.setMenuBar(self.menubar)
        self.action = QtWidgets.QAction(MainWindow)
        self.action.setObjectName("action")
        self.action_2 = QtWidgets.QAction(MainWindow)
        self.action_2.setObjectName("action_2")
        self.action_3 = QtWidgets.QAction(MainWindow)
        self.action_3.setObjectName("action_3")
        self.menu.addAction(self.action)
        self.menu.addAction(self.action_2)
        self.menu.addAction(self.action_3)
        self.menu.addAction(self.menu_2.menuAction())
        self.menubar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.show()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menu.setTitle(_translate("MainWindow", "Файл"))
        self.menu_2.setTitle(_translate("MainWindow", "Файлы"))
        self.action.setText(_translate("MainWindow", "Сохранить"))
        self.action_2.setText(_translate("MainWindow", "Новый файл"))
        self.action_3.setText(_translate("MainWindow", "Открыть"))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = Ui_MainWindow()
    sys.exit(app.exec_())
→ Ссылка