更新QAction的enabledstatus

2024-04-25 06:12:32 发布

您现在位置:Python中文网/ 问答频道 /正文

几年前,当Delphi引入actions时,最大的优点之一是action的状态(enabled/disabled)在事件循环中处理,而不是程序员必须考虑更新这些与应用程序的所有状态更改相关的状态。例如:

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,而不是在内容发生变化时显式地将其设置为enabled。什么是富有成效的方法?你知道吗


Tags: actionstrue状态事件enabledactionsender优点
2条回答
C++中的P>:

void MyForm::onSaveActionUpdateSlot() // must be a slot
{
    QAction* pAction = qobject_cast<QAction*>( sender() );
    if (pAction)  // if sent by QAction
       pAction->setEnbaled( this->contentHasChanged() );
}

我潜入VCL,看看它是如何在那里实现的。我犹豫这样做是否是个好主意,因为这个框架的概念可能与Qt有很大的不同,使我走上了错误的轨道,而不是有所帮助。然而,对这个问题的缺乏回应向我暗示,Qt操作可能不会以这种方式工作。很遗憾。你知道吗

Delphi的VCL操作在一个中心列表的构造中注册自己,该列表在事件循环的应用程序空闲时间中进行评估。我发现这至少可以在Qt中通过使用以timeout 0启动的计时器来模拟。因此,我来做这项工作:

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子代来注册它自己(也可以是一个用于更新的信号槽组合)。你知道吗

更新

采用传统的信号槽机构,从动作式下降

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

相关问题 更多 >