当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而不必在我的内容发生变化时明确地设置它。这样做有用的方法是什么?
答案 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()