我想在应用程序关闭时保存 PyQt5 设置



我想在应用程序关闭时保存 PyQt5 设置。这是因为下次我再次运行它时,它将以最终设置运行。所以,我像这样编写代码。

这是一个主要的 UI 代码。

# main_ui.py
import sys
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QTabWidget, QVBoxLayout
from sub_ui import SubUI

class MainUI(QMainWindow):
def __init__(self):
super().__init__()
self.settings = QSettings("A", "B")
self.init_ui()
def init_ui(self):
tabs = QTabWidget()
tabs.addTab(SubUI(), "SubUI")
vlayout = QVBoxLayout()
vlayout.addWidget(tabs)
central_widget = QWidget()
central_widget.setLayout(vlayout)
self.setCentralWidget(central_widget)
self.setWindowTitle("MainUI")
if self.settings.contains("geometry"):
print("LOAD: " + str(self.settings.value("geometry")))
self.setGeometry(self.settings.value("geometry"))
else:
self.setGeometry(100, 100, 300, 300)
self.show()
def closeEvent(self, event):
print("SAVE: " + str(self.settings.value("geometry")))
self.settings.setValue("geometry", self.frameGeometry())

if __name__ == "__main__":
APP = QApplication(sys.argv)
ex = MainUI()
sys.exit(APP.exec_())

这是一个子 UI 代码。

# sub_ui.py
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QLineEdit

class SubUI(QWidget):
def __init__(self):
super().__init__()
self.settings = QSettings("A", "B")
self.label = QLabel("test")
self.lineedit = QLineEdit()
self.init_ui()
self.load_settings()
def __del__(self):
self.save_settings()
def init_ui(self):
hlayout = QHBoxLayout()
hlayout.addWidget(self.label)
hlayout.addWidget(self.lineedit)
self.setLayout(hlayout)
def save_settings(self):
self.settings.setValue("label", self.lineedit.text())
def load_settings(self):
if self.settings.contains("label"):
self.lineedit.setText(self.settings.value("label"))

有两个问题。

1. 更改框架几何形状

我运行了这个程序,只需单击[X]图标即可关闭。但是"self.frameGeometry(("值会发生变化。为什么会这样?

=== 更多信息 ===

我只是运行了上述程序三次,然后单击 X 将其关闭。

LOAD: PyQt5.QtCore.QRect(1289, 370, 544, 604) 
SAVE: PyQt5.QtCore.QRect(1289, 370, 544, 604) 
LOAD: PyQt5.QtCore.QRect(1288, 339, 546, 636) 
SAVE: PyQt5.QtCore.QRect(1288, 339, 546, 636) 
LOAD: PyQt5.QtCore.QRect(1287, 308, 548, 668) 
SAVE: PyQt5.QtCore.QRect(1287, 308, 548, 668) 

帧几何值自行更改。

这是我程序的一个原始问题。

LOAD: PyQt5.QtCore.QRect(852, 217, 1108, 1050)
SAVE: PyQt5.QtCore.QRect(851, 186, 1110, 1082)
LOAD: PyQt5.QtCore.QRect(851, 186, 1110, 1082)
SAVE: PyQt5.QtCore.QRect(850, 155, 1112, 1114)
LOAD: PyQt5.QtCore.QRect(850, 155, 1112, 1114)
SAVE: PyQt5.QtCore.QRect(849, 124, 1114, 1146)

===

如何使帧几何体值保持一致?

2.无法保存sub_ui设置。

当此程序关闭时,它将返回错误。

运行时错误: 已删除包装的 C/C++ 类型的 QSettings 对象

因此,我无法保存这些值。

我该怎么做我想做的事情?

  1. 我不会在Linux上重现它。但是您可以使用saveGeometry()restoreGeometry()
class MainUI(QMainWindow):
def __init__(self):
super().__init__()
self.settings = QSettings("A", "B")
self.init_ui()
def init_ui(self):
# ...
self.setWindowTitle("MainUI")
self.load_settings()
self.show()
def closeEvent(self, event):
self.save_settings()
super().closeEvent(event)
def save_settings(self):
self.settings.setValue("geometry", self.saveGeometry())
def load_settings(self):
if self.settings.contains("geometry"):
self.restoreGeometry(self.settings.value("geometry"))
else:
self.setGeometry(100, 100, 300, 300)
  1. __del__ 方法中,依赖于 SubUI 作为子小部件的对象已被销毁,这在 OP 获取的错误消息中有所指示。

    另一方面,只有窗口的closeEvent()方法(MainUI(,因为它是唯一关闭的方法,因此在QSettings中保存所有数据的适当方法实现了保存数据的通用方法。

main_ui.py

class MainUI(QMainWindow):
def __init__(self):
super().__init__()
self.settings = QSettings("A", "B")
self.init_ui()
def init_ui(self):
# ...
def closeEvent(self, event):
for w in self.findChildren(QWidget) + [self]:
if hasattr(w, "save_settings") and callable(w.save_settings):
w.save_settings()
super().closeEvent(event)
def save_settings(self):
self.settings.setValue("geometry", self.frameGeometry())

sub_ui.py

from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QLineEdit

class SubUI(QWidget):
def __init__(self):
super().__init__()
self.settings = QSettings("A", "B")
self.label = QLabel("test")
self.lineedit = QLineEdit()
self.init_ui()
self.load_settings()
def init_ui(self):
hlayout = QHBoxLayout(self)
hlayout.addWidget(self.label)
hlayout.addWidget(self.lineedit)
def save_settings(self):
self.settings.setValue("label", self.lineedit.text())
def load_settings(self):
if self.settings.contains("label"):
self.lineedit.setText(self.settings.value("label"))

最新更新