2017-12-04 40 views
0

Delphiが数年前にアクションを導入したとき、大きな利点の1つは、アクションのステータス(有効/無効)がイベントループで処理されたということでした。これらの状態をアプリケーションのすべての状態変更に合わせて更新することについてたとえば、次のようにQActionの有効化ステータスの更新

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を有効にすることができます。これを行うための実りあるアプローチは何でしょうか? C++で

+0

UPDATEは

は、従来の信号スロット機構を使用するには、上記のコードで参照カウントの問題を解決する

class UpdatedAction(QAction): update = pyqtSignal(QAction) def getUpdated(self): self.update.emit(self) 

Weakrefs様作用から派生しますそれは年齢のQtで利用できます:http://doc.qt.io/qt-5/qobject.html#sender 'qobject_cast'を使って' sender() 'から' QAction'型を得ることができます。 「onContentChanging」はスロット機能でなければなりません。私はこれに答えを与えるだろうが、私はQt/C++だけを行う。 – AlexanderVX

+1

@AlexanderVX OPは、最初のコード断片のようなものを望んでいます。** 2番目のコード断片ではありません。 –

+0

私は間違いました。 SaveActionUpdateスロットの必要性があり、そこで送信者を処理することができます。 – AlexanderVX

答えて

0

私はそれがそこに実装されています方法を確認するためにVCLに潜っ。このフレームワークのコンセプトは、Qtとはまったく違っていて、役に立たずに私を間違った方向に向けるかもしれないというコンセプトのため、そうすることをお勧めしますか?しかし、この質問に対する回答の欠如は、私には、Qtの行動がこのようにうまくいかない可能性があることを示唆しています。これは残念です。

DelphiのVCLアクションは、イベントループでアプリケーションのアイドル時間に評価される中央リストに組み込まれて登録されます。これは、少なくとも私は、タイマーを使ってQtの中でエミュレートすることができたタイムアウト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 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() 
0

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

私はこれをよく理解していれば、これはupdateProcとアクションの間の接続を定義しますが、スロットが頻繁にどのように通知されるのかを定義していませんか? – user508402

+0

質問を理解しても分かりませんが、一般的には:http://doc.qt.io/qt-5/signalsandslots.html – AlexanderVX

+0

カスタム信号を定義してupdateProcを呼び出すことは難しくありません。私の答えには表示されていませんが、私はすでにそれを行いました。私の疑問の核心は、他のオブジェクトに頼るよりも、アクションが自動的に更新されるようにすることです。アクション(またはその代理人)は、環境を監視し、有効にするかどうかを決定します。しかし、これを行うにはトリガーが必要です。 – user508402

関連する問題