2017-02-04 5 views
1

Qt 애플리케이션에서 나는 QCalendarWidget을 사용하고 있습니다. 마우스가 새 셀에 들어갈 때 알림을 받고 싶습니다. 나는 QCalendarWidget 내부 QAbstractItemView에서 상속 이는 QTableView를 사용하고 있음을 알고이는 entered 신호를 가지고 : 마우스 커서가 항목을 인덱스로 을 지정 들어갈 때PyQt : 셀이 QCalendarWidget에 입력되었을 때 신호를 내 보냅니다.

이 신호가 방출된다. 이 기능을 사용하려면 마우스 추적을 활성화해야합니다.

나는 다음과 같은 코드를 사용하여 신호를 수신하기 위해 노력 :

import sys 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

class MyCalendar: 

    def __init__(self): 
     app = QApplication(sys.argv) 

     window = QMainWindow() 
     cal = QCalendarWidget(window) 

     window.resize(320, 240) 
     cal.resize(320, 240) 

     table = cal.findChild(QTableView) 
     table.setMouseTracking(True) 
     table.entered.connect(self.onCellEntered) 

     window.show() 
     sys.exit(app.exec_()) 

    def onCellEntered(self, index): 
     print("CellEntered") 

if __name__ == "__main__": 
    window = MyCalendar() 

을하지만 내 콜백 함수가 호출되지 않습니다. 왜 그런 생각이 드나요?

+0

그것은 좋은 것 : 여기

는 것을 구현하는 데모 스크립트입니다. –

+0

@ GeorgSchölly 질문에있는 코드를 'QCalendarWidget'을 보여주는 작업 창 응용 프로그램으로 업데이트했지만 신호가 연결되었지만'onCellEntered' 메서드는 호출되지 않습니다. – Cilenco

답변

2

QCalendarWidget 클래스는 일반 마우스 이벤트 핸들러를 우회하는 사용자 정의 테이블 뷰를 사용하므로 enetered 신호가 방출되지 않습니다. 그러나 동일한 일을하는 사용자 정의 신호를 방출하는 이벤트 필터를 사용하여이를 해결할 수도 있습니다. 당신은 실행하고 문제를 표시 할 수있는 작은 예에 코드를 확장하는 경우

import sys 
from PyQt4 import QtCore, QtGui 

class Window(QtGui.QWidget): 
    cellEntered = QtCore.pyqtSignal(object) 

    def __init__(self): 
     super(Window, self).__init__() 
     self.calendar = QtGui.QCalendarWidget(self) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.calendar) 
     self._table = self.calendar.findChild(QtGui.QTableView) 
     self._table.setMouseTracking(True) 
     self._table.installEventFilter(self) 
     self._index = None 
     self.cellEntered.connect(self.handleCellEntered) 

    def eventFilter(self, source, event): 
     if source is self._table: 
      if event.type() == QtCore.QEvent.MouseMove: 
       index = QtCore.QPersistentModelIndex(
        source.indexAt(event.pos())) 
       if index != self._index: 
        self._index = index 
        self.cellEntered.emit(QtCore.QModelIndex(index)) 
      elif event.type() == QtCore.QEvent.Leave: 
       self._index = None 
     return super(Window, self).eventFilter(source, event) 

    def handleCellEntered(self, index): 
     print(index.row(), index.column()) 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window() 
    window.setGeometry(600, 100, 300, 200) 
    window.show() 
    sys.exit(app.exec_()) 
+0

와우 그 답변에 감사드립니다! 이걸 어떻게 다 찾았 니? – Cilenco

+0

@Cilenco. 큰 비밀은 없어. 저는 2004/5 년 이후 PyQt를 사용하여 지식의 축적이 꾸준히 이루어졌습니다 ... – ekhumoro

2

조금 조사한 결과 왜 이런 일이 발생하는지 알 것 같습니다.

QCalendarWidgetQCalendarView이라는 QTableView의 개인 서브 클래스를 생성하고 자신의 자식으로 인스턴스화합니다. (이 인스턴스는 qt_calendar_calendarview이라고합니다.)

당신이 QCalendarView's code (Qt 5) 보면,이 나타납니다 :

void QCalendarView::mouseMoveEvent(QMouseEvent *event) 
{ 
    [...] 
    if (!calendarModel) { 
     QTableView::mouseMoveEvent(event); 
     return; 
    } 
    [...] 
} 

이 더 calendarModel이없는 경우에만, 슈퍼 클래스 mouseMoveEvent이 방출에 대한 책임이다라는 의미를 entered 신호. 이 모든 것은`QCalendarWidget의 구현 세부 사항이므로 어쨌든 이것에 의존하지 않는 것이 가장 좋습니다.


이 문제를 해결하기 위해 최선의 방법이 무엇인지 잘 모르겠습니다. 이벤트를 잡아야 만이 테이블에 도착합니다. QObject.installEventFilter()을 사용하거나 QWidget.mouseMoveEvent()을 다시 구현할 수 있지만 모델 색인을 직접 가져 오지는 마십시오. 이 목적으로 아마도 QAbstractItemView.indexAt()을 사용할 수 있습니다.