VeighNa量化社区
你的开源社区量化交易平台
Member
加入于:
帖子: 60
声望: 8

在用vnstation的时候, 很多地方都要用户手动输入, 很多场景下都希望能够保存上次输入内容. 这个控件可以解决. vnstation的任何界面都可以继承这两个组件, 实现恢复上次输入内容(原来是Qdialog的, 继承RestorableQDialog, 原来是Qwidget的, 继承RestorableQWidget, 在ui初始化之后, 调用self.load_settings()方法即可), 原理是用Qsetting储存这些配置到注册表.

from PySide6.QtCore import QSettings
from PySide6.QtWidgets import QApplication, QVBoxLayout, QLineEdit

from PySide6 import QtWidgets


def func(x, y):
    y = set(y)
    for i in y:
        found = False
        for j in range(x.count()):
            if i == x.item(j).text():
                found = True
                break
        if not found:
            x.addItem(i)


SUPPORTED_TYPE = {
    "line_edit": {"type_": QtWidgets.QLineEdit, "func_setValue": lambda x, y: x.setText(y),
                  "func_getValue": lambda x: x.text()},
    "spinbox": {"type_": QtWidgets.QSpinBox, "func_setValue": lambda x, y: x.setValue(y),
                "func_getValue": lambda x: x.value()},
    "combobox": {"type_": QtWidgets.QComboBox, "func_setValue": lambda x, y: x.setCurrentText(y),
                 "func_getValue": lambda x: x.currentText()},
    "radio_btn": {"type_": QtWidgets.QRadioButton, "func_setValue": lambda x, y: x.setChecked(y),
                  "func_getValue": lambda x: int(x.isChecked())},
    "checkbox": {"type_": QtWidgets.QCheckBox, "func_setValue": lambda x, y: x.setChecked(y),
                 "func_getValue": lambda x: int(x.checkState())},
    "list_widget": {"type_": QtWidgets.QListWidget, "func_setValue": func,
                    "func_getValue": lambda x: list(x.item(i).text() for i in range(x.count()))}
}


class RestorableQDialog(QtWidgets.QDialog):
    COMPANY_NAME = "LXRestorableQDialog"

    def __init__(self, window_name):
        super().__init__()
        self.window_name = window_name

    def find_child(self):
        found_widget_dict = {}
        for group_name, d in SUPPORTED_TYPE.items():
            widget_list = [widget for widget in self.findChildren(d["type_"]) if not widget.objectName()]
            if widget_list:
                found_widget_dict[group_name] = widget_list
        return found_widget_dict

    def save_settings(self, found_widget_dict):
        settings = QSettings(self.COMPANY_NAME, self.window_name)

        for group_name, widget_list in found_widget_dict.items():
            get_func = SUPPORTED_TYPE[group_name].get("func_getValue")
            settings.beginGroup(group_name)
            for n, widget_ in enumerate(widget_list):
                value = get_func(widget_)
                settings.setValue(str(n), value)
            settings.endGroup()

        settings.sync()

    def closeEvent(self, e):
        super().closeEvent(e)
        self.save_settings(self.find_child())

    def accept(self) -> None:
        self.save_settings(self.find_child())
        super().accept()

    def load_settings(self):
        found_widget_dict = self.find_child()
        settings = QSettings(self.COMPANY_NAME, self.window_name)
        for group_name, widget_list in found_widget_dict.items():
            settings.beginGroup(group_name)
            for n, widget_ in enumerate(widget_list):
                set_func = SUPPORTED_TYPE[group_name].get("func_setValue")
                value = settings.value(str(n))
                if value is not None:
                    set_func(widget_, value)
            settings.endGroup()


class RestorableQWidget(QtWidgets.QWidget):
    COMPANY_NAME = "LXRestorableQWidget"

    def __init__(self, window_name):
        super().__init__()
        self.window_name = window_name

    def find_child(self):
        found_widget_dict = {}
        for group_name, d in SUPPORTED_TYPE.items():
            widget_list = [widget for widget in self.findChildren(d["type_"]) if not widget.objectName()]
            if widget_list:
                found_widget_dict[group_name] = widget_list
        return found_widget_dict

    def save_settings(self, found_widget_dict):
        settings = QSettings(self.COMPANY_NAME, self.window_name)

        for group_name, widget_list in found_widget_dict.items():
            get_func = SUPPORTED_TYPE[group_name].get("func_getValue")
            settings.beginGroup(group_name)
            for n, widget_ in enumerate(widget_list):
                value = get_func(widget_)
                settings.setValue(str(n), value)
            settings.endGroup()

        settings.sync()

    def closeEvent(self, e):
        super().closeEvent(e)
        self.save_settings(self.find_child())

    def load_settings(self):
        found_widget_dict = self.find_child()
        settings = QSettings(self.COMPANY_NAME, self.window_name)
        for group_name, widget_list in found_widget_dict.items():
            settings.beginGroup(group_name)
            for n, widget_ in enumerate(widget_list):
                set_func = SUPPORTED_TYPE[group_name].get("func_setValue")
                value = settings.value(str(n))
                if value is not None:
                    set_func(widget_, value)
            settings.endGroup()


class RestorableCustomQDialog(RestorableQDialog):
    def __init__(self):
        super().__init__(window_name=RestorableCustomQDialog.__name__)
        layout = QVBoxLayout()
        line_edit = QLineEdit()
        line_edit2 = QLineEdit()
        line_edit3 = QLineEdit()
        spin = QtWidgets.QSpinBox()
        btn = QtWidgets.QPushButton("accept")
        btn.clicked.connect(self.accept)


        layout.addWidget(line_edit)
        layout.addWidget(line_edit2)
        layout.addWidget(line_edit3)
        layout.addWidget(spin)
        layout.addWidget(btn)
        self.setLayout(layout)

    def show(self):
        self.load_settings()  # 在子类的show方法中调用load_settings()
        super().show()


if __name__ == "__main__":
    app = QApplication([])
    widget = RestorableCustomQDialog()
    widget.show()
    app.exec()

用法: 
例如回测界面的BacktestingSettingEditor
class BacktestingSettingEditor(RestorableQDialog):
    """
    回测参数配置界面.
    """

    def __init__(
            self, class_name: str, parameters: dict
    ) -> None:
        """"""
        super(BacktestingSettingEditor, self).__init__(BacktestingSettingEditor.__name__)

        self.class_name: str = class_name
        self.parameters: dict = parameters
        self.edits: dict = {}

        self.init_ui()
        self.load_settings()

修改super(BacktestingSettingEditor, self).init(BacktestingSettingEditor.name)
增加self.load_settings()

所有界面都可以用类似的办法实现restore用户输入内容

目前实现了6种常用组件的保存和恢复, 有pyqt基础的, 可以自行添加

Member
avatar
加入于:
帖子: 1472
声望: 105

感谢分享!

Administrator
avatar
加入于:
帖子: 4502
声望: 322

调整了下代码文字显示,帮你加个精华

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】