**在应用程序中,我将新的 LineEdit 和 Pushbutton 添加到创建的 Gridlayout 中,并且需要在关闭时保存数据并为下一个会话加载数据。告诉我如何实现这个
**
这是一个示例界面
import sys
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QLabel, QGridLayout, QLineEdit, QPushButton, \
QMessageBox
from Designer.designerTest import Ui_MainWindow # Импорт класса Ui_MainWindow из другого модуля
#################################################################################################
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow() # Создание экземпляра класса Ui_MainWindow
self.ui.setupUi(self) # Инициализация UI элементов
self.layout = QVBoxLayout()
self.ui.widget_2.setLayout(self.layout) # Установка QVBoxLayout как layout для виджета widget_2
self.ui.btnSaveTopic.clicked.connect(
self.create_new_label) # Подключение функции create_new_label при нажатии на кнопку btnSaveTopic
###########################
def create_new_label(self): # Создание новой метки и вызов функции new_grid
if self.ui.lineTopic.text() != "":
text = self.ui.lineTopic.text()
label = QLabel(text)
label.setStyleSheet('color: white; font: 14pt;')
self.layout.addWidget(label)
self.new_grid() # Создание нового grid
self.ui.lineTopic.clear()
else:
QMessageBox.warning(None, "Ошибка", "Введите тему") # Показ предупреждающего сообщения
###########################
def new_grid(self): # Создание нового grid layout с элементами
grid = QGridLayout()
self.layout.addLayout(grid)
line_edit = self.create_new_line_edit()
grid.addWidget(line_edit, 0, 0)
plus_right = QPushButton()
plus_right.setFixedSize(20, 20)
plus_right.setIcon(QIcon("icons/iconPlus.svg"))
plus_right.setIconSize(QSize(14, 14))
plus_down = QPushButton()
plus_down.setFixedSize(20, 20)
plus_down.setIcon(QIcon("icons/iconPlus.svg"))
plus_down.setIconSize(QSize(14, 14))
grid.addWidget(plus_right, 0, 1)
grid.addWidget(plus_down, 1, 0)
plus_right.clicked.connect(lambda: self.create_new_btn_right(grid))
plus_down.clicked.connect(lambda: self.create_new_btn_down(grid))
self.column_stretch(grid) # Установка растягиваемости колонок и строк
###########################
def create_new_btn_down(self, grid): # Создание новой строки при нажатии на кнопку вниз
clicked_widget = self.sender()
# Получение позиции нажатого виджета в сетке
for i in range(grid.count()):
item = grid.itemAt(i)
if item.widget() == clicked_widget:
row, column = grid.getItemPosition(i)[:2]
break
else:
return
line_edit = self.create_new_line_edit()
plus_right = self.create_new_button(lambda: self.create_new_btn_right(grid))
plus_down = self.create_new_button(lambda: self.create_new_btn_down(grid))
grid.addWidget(line_edit, row, column)
grid.addWidget(plus_down, row + 1, column)
grid.addWidget(plus_right, row, column + 1)
###########################
def create_new_btn_right(self, grid): # Создание новой колонки при нажатии на кнопку вправо
clicked_widget = self.sender()
# Получение позиции нажатого виджета в сетке
for i in range(grid.count()):
item = grid.itemAt(i)
if item.widget() == clicked_widget:
row, column = grid.getItemPosition(i)[:2]
break
else:
return
line_edit = self.create_new_line_edit()
plus_right = self.create_new_button(lambda: self.create_new_btn_right(grid))
grid.addWidget(line_edit, row, column)
grid.addWidget(plus_right, row, column + 1)
self.column_stretch(grid)
###########################
@staticmethod
def column_stretch(grid): # Установка растягиваемой колонок и строк сетки
grid.setColumnStretch(grid.columnCount(), 1)
grid.setRowStretch(grid.rowCount(), 1)
@staticmethod
def create_new_line_edit(): # Создание нового QLineEdit
line_edit = QLineEdit()
line_edit.setFixedSize(30, 30)
line_edit.setStyleSheet("background-color: white; color: black; font: 10pt;")
line_edit.setAlignment(Qt.AlignCenter)
return line_edit
@staticmethod
def create_new_button(callback): # Создание новой кнопки
button = QPushButton()
button.setFixedSize(20, 20)
button.setIcon(QIcon("icons/iconPlus.svg"))
button.setIconSize(QSize(14, 14))
button.clicked.connect(callback)
return button
#################################################################################################
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
我尝试了使用 JSON、PICKLE、SQLITE3 的不同保存方法,但它对我不起作用
这是我通常做的事情:我保存每个小部件数据并以某种方式声明,以便稍后在下次打开应用程序时检索它。
对于下面的这个示例(这不是你的,我只是创建了一个较小的新示例,只是为了展示我是如何做到的),我将每个小部件状态(例如文本和用户角色数据)保存到 python 字典中对象,并使用json将其保存到文件中。
稍后,当应用程序再次加载时,将检索该文件数据,并将其从 Json 字符串转换回 python 字典对象。字典的每个键对应于代码内定义的小部件状态,并用于将小部件状态重置回文件中提示的状态。
现在,请注意,这个文件确实只是一个提示,其内容可能是错误的(因为它的 Json,任何用户都可以像 CSS 一样编辑它)。如果文件不存在,或者文件中存储的数据错误,因为我们的加载函数根本不应该失败,所以每个键总是准备好默认值。
from PySide2.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QComboBox, QMenuBar, QButtonGroup, QRadioButton
import json
CONTEXT_FILENAME = 'settings.json'
class Scene(QWidget):
def __init__(self):
super().__init__()
self.ledit = QLineEdit()
self.rdbA = QRadioButton('Option A')
self.rdbB = QRadioButton('Option B')
self.rdbC = QRadioButton('Option C')
self.combo = QComboBox()
self.group = QButtonGroup()
self.group.addButton(self.rdbA, 100)
self.group.addButton(self.rdbB, 200)
self.group.addButton(self.rdbC, 300)
self.combo.addItem('Item 1', 111)
self.combo.addItem('Item 2', 222)
self.combo.addItem('Item 3', 333)
layout = QVBoxLayout()
layout.addWidget(self.ledit)
layout.addWidget(self.rdbA)
layout.addWidget(self.rdbB)
layout.addWidget(self.rdbC)
layout.addWidget(self.combo)
layout.addStretch()
self.setLayout(layout)
# Saves current widget states and values into a context object, and convert it
# into a JSON String, which will be saved into a corresponding file that can be
# loaded later on.
#
# In Short:
# WIDGETS -> CONTEXT OBJ -> JSON STRING -> FILE
#
def save(self):
context = {}
context['ledit-text'] = self.ledit.text()
context['radio-selected'] = self.group.checkedId()
context['combo-current'] = self.combo.currentData()
try:
fp = open(CONTEXT_FILENAME, 'wb')
except Exception as error:
print('Failed to create the save: ', error)
return False
else:
data = b''
try:
data = json.dumps(context).encode('utf-8')
except Exception as error:
print('Failed to convert to JSON String: ', error)
fp.close()
return False
else:
fp.write(data)
fp.close()
return True
# Loads context saved as a JSON String in an known file, and reset each widget
# based on the loaded context. If no such file exists, use default values.
#
# In Short:
# FILE -> JSON STRING -> CONTEXT OBJ -> WIDGETS
#
def load(self):
context = {}
try:
fp = open(CONTEXT_FILENAME, 'rb')
except FileNotFoundError:
context = {}
except Exception as error:
print('another exception just occurred: ', error)
context = {}
else:
data = fp.read()
fp.close()
try:
context = json.loads(data.decode('utf-8'))
except Exception as error:
print('failed to load JSON String: ', error)
context = {}
self.ledit.setText(context.get('ledit-text', ''))
radio = context.get('radio-selected', -1)
button = self.group.button(radio)
if (button is not None):
button.setChecked(True)
else:
self.rdbA.setChecked(True)
index = self.combo.findData(context.get('combo-current', -1))
if (index == -1):
self.combo.setCurrentIndex(0)
else:
self.combo.setCurrentIndex(index)
# Catch the close event, and automatically save before the app closes.
def closeEvent(self, ev):
self.save()
ev.accept()
###
if __name__ == '__main__':
app = QApplication()
win = Scene()
win.load()
win.show()
app.exec_()