更新QAction的enabled-status

时间:2017-12-04 20:58:19

标签: python qt delphi action

当Delphi几年前引入动作时,其中一个很大的优点是动作的状态(启用/禁用)是在事件循环中处理的,而不是程序员必须考虑更新这些状态。应用程序的所有状态更改。例如:

procedure TMyForm.SaveActionUpdate(Sender: TObject) begin (sender as TAction).enabled := self.contentHasChanged(); end;

而不是

procedure TMyForm.onContentChanging(sender: TObject) begin SaveAction.enabled := True; SaveAsAction.enabled := True; RevertAction ... etc. end;

现在我正在尝试使用Qt在Python中重建一些旧的Delphi程序,但到目前为止,我没有弄清楚如何启用QActions而不必在我的内容发生变化时明确地设置它。这样做有用的方法是什么?

2 个答案:

答案 0 :(得分:0)

在C ++中:

sprintf()

答案 1 :(得分:0)

我潜入VCL,看看它是如何在那里实施的。我犹豫是否这样做是一个好主意,因为这个概念可能与Qt有很大的不同,并且让我走错了轨道而不是帮助。然而,对这个问题缺乏回应表明,Qt行动可能不会这样。很可惜。

Delphi的VCL操作在一个中心列表中进行构建,该列表在应用程序的事件循环空闲时间内进行评估。这至少我发现可以通过使用以超时0开始的计时器在Qt中模拟。因此我来到这个解决方法:

class HFClient(QMainWindow):

    def updateAction(self, action):
        action.setEnabled(False)

class ActionUpdater(QTimer):

    def __init__(self):
        super(ActionUpdater, self).__init__()
        self.members = {}
        self.timeout.connect(self.timerEvent)

    def add(self, action, updateProc):
        self.members[action] = updateProc

    def remove(self, action):
        del self.members[action] 

    def timerEvent(self, unused):
        # prevent being the last one to keep the object alive:
        done = [action for action in self.members if sys.getrefcount(action) < 5]
        for action in done:
            self.remove(action)

        # call registered method:
        for action, updateProc in self.members.items():
                updateProc(action)




if __name__ == '__main__':

    app = QApplication(sys.argv)
    w   = HFClient()
    w.show()

    updater = ActionUpdater()
    updater.start()

    a = QAction("save as", app)
    updater.add(a, w.updateAction)
#     del a        
    app.exec()

当注册对象完成后,内存管理的编程语言有点难以再次注册对象。对象很容易保持活着,因为它仍然在寄存器中有一个引用。我试图通过检查refcount与updater实例中引用的数量来避免这种情况。不过,我会重视一种更好的方法。

可以制作一个能够自我注册的QAction后代(也许是一个用于更新的信号槽组合)。

<强>更新

要使用传统的信号槽机制,请从Action中下载

class UpdatedAction(QAction):
    update = pyqtSignal(QAction)

    def getUpdated(self):
        self.update.emit(self)

Weakrefs解决了上面代码中的引用计数问题:

class ActionUpdater(QTimer):

    def __init__(self):
        super(ActionUpdater, self).__init__()
        self.members = []
        self.timeout.connect(self.timerEvent)

    def add(self, action):
        self.members.append(weakref.ref(action, self.remove))

    def remove(self, action):
        self.members.remove(action) 

    def timerEvent(self, unused):
        # call registered method:
        for action in self.members:
            action().getUpdated()