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

Posted

技术标签:

【中文标题】我想在应用程序关闭时保存 PyQt5 设置【英文标题】:I want to save PyQt5 settings when application close 【发布时间】:2020-02-08 02:21:23 【问题描述】:

。这是因为下次我再次运行它时,它将以最终设置运行。所以,我写了这样的代码。

这是一个主用户界面代码。

# 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_())

这是一个子用户界面代码。

# 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。更改了 frameGeometry

我运行了这个程序,然后单击 [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) 

frameGeometry 值自行改变。

这是我程序的原始问题。

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)

===

如何使 frameGeometry 值保持一致?

2。无法保存 sub_ui 设置。

当这个程序关闭时,它会返回错误。

RuntimeError: QSettings 类型的包装 C/C++ 对象已被删除

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

我怎么能做我想做的事?

【问题讨论】:

提供minimal reproducible example 好的,我会更新的。 好的,你可以解释一下你的意思但是“self.frameGeometry()”的值改变了,你说的不是很清楚 【参考方案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)

    在__del__方法中,依赖SubUI作为子widget的对象已经被销毁,在OP获取的错误信息中有所说明。

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

ma​​in_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"))

【讨论】:

非常感谢!!!它运作良好。 :) 这是第一件事的结果。我只运行了 3 次,然后通过单击 X 将其关闭。加载:PyQt5.QtCore.QRect(1289, 370, 544, 604) 保存:PyQt5.QtCore.QRect(1289, 370, 544, 604) 加载:PyQt5 .QtCore.QRect(1288, 339, 546, 636) 保存:PyQt5.QtCore.QRect(1288, 339, 546, 636) 加载:PyQt5.QtCore.QRect(1287, 308, 548, 668) 保存:PyQt5.QtCore .QRect(1287, 308, 548, 668) frameGeometry 值会自行改变。 糟糕,我会写在我的问题上。 @HoYa 编辑您的问题并指明您在代码的哪个部分进行“打印”,同时指明您的屏幕尺寸。 @HoYa 一个问题:你有没有将点击之间的窗口移动到“X”按钮?也就是说,假设你关闭窗口并返回打开,我理解当你关闭它时你没有移动窗口,对吗? @HoYa 您必须删除之前保存 QSettings 数据的文件,才能找到它的位置使用:print(QSettings("A", "B").filename())

以上是关于我想在应用程序关闭时保存 PyQt5 设置的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PyQt5 中正确显示图片? [关闭]

如何保存编辑的 PyQt5 TableWidget 单元格?

按下保存按钮pyqt5后关闭第二个小部件

当我使用 prettier 和 ESLint 在 VSCode 上保存代码时如何设置自动关闭?

矩形状态仅在单击 PyQt5 QML 时发生变化

在关闭应用程序之前保存值?