3

私は現在 PyQT GUI を作成しているコマンド ライン ツールに取り組んできました。readline モジュールを使用して現在のオートコンプリートの実装を取り、それを QLineEdit テキスト ボックスに入れたいと思います。これは可能ですか?おすすめはありますか?

これは私が readline モジュールで行っていることの例です:

import readline

values = ['these','are','my','autocomplete','words']
completions = {}

def completer(text,state):
    try:
        matches = completions[text]
    except KeyError:
        matches = [value for value in values if text.upper() in value.upper()]
        completions[text] = matches
    try:
        return matches[state]
    except IndexError:
        return None

readline.set_completer(completer)
readline.parse_and_bind('tab: menu-complete')

whie 1:
    text = raw_input('> ')
    text.dostuff()

最終的に、readline モジュールを QLineEdit ウィジェットで動作させることができない場合、最終的にやりたいことは、+-*/( のような記号で区切られた複数の単語を持つ機能を使用して、単語のリストを完成させることです。 )など...

ありがとう!

4

1 に答える 1

4

まず第一に、新しい機能を QCompleter でラップしようとするのは非常に面倒なことです。QCompleter のすべてのインターフェイスを満たし、その realine コードをブリッジできる必要があります。

QCompleter に設定された QStringListModel を手動で更新し、指定された検索プレフィックスの現在の補完と補完の総数を取得する実装を提供する必要があります。

PopupCompletion モードと互換性のある実際の例を次に示します。

import re

class ReadlineCompleter(QtGui.QCompleter):

    def __init__(self, completeFn, *args, **kwargs):
        super(ReadlineCompleter, self).__init__(*args, **kwargs)
        self._completer = completeFn
        self.setModel(QtGui.QStringListModel())
        self.update()

    def setCompletionPrefix(self, val):
        super(ReadlineCompleter, self).setCompletionPrefix(val)
        self.update()

    def currentCompletion(self):
        state = self.currentRow()
        return self._completionAt(state)

    def completionCount(self):
        state = 0
        while True:
            result = self._completionAt(state)
            if not result:
                break
            state += 1
        return state

    def update(self):
        matches = [self._completionAt(i) for i in xrange(self.completionCount())]
        self.model().setStringList(matches)

    def _completionAt(self, state):
        text = str(self.completionPrefix())

        # regex to split on any whitespace, or the char set +*/^()-
        match = re.match(r'^(.*)([\s+*/^()-]+)(.*)$', text)
        if match:
            prefix, sep, text = match.groups()

        result = self._completer(str(text), state)

        if result and match:
            result = sep.join([prefix, result])

        return '' if result is None else result     

_completionAt()メソッドで、区切りパターンを検出するために、必要な追加機能を追加したことに注意してください。これは明らかに調整できます。ただし、最後の部分を分割し、その値を使用して完了を確認し、結果をプレフィックスで再度結合します。

使用法

重要。textChanged更新を強制するには、QLineEdit からのシグナルをコンプリータに接続する必要があります。そうしないと、コンプリーターでどの機能も使用されません。

line = QtGui.QLineEdit()
comp = ReadlineCompleter(completer)
comp.setCompletionMode(comp.PopupCompletion)
line.setCompleter(comp)
# important
line.textChanged.connect(comp.setCompletionPrefix)

他の人がどのようにカスタム行編集で機能を埋めなければならなかったかを示す例がここにあります。そこでは、彼らはコンプリーターの標準的なシグナル伝達を完全に回避し、それを自分自身でトリガーします。ちょっとした工夫が見られます。

于 2012-07-09T20:51:51.177 に答える