2017-02-04 19 views
1

私のQtアプリケーションでは、QCalendarWidgetを使用しています。マウスがカレンダーの新しいセルに入ったときに通知を受けたいと思います。マウスカーソルがインデックスによって を指定された項目を入力したときに、この信号が発せられるPyQt:セルがQCalendarWidgetに入力されたときに信号を送信

:私はQCalendarWidgetQAbstractItemViewから継承し、これはentered信号を有する内部QTableViewを使用していることを知っています。この機能を使用するには、マウストラッキングを有効にする必要があります。

私は次のコードで信号を受信しようとした:

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

私はちょっと調査しましたが、なぜこれが起こるのか知っていると思います。

QCalendarWidgetは、QCalendarViewと呼ばれる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()を使用できます。

関連する問題