2017-10-12 7 views
1

前の最後のフォーカスを持っていたQWidgetの決定:私はQtアプリケーションに次の機能を実装したいボタンを押し

  • ユーザーは、それぞれが含む、1以上の「入力」ウィジェット(InputWidgetクラスのインスタンス)を開き、 QLineEditウィジェット
  • ユーザーが「ヘルパー]ダイアログを開きます
  • ユーザーは
  • ユーザーは、「挿入」QPushButton「ヘルパー」ダイアログ
  • でを押す「ヘルパー」ダイアログで値を選択します「ヘルパー」ダイアログから
  • 選択した値が挿入 『ボタンだから、

を押された、基本的に、私が欲しいものである入力『前の最後のフォーカスを持っていたダイアログ』」というのQLineEditに挿入されています』次のスクリーンショットでユーザーが「挿入」をクリックすると、フォーカスされた入力ダイアログに文字列「Apple」が表示されるはずです。以下のコード例は、作業の種類を示していますが、文字列は2番目の文字列に挿入されています(通常は下を参照)。

enter image description here

ここだ、このセットアップを作成するコードの例です:

from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout, 
          QLineEdit, QLabel, QPushButton, QComboBox) 
import sys 


# this is the missing bit 
def determineWhichWidgetHadLastFocus(): 
    for widget in QApplication.instance().topLevelWidgets(): 
     if isinstance(widget, InputWidget): 
      # do something wonderful to determine whether this widget 
      # is the one that had last focus 
      wonderful = True 

     if wonderful: 
      return widget 
    return None 


class BaseWidget(QWidget): 
    """ Base widget type """ 

    def __init__(self, name): 
     super(BaseWidget, self).__init__() 
     self.setWindowTitle(name) 
     self.setupUi() 
     self.show() 

    def setupUi(self): 
     pass 


class InputWidget(BaseWidget): 
    """ InputWidget contains a QLabel and a QLineEdit widget """ 

    def setupUi(self): 
     self.label = QLabel("Input string:") 
     self.edit = QLineEdit() 

     layout = QHBoxLayout(self) 
     layout.addWidget(self.label) 
     layout.addWidget(self.edit) 


class HelperWidget(BaseWidget): 
    """ HelperWidget contains a QLineEdit and a QPushButton widget. Pressing 
    the button inserts the content of the edit widget into the edit widget of 
    the last activated InputWidget """ 

    def setupUi(self): 
     self.combo = QComboBox() 
     self.combo.addItems(["Apple", "Pear", "Banana"]) 
     self.button = QPushButton("Insert") 
     self.button.clicked.connect(self.insertString) 

     layout = QHBoxLayout(self) 
     layout.addWidget(self.combo) 
     layout.addWidget(self.button) 

    def insertString(self): 
     widget = determineWhichWidgetHadLastFocus() 
     if widget: 
      widget.edit.insert(self.combo.currentText()) 

def main(): 
    app = QApplication(sys.argv) 

    diag1 = InputWidget("Input dialog") 
    diag2 = InputWidget("Another input") 

    helper = HelperWidget("Helper") 

    app.exec_() 


if __name__ == "__main__": 
    main() 

欠けている部分がdetermineWhichWidgetHadLastFocus()機能です。

この関数は、「入力」がフォーカスを保持する最後のものであるかどうかを判断できるようにすばらしいやり方をすることになっています。現在のところ、トップレベルのウィジェットのリストをQApplicationから検索していますが、トップレベルのウィジェットの順序はアクティブ化の順序を反映していません(通常、作成の順番であるとは限りません)。

私の頭に浮かべた1つのアイデアは、FocusInイベントを追跡するイベントフィルタをインストールすることでした。これは私の例ではInputWidgetクラスにとっては簡単ですが、実際のアプリケーションでは多くのQLineEditQTextEdit、下位クラスのすべてがあまりにもうまく機能しない可能性があります。私はむしろそのように行かないだろう。

他のアイデアはありますか?

答えて

0

イベントフィルタのアイデアは、結局のところ進む方法です。作成されたすべてのイベントがフィルターを通過するようにカスタムQApplicationクラスの

from PyQt5.QtCore import QObject, QEvent, pyqtSignal 


class inputFocusFilter(QObject): 
    focusIn = pyqtSignal(object) 

    def eventFilter(self, widget, event): 
     if event.type() == QEvent.FocusIn and isinstance(widget, QLineEdit): 
      # emit a `focusIn` signal, with the widget as its argument: 
      self.focusIn.emit(widget) 
     return super(inputFocusFilter, self).eventFilter(widget, event) 

このフィルタはインストールされています:私がやったことは、送信オブジェクトがQLineEditオブジェクトされた場合は、最初の信号を発するイベントフィルタクラスを作成しました。信号focusInはフォーカスを受信した最後の入力ウィジェット覚えセッター関数に接続されている:

class MyApplication(QApplication): 
    def __init__(self, *arg, **kwarg): 
     super(MyApplication, self).__init__(*arg, **kwarg) 

     self._input_focus_widget = None 

     self.event_filter = inputFocusFilter() 
     self.event_filter.focusIn.connect(self.setInputFocusWidget) 
     self.installEventFilter(self.event_filter) 

    def setInputFocusWidget(self, widget): 
     self._input_focus_widget = widget 

    def inputFocusWidget(self): 
     return self._input_focus_widget 

MyApplicationmain()の1行目に代わりQApplicationのに使用されます。今度はdetermineWhichWidgetHadLastFocus()への電話をHelperWidget.insertString()に置き換えてQApplication.instance().inputFocusWidget()に置き換えることができ、すべてが意図どおりに動作します。

関連する問題