2017-12-04 50 views
0

델파이가 몇 년 전에 액션을 도입했을 때 커다란 이점 중 하나는 액션의 상태 (활성화/비활성화)가 프로그래머가 생각해야했던 것보다 이벤트 루프에서 처리된다는 것입니다 이 상태를 응용 프로그램의 모든 상태 변경에 부합되게 업데이트하는 방법에 대해 설명합니다. 예를 들면 :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는을 사용하여 파이썬에서 이러한 오래된 델파이 프로그램의 일부를 다시하려고하지만, 지금까지 내가 어떻게 알아 내기 위해 실패 콘텐츠가 변경 될 때마다 명시 적으로 설정하지 않고도 QActions를 사용하도록 설정할 수 있습니다. 이것을하기위한 유익한 접근 방법은 무엇입니까? C++에서

+0

:

업데이트

종래 신호 슬롯 메커니즘을 사용하려면, 위 코드에서 참조 카운팅 문제를 해결

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

Weakrefs처럼 행동 자손 http://toc.qt.io/qt-5/qobject.html#sender에 대한 Qt에서 사용 가능하며'qobject_cast'를 사용하여'sender()'에서'QAction' 타입을 얻을 수 있습니다. 'onContentChanging'이 슬롯 함수 여야합니다. 나는 이것에 대한 답을 줄 것이지만 나는 Qt/C++ 만한다. – AlexanderVX

+1

@AlexanderVX OP는 첫 번째 코드 조각과 같은 것을 원하지만 ** 두 번째 코드 조각은 아닙니다. –

+0

미안합니다. SaveActionUpdate 슬롯이 필요하고 거기에 보낸 사람을 처리 할 수 ​​있습니다. – AlexanderVX

답변

0

나는 그것이이 구현 어떻게 볼 수 VCL에 뛰어 들었다. 나는 그렇게하는 것이 좋은 생각인지 주저했다. 왜냐하면이 프레임 워크의 개념은 Qt와는 완전히 다르고 도움이되기보다는 나를 잘못된 길로 인도 할 수 있기 때문이다. 그러나이 질문에 대한 답변이 없으면 Qt 조치가이 방법으로 작동하지 않을 수도 있음을 나에게 알립니다. 어느 쪽이 유감이다.

델파이의 VCL 액션은 이벤트 루프에서 애플리케이션의 유휴 시간으로 평가되는 중앙 목록에 자신을 등록합니다. 등록되지 않은 때 다시

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

메모리 언어는 객체를 가지고 열심히 비트입니다 프로그램 관리 : 내가 타이머를 사용하여 Qt를 에뮬레이트 할 수 있습니다 발견 적어도이 따라서 나는이 주위에 출근 시간 제한은 0으로 시작 등록 된 개체가 완료됩니다. 너무 쉽게 개체는 여전히 레지스터에 참조를 가지고 있기 때문에 살아있게됩니다. 나는 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