Вызов метода родительского класса PyQT
Есть некая программа с 2-мя окнами:
- 1-е главное окно (
main) где всё отображается; - 2-е окно добавления заметок (
AddNotesForm).
Так вот я никак не могу понять принцип работы сигналов и слотов.
Как сделать так, чтобы при закрытии дочернего окна (AddNotesForm) по крестику или кнопке, вызывался метод родительского окна (main) "обновление информации после добавления"?
Пробовал разные варианты и практически всегда получаю ошибки типа:
"AttributeError: object has no attribute".
Main
import sys
from PySide6 import *
# ----- Импорт форм и стилей
from PySide6 import QtWidgets, QtCore
from PySide6.QtCore import QSortFilterProxyModel, Qt
from PySide6.QtGui import QStandardItemModel, QStandardItem
from PySide6.QtWidgets import QToolBar, QHeaderView
from gui_MainWindow_Notes import Ui_MainWindow
from settingsForm import SettingsForm
from addToolboxForm import AddNotesForm
from imagesForNote import ImagesForNote
from utilsCommunalPaymentDialog import UtilsCommunalPayment
from synchronizedForm import SynchronizedFormForm
# ----- Импорт для работы с config.ini
import configparser
config = configparser.ConfigParser()
config.read('config.ini', encoding='utf-8-sig')
# ----- Импорт для работы с базой данных
from db import DbWork as dbexec
# ----- Импорт дополнительных функций и констант
from functions.Extensions import Extensions
class MainApp(QtWidgets.QMainWindow, Ui_MainWindow):
# ----- Конструктор класса
def __init__(self, name='admin'):
super().__init__()
self.setupUi(self) # Создание формы и Ui (наш дизайн)
self.showMaximized() # Показать наше окно на весь экран
self.createToolBarTextEditNote()
self.database = config["db"]["db_select"]
self.settingsWindow_action.triggered.connect(self.settingsDialog) # Запуск окна настроек по клику в menubar
self.exitApp_action.triggered.connect(self.exitProgramm) # Закрытие программы по клику в menubar
if self.database == "mysql":
self.connect = dbexec.create_connection_mysql(self)
elif self.database == "sqlite3" or self.database == "all":
self.connect = dbexec.create_connection_sqlite(self)
if self.connect == None:
mess = Extensions.showMessageBoxYesNo(self, "Соединение с БД", "Нет соединения c БД MySQL! \n Проверьте настройки подключения или переключитесь на другую БД. \n Переключиться?")
if mess == 1024:
self.settingsDialog()
else:
pass
else:
self.init_all()
self.tableView_Books.clicked.connect(self.selectedBooks) # Клик по книге (1 таблица) и вывод заметок (2 таблица)
self.tableView_Notes.clicked.connect(self.selectedNote) # Клик по заметке (2 таблица) и вывод содержимого заметки (textEdit_Notes)
self.textEdit_Notes.textChanged.connect(self.pushButton_saveNoteTextEdit.setEnabled(True)) # После
self.lineEdit_searchBooks.textChanged.connect(self.searchBook)
self.lineEdit_searchNote.textChanged.connect(self.searchNote)
self.comboBox_choiseBookForNote.currentIndexChanged.connect(self.on_combobox_changed)
self.lineEdit_titleNote.setText("")
self.textEdit_Notes.setText("")
self.label_NoteIdHidden.setText("")
def init_all(self):
self.loadDataAll() # Загрузка разделов заметок в левую таблицу при запуске программы
self.searchNote("") # Загрузка заметок в среднюю таблицу при запуске программы
self.pushButton_reloadAllMainDataWindow.clicked.connect(self.loadDataAll) # Обновление данных главного окна
self.pushButton_addNewNotes_Left.clicked.connect(self.addNotesDialog) # Запуск окна добавления разделов и заметок
self.utilsCommunalPaymentWindow_action.triggered.connect(self.utilsCommunalPaymentDialog) # Запуск окна утилиты/ЖКХ по клику в menubar
self.pushButton_imagesForNote.clicked.connect(self.imgForNote) # Запуск окна добавления или редактирования изображений для заметки
self.pushButton_syncDB.clicked.connect(self.syncDbForProgramm) # Запуск окна синхронизации
self.pushButton_deleteNoteTextEdit.clicked.connect(self.deleteNote) # Запуск окна добавления разделов и заметок
self.pushButton_saveNoteTextEdit.clicked.connect(self.changeNoteAndSave) # Сохранение заметки после редактирования
self.pushButton_deleteBook.clicked.connect(self.deleteBook) # Удаление раздела
def on_combobox_changed(self, value):
self.selectBook = self.comboBox_choiseBookForNote.currentIndex() # ID Выбранной книги
self.comboBox_choiseBookForNote.itemData(self.comboBox_choiseBookForNote.currentIndex()) # ID Выбранной книги для смены книги у выбранной заметки comboboks справа
# ----- Инициализация окна настроек
def settingsDialog(self):
self.w2 = SettingsForm(self)
self.w2.show()
# ----- Инициализация окна добавления заметок
def addNotesDialog(self):
self.w3 = AddNotesForm(self)
self.w3.show()
# ----- Инициализация окна утилиты/ЖКХ
def utilsCommunalPaymentDialog(self):
self.w4 = UtilsCommunalPayment(self)
self.w4.show()
# ----- Инициализация окна утилиты/ЖКХ
def syncDbForProgramm(self):
self.w5 = SynchronizedFormForm(self)
self.w5.show()
######### Тестовая функция
def clickCloseSubWindow(*args):
print("Дочернее окно закрыто")
def loadDataAll(self):
print("reload")
if self.database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = "SELECT * FROM books ORDER BY book_title DESC"
rowBooks = dbexec.execute_read_query_mysql(self, connect, sql)
elif self.database == "sqlite3" or self.database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = "SELECT * FROM books ORDER BY book_title DESC"
rowBooks = dbexec.execute_read_query_sqlite(self, connect, sql)
model = QStandardItemModel(len(rowBooks), 1)
model.setHorizontalHeaderLabels(['ID', 'Разделы'])
for row, book in enumerate(rowBooks):
model.setItem(row, 0, QStandardItem(str(book[0])))
model.setItem(row, 1, QStandardItem(str(book[1])))
filter_proxy_model = QSortFilterProxyModel()
filter_proxy_model.setSourceModel(model)
filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
filter_proxy_model.setFilterKeyColumn(0)
self.tableView_Books.verticalHeader().hide()
self.tableView_Books.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.tableView_Books.setModel(filter_proxy_model)
self.tableView_Books.setColumnHidden(0, True)
self.tableView_Books.setAlternatingRowColors(True)
for item_book in rowBooks:
self.comboBox_choiseBookForNote.addItem(item_book[1], item_book[0])
self.lineEdit_titleNote.setText("")
self.textEdit_Notes.setText("")
self.label_NoteIdHidden.setText("")
# self.tableView_Notes.setRowCount(0)
index = self.tableView_Books.currentIndex()
row = index.row()
index = self.tableView_Books.model().index(row, 0)
self.idBook = str(self.tableView_Books.model().data(index))
if self.database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = "SELECT * FROM notes WHERE note_parent = " + self.idBook + ""
rowNote = dbexec.execute_read_query_mysql(self, connect, sql)
elif self.database == "sqlite3" or self.database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = "SELECT * FROM notes WHERE note_parent = " + self.idBook + ""
rowNote = dbexec.execute_read_query_sqlite(self, connect, sql)
model = QStandardItemModel(len(rowNote), 1)
for row, book in enumerate(rowNote):
model.setItem(row, 0, QStandardItem(str(book[0])))
model.setItem(row, 1, QStandardItem(str(book[1])))
filter_proxy_model = QSortFilterProxyModel()
filter_proxy_model.setSourceModel(model)
filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
filter_proxy_model.setFilterKeyColumn(0)
self.tableView_Notes.verticalHeader().hide()
self.tableView_Notes.horizontalHeader().hide()
self.tableView_Notes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.tableView_Notes.setModel(filter_proxy_model)
self.tableView_Notes.setColumnHidden(0, True)
self.tableView_Notes.setAlternatingRowColors(True)
index = self.tableView_Notes.currentIndex()
row = index.row()
index = self.tableView_Notes.model().index(row, 0)
noteId = self.tableView_Notes.model().data(index)
if self.database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = "SELECT (SELECT COUNT(*) FROM images WHERE images.img_id_note = notes.note_id) as count, notes.*, books.book_title FROM notes LEFT JOIN books on books.book_id = notes.note_parent WHERE notes.note_id = " + noteId + ""
rowPage = dbexec.execute_read_query_mysql(self, connect, sql)
elif self.database == "sqlite3" or self.database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = "SELECT (SELECT COUNT(*) FROM images WHERE images.img_id_note = notes.note_id) as count, notes.*, books.book_title FROM notes LEFT JOIN books on books.book_id = notes.note_parent WHERE notes.note_id = " + noteId + ""
rowPage = dbexec.execute_read_query_sqlite(self, connect, sql)
index = self.comboBox_choiseBookForNote.findText(rowPage[0][6], QtCore.Qt.MatchFixedString)
if index >= 0:
self.comboBox_choiseBookForNote.setCurrentIndex(index)
for item in rowPage:
self.lineEdit_titleNote.setText(str(item[2]))
self.textEdit_Notes.setText(item[3])
self.pushButton_imagesForNote.setText("Изображения ( " + str(item[0]) + " )")
self.label_NoteIdHidden.setText(str(item[1])) # Устанеавливаем ID в скрытый лэйбл для сохранения, удаления или изображений
def createToolBarTextEditNote(self):
tool = QToolBar()
tool.addWidget(self.pushButton_undo_toolbar)
tool.addWidget(self.pushButton_repeat_toolbar)
self.toolBox_horizontalLayout.addWidget(tool)
search_text = search_text.upper()
if self.database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = "SELECT * FROM books WHERE book_search LIKE '%{}%' ORDER BY book_title DESC".format(search_text)
rowBooks = dbexec.execute_read_query_mysql(self, connect, sql)
elif self.database == "sqlite3" or self.database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = "SELECT * FROM books WHERE book_search LIKE '%{}%' ORDER BY book_title DESC".format(search_text)
rowBooks = dbexec.execute_read_query_sqlite(self, connect, sql)
model = QStandardItemModel(len(rowBooks), 1)
model.setHorizontalHeaderLabels(['ID', 'Заметки'])
for row, book in enumerate(rowBooks):
model.setItem(row, 0, QStandardItem(str(book[0])))
model.setItem(row, 1, QStandardItem(str(book[1])))
filter_proxy_model = QSortFilterProxyModel()
filter_proxy_model.setSourceModel(model)
filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
filter_proxy_model.setFilterKeyColumn(-1)
search_field = self.lineEdit_searchBooks
search_field.textChanged.connect(filter_proxy_model.setFilterRegularExpression)
self.tableView_Books.setModel(filter_proxy_model)
self.tableView_Books.setColumnHidden(0, Tru
if self.database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = "SELECT * FROM notes WHERE note_search LIKE '%{}%' ORDER BY note_title DESC".format(search_text.upper())
rowPage = dbexec.execute_read_query_mysql(self, connect, sql)
elif self.database == "sqlite3" or self.database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = "SELECT * FROM notes WHERE note_search LIKE '%{}%' ORDER BY note_title DESC".format(search_text.upper())
rowPage = dbexec.execute_read_query_sqlite(self, connect, sql)
model = QStandardItemModel(len(rowPage), 1)
model.setHorizontalHeaderLabels(['ID', 'Заметки'])
for row, note in enumerate(rowPage):
model.setItem(row, 0, QStandardItem(str(note[0])))
model.setItem(row, 1, QStandardItem(str(note[1])))
filter_proxy_model = QSortFilterProxyModel()
filter_proxy_model.setSourceModel(model)
filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
filter_proxy_model.setFilterKeyColumn(-1)
self.tableView_Notes.verticalHeader().hide()
self.tableView_Notes.horizontalHeader().hide()
self.tableView_Notes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
search_field = self.lineEdit_searchBooks
search_field.textChanged.connect(filter_proxy_model.setFilterRegularExpression)
self.tableView_Notes.setModel(filter_proxy_model)
self.tableView_Notes.setColumnHidden(0, True)
def exitProgramm(self):
sys.exit()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
omstools = MainApp()
app.exec()
AddNotesForm
#import uuid
from PySide6 import QtWidgets, QtCore
from gui_AddToolboxWindow_Notes import Ui_AddToolboxWindow
import configparser
config = configparser.ConfigParser()
config.read('config.ini', encoding='utf-8-sig')
from db import DbWork as dbexec
from functions.Extensions import Extensions
class AddNotesForm(QtWidgets.QMainWindow, Ui_AddToolboxWindow):
def __init__(self, parent=None):
super().__init__(parent, QtCore.Qt.Window)
self.setupUi(self) # Создание формы и Ui (наш дизайн)
self.show() # Показать наше окно
self.parrent = self.parent()
self.loadData()
self.saveBook_toolBox_pushButton.clicked.connect(self.addNewBook)
self.savePage_toolBox_pushButton.clicked.connect(self.addNewPage)
self.cancelAddBook_toolBox_pushButton.clicked.connect(self.destroy_window)
self.cancelAddPage_toolBox_pushButton.clicked.connect(self.destroy_window)
def loadData(self):
database = config["db"]["db_select"]
if database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = "SELECT * FROM books"
result = dbexec.execute_read_query_mysql(self, connect, sql)
elif database == "sqlite3" or database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = "SELECT * FROM books"
result = dbexec.execute_read_query_sqlite(self, connect, sql)
for item in result:
self.selectBook_addPage_toolBox_comboBox.addItem(item[1], item[0])
def addNewBook(self):
if not self.addBook_toolBox_lineEdit.text():
Extensions.showMessageBox(self, 'Ошибка', 'Необходимо заполнить все поля!')
pass
else:
database = config["db"]["db_select"]
#uuid_code = uuid.uuid4().hex
if database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = """INSERT INTO books (book_title, book_search) VALUES ('{}', '{}')""".format(self.addBook_toolBox_lineEdit.text(), self.addBook_toolBox_lineEdit.text().upper())
dbexec.execute_query_mysql(self, connect, sql)
prefix = "sqlite3"
dbexec.uniq_filename_sql(self, prefix, sql)
dbexec.sync_sql_execute(self, prefix, sql, Extensions.BOOK_PRIORITY)
elif database == "sqlite3" or database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = """INSERT INTO books (book_title, book_search) VALUES ('{}', '{}')""".format(self.addBook_toolBox_lineEdit.text(), self.addBook_toolBox_lineEdit.text().upper())
dbexec.execute_query_sqlite(self, connect, sql)
prefix = "mysql"
dbexec.uniq_filename_sql(self, prefix, sql)
dbexec.sync_sql_execute(self, prefix, sql, Extensions.BOOK_PRIORITY)
self.addBookSuccess_label.setText('Книга успешно добавлена!')
self.loadData()
def addNewPage(self):
noteTitle = self.addPage_toolBox_lineEdit.text()
selectBook = self.selectBook_addPage_toolBox_comboBox.itemData(self.selectBook_addPage_toolBox_comboBox.currentIndex())
noteText = self.addPageText_toolBox_textEdit.toPlainText()
if not noteTitle or selectBook is None:
Extensions.showMessageBox(self, 'Ошибка', 'Необходимо заполнить все поля!')
pass
else:
database = config["db"]["db_select"]
if database == "mysql":
connect = dbexec.create_connection_mysql(self)
sql = """INSERT INTO `notes` (`note_title`, `note_text`, `note_parent`, `note_search`) VALUES ('{}', '{}', {}, '{}');""".format(noteTitle, noteText, selectBook, noteTitle.upper() + " " + noteText.upper())
dbexec.execute_query_mysql(self, connect, sql)
prefix = "sqlite3"
dbexec.uniq_filename_sql(self, prefix, sql)
dbexec.sync_sql_execute(self, prefix, sql, Extensions.NOTE_PRIORITY)
elif database == "sqlite3" or database == "all":
connect = dbexec.create_connection_sqlite(self)
sql = """INSERT INTO `notes` (`note_title`, `note_text`, `note_parent`, `note_search`) VALUES ('{}', '{}', {}, '{}');""".format(noteTitle, noteText, selectBook, noteTitle.upper() + " " + noteText.upper())
dbexec.execute_query_sqlite(self, connect, sql)
prefix = "mysql"
dbexec.uniq_filename_sql(self, prefix, sql)
dbexec.sync_sql_execute(self, prefix, sql, Extensions.NOTE_PRIORITY)
self.addPageSuccess_label.setText('Заметка успешно добавлена!')
def destroy_window(self):
print("destroy_window")
self.parent.init_all
self.close()
def closeEvent(self, event):
self.parent.init_all
print("closeEvent")
Ответы (1 шт):
Я совсем недавно более подробно описывал принципы работы сигналов и слотов. Вы можете найти это описание в моих ответах.
class AddNotesForm(QtWidgets.QMainWindow):
# signal_close_notes_form = Signal() # PySide6 # <----
signal_close_notes_form = pyqtSignal() # PyQt5
...
def closeEvent(self, event):
print("\ncloseEvent")
self.signal_close_notes_form.emit() # <----
class MainApp(QtWidgets.QMainWindow):
def __init__(self, name='admin'):
super().__init__()
...
self.w3 = AddNotesForm(self)
self.w3.signal_close_notes_form.connect(self.loadDataAll) # <----
...
def loadDataAll(self): # <----
# Вывод разделов заметок в ...
print("reload")
q1469645_main.py
import sys
# установите свои импорты PySide6 # !!!
from PyQt5 import QtCore, QtGui, QtWidgets, QtTest
from PyQt5.Qt import *
from q1469645_addToolboxForm import AddNotesForm
class MainApp(QtWidgets.QMainWindow):
def __init__(self, name='admin'):
super().__init__()
self.centralwidget = QWidget(self)
self.setCentralWidget(self.centralwidget)
self.label = QtWidgets.QLabel('MainApp', alignment=Qt.AlignCenter)
self.pushButton_reloadAllMainDataWindow = QPushButton()
self.pushButton_reloadAllMainDataWindow.setText('Обновление данных главного окна')
# Обновление данных главного окна
self.pushButton_reloadAllMainDataWindow.clicked.connect(self.loadDataAll)
pushButton = QPushButton('Показать AddNotesForm')
pushButton.clicked.connect(self.addNotesDialog)
layout = QGridLayout(self.centralwidget)
layout.addWidget(self.label, 0, 0, 1, 2)
layout.addWidget(self.pushButton_reloadAllMainDataWindow, 1, 0)
layout.addWidget(pushButton, 1, 1)
self.w3 = AddNotesForm(self)
self.w3.signal_close_notes_form.connect(self.loadDataAll) # <----
def addNotesDialog(self):
self.w3.show()
def loadDataAll(self): # <----
# Вывод разделов заметок в ...
print("reload")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
omstools = MainApp()
omstools.show()
app.exec()
q1469645_addToolboxForm.py
import sys
# установите свои импорты PySide6 # !!!
from PyQt5 import QtCore, QtGui, QtWidgets, QtTest
from PyQt5.Qt import *
class AddNotesForm(QtWidgets.QMainWindow):
# signal_close_notes_form = Signal() # PySide6 # <----
signal_close_notes_form = pyqtSignal() # PyQt5
def __init__(self, parent=None):
super().__init__(parent, QtCore.Qt.Window)
# self.parrent = self.parent()
# print(f'{parent}')
# print(f'{self.parrent}')
self.centralwidget = QWidget(self)
self.setCentralWidget(self.centralwidget)
self.label = QtWidgets.QLabel('AddNotesForm', alignment=Qt.AlignCenter)
self.cancelAddPage_toolBox_pushButton = QPushButton()
self.cancelAddPage_toolBox_pushButton.setText('Обновление данных главного окна')
# Обновление данных главного окна
self.cancelAddPage_toolBox_pushButton.clicked.connect(self.close)
layout = QGridLayout(self.centralwidget)
layout.addWidget(self.label, 0, 0, 1, 2)
layout.addWidget(self.cancelAddPage_toolBox_pushButton, 1, 0)
def closeEvent(self, event):
print("\ncloseEvent")
self.signal_close_notes_form.emit() # <----
Да, чуть не забыл, вы должны научиться составлять минимально-воспроизводимые примеры, которые демонстрируют только суть проблемы, а не работу с БД.

