Как написать класс, с подтверждением окончания обращения к нему и возможностью отмены последнего действия выполненного в нем?
Есть класс с двумя методами:
method1
прибавляет по единице (инкремент);method2
принимает строку и добавляет её в список.
Что нужно:
После окончания работы с методом (не после каждого вызова, а после того, как он стал не нужен) надо это обозначить, вызвав
escape_method()
.
Если забыли это сделать, то:- второй метод будет недоступен для обращения
- по окончании работы с классом (см. далее) не появится меню.
Также надо обозначить окончание работы с классом (вызов метода
escape_class()
).
Этот метод вернёт меню 'да' \ 'нет'.
- Если 'да' - изменения сохранились, и мы можем получить переменные.
- Если 'нет' - не сохранились.
Вызовется, только если отработавшие method1
и method2
были закрыты. После 'закрытия' класса можно получить my_list
и counter
через вызов get_data()
.
Единовременно в работе может быть только один метод (
method1()
илиmethod2()
), и надо понимать какой именно.
Этим занимается переменная, в которую записывается название текущего метода, и эту переменную можно получить. Она сохраняет это состояние между вызовами метода, и обнуляется после закрытия (escape_method
) текущего метода.Нужна возможность отмены последнего действия для
method1
иmethod2
.
Методы между собой не связаны; окончание работы одного не обязывает запускать другой.
Пункты 1 - 3 примерно сделал, но мне не нравится как (в частности, флажки это не очень надёжно). Как это переделать? Наверное, нужны декораторы или внешний управляющий класс/классы.
Кроме того, класс должен возвращать переменные my_list
и counter
только методом get_data
и только после своего закрытия (а значит и закрытия методов). Как это реализовать?
Пункт 4 получается очень громоздко, даже не хочу выкладывать. Как сделать отмену последней операции?
class DataProcessing:
def __init__(self):
self.my_list = [] # method1
self.counter = 0 # method2
self.current_method = 0 # текущий метод
self.are_methods_closed = True # флажок закрытия метода
self.is_class_closed = True # флажок закрытия класса
def method1(self):
if self.are_methods_closed:
self.are_methods_closed = False # начало сессии этого метода
self.current_method = 1
self.counter += 1
elif self.are_methods_closed == False and self.current_method == 1: # продолжение сессии этого метода
self.counter += 1
def method2(self, value):
if self.are_methods_closed:
self.are_methods_closed = False
self.current_method = 2
self.my_list.append(value)
elif self.are_methods_closed == False and self.current_method == 2:
self.my_list.append(value)
def escape_method(self):
self.are_methods_closed = True
self.current_method = 0
def escape_class(self):
if self.are_methods_closed:
text = input("Сохранить изменения? \n Введите Да либо Нет: ")
if text == 'Да':
print('Изменения сохранены')
self.is_class_closed = True
elif text == 'Нет':
print('Изменения не сохранены')
self.is_class_closed = True
else:
pass
def get_data(self, n):
if n == 1:
return(self.counter)
elif n == 2:
return (self.my_list)
Ответы (1 шт):
Я попробовал реализовать то, что вы написали.
Не факт, что я правильно понял то, что вы хотите сделать.
Попробуйте запустить мой пример и потихоньку нажимайте доступные кнопки и внимательно смотрите что происходит на экране.
import sys
import random
from PyQt5.Qt import *
class DataProcessing(QMainWindow):
def __init__(self):
super().__init__()
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.my_list = [] # method2
self.counter = 0 # method1
self.label_1 = QLabel("Method 1", alignment = Qt.AlignCenter)
self.label_2 = QLabel("Method 2", alignment = Qt.AlignCenter)
self.textBrowser_1 = QTextBrowser()
self.textBrowser_2 = QTextBrowser()
self.button_1 = QPushButton("Go method1")
self.button_1.clicked.connect(self.method1)
self.button_1.setCheckable(True)
self.button_2 = QPushButton("Go method2")
self.button_2.setCheckable(True)
self.button_2.clicked.connect(
lambda ch, value=None: self.method2(ch, value))
self.layout = QGridLayout(self.centralWidget)
self.layout.addWidget(self.label_1, 0, 0)
self.layout.addWidget(self.label_2, 0, 1)
self.layout.addWidget(self.textBrowser_1, 1, 0)
self.layout.addWidget(self.textBrowser_2, 1, 1)
self.layout.addWidget(self.button_1, 2, 0)
self.layout.addWidget(self.button_2, 2, 1)
self.timer = QTimer()
self.timer.timeout.connect(self._update)
self.timer.setInterval(1500)
self.timer.start()
def _update(self):
if self.button_1.isChecked():
self.method1(True)
elif self.button_2.isChecked():
value = random.randint(0, 100)
self.method2(True, value)
def method1(self, state):
""" method1 прибавляет по единице (инкремент) """
if state:
self.button_2.setEnabled(False)
self.button_1.setText("Остановить method1")
self.counter += 1
self.textBrowser_1.setHtml(
f'Работает method1.<br> counter = {self.counter}<br>')
else:
self.button_1.setText("Go method1")
self.button_2.setEnabled(True)
self.textBrowser_1.moveCursor(QTextCursor.End)
self.textBrowser_1.insertHtml(
'<b style="font-size: 22px; color: red">method1 отклучен</b> <br><br>')
self.escape_method()
def method2(self, state, value):
""" method2 принимает строку и добавляет её в список """
if state:
self.button_1.setEnabled(False)
if value:
self.button_2.setText("Остановить method2")
self.my_list.append(value)
self.textBrowser_2.setHtml(
f'Работает method2.<br> item = {value}; '
f'записей {len(self.my_list)}<br>')
else:
self.button_1.setEnabled(True)
self.button_2.setText("Go method2")
self.textBrowser_2.moveCursor(QTextCursor.End)
self.textBrowser_2.insertHtml(
'<b style="font-size: 22px; color: red">method2 отклучен</b> <br><br>')
self.escape_method()
def escape_method(self):
if not self.button_1.isChecked() and not self.button_2.isChecked():
self.escape_class()
def escape_class(self):
msg = QMessageBox.question(
self,
"Сообщение вопроса",
"Сохранить изменения? ",
QMessageBox.Yes | QMessageBox.No)
if msg == QMessageBox.Yes:
print('Изменения сохранены')
self.get_data()
else:
print('Изменения не сохранены')
self.method4()
def method4(self):
msg = QMessageBox(self)
msg.setWindowIcon(QIcon("icono.png"))
msg.setWindowTitle("Пользовательское сообщение")
msg.setIconPixmap(QPixmap("Qt.png").scaled(100, 100, Qt.KeepAspectRatio))
msg.setText("Это окно сообщения <b>ПОЛЬЗОВАТЕЛЬСКОЕ</b> ")
msg.setInformativeText(
"""Есть возможность отмены последнего действия для method1 или method2.
Выберите какое действие вы хотите отменить или откажитесь.
""")
buttonMethod1 = msg.addButton("method1", QMessageBox.YesRole)
buttonMethod2 = msg.addButton("method2", QMessageBox.AcceptRole)
buttonCancel = msg.addButton("Отменить", QMessageBox.RejectRole)
msg.exec_()
if msg.clickedButton() == buttonMethod1:
self.counter -= 1
self.textBrowser_1.insertHtml(
f'Отменено последнее действие method1.<br> '
f'counter = {self.counter}<br><br>')
elif msg.clickedButton() == buttonMethod2:
if not self.my_list:
# my_list - пустой
return
self.my_list.pop()
self.textBrowser_2.insertHtml(
f'Отменено последнее действие method2.<br> '
f'Всего элементов {len(self.my_list)}, '
f'последний item = {self.my_list[-1]}<br><br>')
elif msg.clickedButton() == buttonCancel:
pass
def get_data(self): #, n): n <---- ?
# if n == 1: return(self.counter)
# elif n == 2: return (self.my_list)
self.textBrowser_1.insertHtml(
f'''<b style="font-size: 18px; color: green">
== The End ==<br><br>
counter={self.counter}
</b> <br><br>''')
self.textBrowser_2.insertHtml(
f'''<b style="font-size: 18px; color: green">
== The End ==<br>
</b> <br>''')
for item in self.my_list:
self.textBrowser_2.insertHtml(
f'''<b style="font-size: 18px; color: green">
item={item}
</b> <br>''')
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setFont(QFont("Times", 12, QFont.Bold))
window = DataProcessing()
window.resize(600, 400)
window.show()
sys.exit(app.exec())