【问题标题】:How to go about monitoring change?如何监控变化?
【发布时间】:2018-09-07 04:30:47
【问题描述】:

背景故事:

我目前正在开发一个程序,其中包含多个qComboBoxqLineEdit 元素,用户可以在其中输入数据或选择一个值。当用户选择“新文件”或“打开文件”时,我想检查是否有任何值已更改,并为用户提供保存工作的选项。输出文件是 XML。

问题:

基本上,我只需要知道是否有任何值与默认值不同。我不关心确切的值有什么不同,我只需要知道它们是不同的。

我尝试通过在程序启动时创建一个包含初始值的元素树来使用 xmldiff,然后将其与具有当前值的第二个元素树进行比较。它似乎不能只给出真值或假值,而且第二个元素树的大小各不相同,所以我认为我不能简单地进行一对一的比较。

我尝试的第二件事是在元素更改时简单地设置一个布尔值,但我无法解释一个元素被重置为默认值。例如,如果qLineEdit 框没有值,并且用户输入了某些内容,那么会将布尔值设置为“true”;但是,如果他们返回并将该值更改回默认值,则结果也将为“true”。

我想知道是否有做这类事情的“最佳实践”,或者是否有人可以为我指明正确的方向。这似乎在大多数情况下应该是微不足道的,但我不知道如何处理。

编辑……添加了第二次尝试的示例。

import sys
from PyQt5.QtWidgets import *


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.modified = False
        self.edit1 = QLineEdit()
        layout = QGridLayout(self)
        layout.addWidget(self.edit1)

        self.edit1.editingFinished.connect(self.valueChanged)

    def valueChanged(self):
        print('valueChanged Event')
        self.modified = True

    def closeEvent(self, event):
        if self.modified:
            prompt = QMessageBox.warning(
                self, 'Save Changes?',
                'This document has been modified.\n'
                'Do you want to save these changes?',
                QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Cancel
        )

            if prompt == QMessageBox.Yes:
                event.accept()
            if prompt == QMessageBox.No:
                event.accept()
            if prompt == QMessageBox.Cancel:
                event.ignore()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 300, 100)
    window.show()
    sys.exit(app.exec_())

【问题讨论】:

  • 如果你要提供一个最小的例子来展示你实际尝试过的不同的东西(关键是让它最小化),这是一个很好的问题。
  • 实际上不需要显示任何对话框或 XML 内容。只做一些最小可运行的东西。
  • 我不太明白为什么这会得到如此多的赞成票......问题很清楚,提供的代码显示了所做的事情 - 并演示了问题。如果您在文本框中输入 smth,则会显示 onclose 弹出窗口,如果您再次清除文本框,它仍会显示:那是 不需要的行为。有几种方法可以实现想要的东西,而且问题很容易回答 - 无论是在代码中还是在概念中。
  • @PatrickArtner 我建议不仅要考虑问题的当前状态,还要了解问题具有生命周期,也就是说,您正在限定当前问题而不是初始问题,并且例如,可能那些投票关闭的人只看到了没有 MCVE 的先前状态。 :)
  • 我认为这部分是我的错。我试图解释一个我遇到的复杂问题,而不是写一本关于正在发生的事情的小说。

标签: python python-3.x pyqt pyqt5


【解决方案1】:

具有默认值的成员字典:

使用{ qline1Name: "tata", qcombo: 2, ...} 创建一个dict。它将您的 instances 作为键及其初始值。保存时检查是否有任何当前值与其中存储的值不同并采取相应措施。您必须区分用作输入元素的几个类 - 对于组合框,可以使用初始选定的索引。

派生/猴子补丁/装饰:

您可以派生/猴子补丁/装饰您的 Q*-输入并为它们添加 default_value 属性。在创建时设置它并在保存时评估:

(错误)使用现有字段:

QLineEdit 有 QLineEdit.placeholderText,您可以将其用于“默认值”并简单地比较它(除非您的 defaultText 是空格 - 它们被取消了)。

更通用的方法是利用QWidget.whatsThis QString 字段。这样一来,所有输入元素只能使用一个属性,您可以if isinstance(...): 在将其与实际值进行比较时将其转换为 QString 值。

【讨论】:

  • 无需重新发明轮子或求助于hackery:Qt 提供了一个通用的Undo/Redo Framework,旨在解决此类问题。
  • 我曾考虑为此使用字典,但我认为这不是解决此问题的最有效方法。我也没有尝试在代码中实现任何骇人听闻的东西。我想让事情尽可能干净和易于理解。 @ekhumoro,我阅读了撤消/重做框架,但我不确定这将如何帮助解决问题。如果我可以简单地执行xmlTree1 != xmlTree2 并根据比较得到一个真或假值,这将不是一个真正的问题。
  • 我认为我最关心的是在程序运行期间处理更改检测的行业标准。
  • @AaronTomason 你确定你真的读过它吗?撤消堆栈的设计正是为了在程序运行期间处理更改检测。
  • @ekhumoro 我看到了你在说什么,但我仍然在用一个最小的程序来解决这个问题。我之前没有使用过QUndoStack,似乎我可以使用isClean() 跟踪是否发生了“更改”,并在保存时适当地设置标志以重置状态。我仍然不知道我是否可以使用它来检测一个值是否等于默认值。似乎这需要在每个更改方法中实现。
猜你喜欢
  • 2010-10-13
  • 2012-05-18
  • 2013-06-02
  • 1970-01-01
  • 2010-12-14
  • 2014-03-16
  • 2011-10-25
  • 1970-01-01
  • 2023-02-10
相关资源
最近更新 更多