8

PyQt5 で、基本的な構文の強調表示、コード補完、クリック可能な関数と変数を備えた単純なテキスト エディターを作成しようとしています。これを達成するための私の最善の希望は
、PyQt5 の QScintilla ポートを使用することです。Eli Bendersky Web サイト ( http://eli.thegreenplace.net/2011/04/01/sample-using-qscintilla-with-pyqt、Victor S. が PyQt5 に適応させたもの) で
、次の QScintilla ベースの texteditor の例を見つけました。 )。この例は良い出発点だと思います:

#-------------------------------------------------------------------------
# qsci_simple_pythoneditor.pyw
#
# QScintilla sample with PyQt
#
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------
import sys

import sip
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.Qsci import QsciScintilla, QsciLexerPython


class SimplePythonEditor(QsciScintilla):
    ARROW_MARKER_NUM = 8

    def __init__(self, parent=None):
        super(SimplePythonEditor, self).__init__(parent)

        # Set the default font
        font = QFont()
        font.setFamily('Courier')
        font.setFixedPitch(True)
        font.setPointSize(10)
        self.setFont(font)
        self.setMarginsFont(font)

        # Margin 0 is used for line numbers
        fontmetrics = QFontMetrics(font)
        self.setMarginsFont(font)
        self.setMarginWidth(0, fontmetrics.width("00000") + 6)
        self.setMarginLineNumbers(0, True)
        self.setMarginsBackgroundColor(QColor("#cccccc"))

        # Clickable margin 1 for showing markers
        self.setMarginSensitivity(1, True)
#        self.connect(self,
#            SIGNAL('marginClicked(int, int, Qt::KeyboardModifiers)'),
#            self.on_margin_clicked)
        self.markerDefine(QsciScintilla.RightArrow,
            self.ARROW_MARKER_NUM)
        self.setMarkerBackgroundColor(QColor("#ee1111"),
            self.ARROW_MARKER_NUM)

        # Brace matching: enable for a brace immediately before or after
        # the current position
        #
        self.setBraceMatching(QsciScintilla.SloppyBraceMatch)

        # Current line visible with special background color
        self.setCaretLineVisible(True)
        self.setCaretLineBackgroundColor(QColor("#ffe4e4"))

        # Set Python lexer
        # Set style for Python comments (style number 1) to a fixed-width
        # courier.
        #

        lexer = QsciLexerPython()
        lexer.setDefaultFont(font)
        self.setLexer(lexer)

        text = bytearray(str.encode("Arial"))
# 32, "Courier New"         
        self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, text)

        # Don't want to see the horizontal scrollbar at all
        # Use raw message to Scintilla here (all messages are documented
        # here: http://www.scintilla.org/ScintillaDoc.html)
        self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0)

        # not too small
        self.setMinimumSize(600, 450)

    def on_margin_clicked(self, nmargin, nline, modifiers):
        # Toggle marker for the line the margin was clicked on
        if self.markersAtLine(nline) != 0:
            self.markerDelete(nline, self.ARROW_MARKER_NUM)
        else:
            self.markerAdd(nline, self.ARROW_MARKER_NUM)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    editor = SimplePythonEditor()
    editor.show()
    editor.setText(open(sys.argv[0]).read())
    app.exec_()

このコードをコピーして空の.pyファイルに貼り付け、実行してください。次の単純なテキスト エディタがディスプレイに表示されるはずです。

ここに画像の説明を入力

構文の強調表示がいかに完璧であるかに注目してください。QScintilla は、これを実現するために、バックグラウンドで解析を行いました。この texteditor のクリック可能な関数と変数
を作成することは可能ですか? すべての自尊心のある IDE にはそれがあります。関数をクリックすると、IDE が関数定義にジャンプします。変数についても同様です。私が知りたいのですが:

  • QScintilla はクリック可能な関数と変数をサポートしていますか?
  • そうでない場合、QScintilla texteditor でこの機能を実装する別の python モジュールをインポートすることは可能ですか?

EDIT :
λuser は次のことに注意しました:

クリック可能な関数名には、プログラミング言語のより深い知識による完全な解析が必要です [..]
これは、Scintilla/QScintilla の範囲をはるかに超えています。Scintilla はマウスがテキストのどこかをクリックしたときに反応する方法を提供しますが、「関数の定義がどこにあるか」というロジックは Scintilla にはなく、おそらく今後もありません。ただし、 ctags
のように、一部のプロジェクトはこのタスクに専念しています。この種のツールのラッパーを簡単に作成できます。

そのようなctagsのラッパーを書くことは、私の TODO リストに載っていると思います。最初のステップは、ユーザーが関数または変数をクリックしたときに反応 (Qt シグナル) を取得することです。また、関数/変数の上にマウスを置いたときに少し青みがかった色に変わり、クリック可能であることをユーザーに通知する必要があります。私はすでにこれを達成しようとしましたが、QScintilla のドキュメントが不足しているため足を引っ張っています。

QScintilla texteditor で関数または変数をクリック可能にするにはどうすればよいですか (「何かが起こる」と定義されたクリック可能)


編集:
数か月後、私は今この質問に戻ってきました。私は友人の Matic Kukovec と協力して、QScintilla に関する Web サイトをデザインしています。これは、使用方法に関する初心者向けのチュートリアルです。

ここに画像の説明を入力

https://qscintilla.com/

このイニシアチブが不足しているドキュメントのギャップを埋めることを願っています。

4

4 に答える 4

1

Matic Kukovec からメールで有益な回答を得たので、ここで共有したいと思います。Matic Kukovec は、QScintilla に基づいて素晴らしい IDE を作成しました: https://github.com/matkuki/ExCo。おそらく、より多くの人々が QScintilla (およびクリック可能な変数と関数) をより深く掘り下げるきっかけになるでしょう。


ホットスポットはテキストをクリック可能にします。関数を使用して手動でスタイルを設定する必要がありQScintilla.SendScintillaます。エディタで使用した関数の例 Ex.Co. ( https://github.com/matkuki/ExCo ):

def style_hotspot(self, index_from, length, color=0xff0000):
    """Style the text from/to with a hotspot"""
    send_scintilla = 
    #Use the scintilla low level messaging system to set the hotspot
    self.SendScintilla(PyQt4.Qsci.QsciScintillaBase.SCI_STYLESETHOTSPOT, 2, True)
    self.SendScintilla(PyQt4.Qsci.QsciScintillaBase.SCI_SETHOTSPOTACTIVEFORE, True, color)
    self.SendScintilla(PyQt4.Qsci.QsciScintillaBase.SCI_SETHOTSPOTACTIVEUNDERLINE, True)
    self.SendScintilla(PyQt4.Qsci.QsciScintillaBase.SCI_STARTSTYLING, index_from, 2)
    self.SendScintilla(PyQt4.Qsci.QsciScintillaBase.SCI_SETSTYLING, length, 2)

これにより、QScintilla エディターのテキストの上にマウスを置いたときに、そのテキストをクリックできるようになります。上記の関数の番号 2 は、ホットスポット スタイルの番号です。ホットスポットをクリックしたときに発生するイベントをキャッチするには、次のシグナルに接続します。

QScintilla.SCN_HOTSPOTCLICK
QScintilla.SCN_HOTSPOTDOUBLECLICK
QScintilla.SCN_HOTSPOTRELEASECLICK

詳細については、Scintilla ホットスポットのドキュメント: http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETHOTSPOT および QScintilla ホットスポット イベント: http://pyqt.sourceforge.net/Docs/QScintilla2/classQsciScintillaBase.html#a5eff383e6fa96cbbaba6a2558b076c0bを参照してください。


まず、クコベックさん、ありがとうございました!あなたの回答に関していくつか質問があります。

(1)あなたのサンプル関数には、私が理解できないことがいくつかあります。

def style_hotspot(self, index_from, length, color=0xff0000):
    """Style the text from/to with a hotspot"""
    send_scintilla =     # you undefine send_scintilla?
    #Use the scintilla low level messaging system to set the hotspot
    self.SendScintilla(..) # What object does 'self' refer to in this
    self.SendScintilla(..) # context?
    self.SendScintilla(..)

(2)「ホットスポットをクリックしたときに発生するイベントをキャッチするには、これらのシグナルに接続します。」

QScintilla.SCN_HOTSPOTCLICK
QScintilla.SCN_HOTSPOTDOUBLECLICK
QScintilla.SCN_HOTSPOTRELEASECLICK

それらの信号に実際にどのように接続しますか? 一例を挙げていただけますか?私は PyQt シグナルスロット メカニズムに慣れていますが、QScintilla では使用したことがありません。例を見ることは大きな助けになるでしょう:-)

(3)何かを見逃したのかもしれませんが、QScintilla のどこで、関数と変数 (およびその他のものではない) がソース コードでクリック可能であると定義されているかわかりませんか?

あなたの親切な助けに感謝します:-)

于 2016-10-12T19:37:09.217 に答える
1

次のドキュメントをご覧ください: https://qscintilla.com/#clickable_text

Qscintilla でクリック可能にする方法は 2 つあります。ホットスポットまたはインジケーターを使用できます。ホットスポットでは、基礎となるレクサーのデフォルトの動作をオーバーライドする必要がありますが、インジケーターはユースケースにとってより便利だと思います。

テキストをクリック可能にするのに役立つインジケーターを見て、クリックされたときに実行されるイベントハンドラーを定義できることをお勧めします。 https://qscintilla.com/#clickable_text/indicators

于 2019-12-16T14:43:38.687 に答える