2016-09-25 6 views
1

私はこの小さなMCVEコードを得た:QScintillaウィジェットで特定のマッチを正しく置き換えるにはどうすればいいですか?

import sys 
import re 

from PyQt5 import QtGui, QtWidgets, QtCore 
from PyQt5.QtCore import Qt 
from PyQt5.Qsci import QsciScintilla 
from PyQt5 import Qsci 


class FloatSlider(QtWidgets.QWidget): 

    value_changed = QtCore.pyqtSignal(float) 

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

     self.slider = QtWidgets.QSlider(Qt.Horizontal) 
     self.label = QtWidgets.QLabel() 
     self.label.setAlignment(Qt.AlignCenter) 

     self.adjust(value) 

     layout = QtWidgets.QHBoxLayout() 
     layout.addWidget(self.slider) 
     layout.addWidget(self.label) 

     self.slider.valueChanged.connect(self.on_value_changed) 
     self.setLayout(layout) 
     self.setWindowTitle("Adjust number") 

    def adjust(self, value): 
     width = 100 # TODO: Adjust it properly depending on input value 
     self.slider.setRange(value - width, value + width) 
     self.slider.setSingleStep(1) 
     self.slider.setValue(value) 
     self.label.setText(str(float(value))) 

    def on_value_changed(self, value): 
     # vmax, vmin = self.slider.minimum(), self.slider.maximum() 
     # value = 2 * value/(vmax - vmin) 
     self.label.setText(str(float(value))) 
     self.value_changed.emit(value) 


class SimpleEditor(QsciScintilla): 

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

     self.slider = FloatSlider(value=0.0) 
     self.slider.value_changed.connect(self.float_value_changed) 

     font = QtGui.QFont() 
     font.setFamily('Courier') 
     font.setFixedPitch(True) 
     font.setPointSize(10) 
     self.setFont(font) 
     self.setMarginsFont(font) 
     fontmetrics = QtGui.QFontMetrics(font) 
     self.setMarginsFont(font) 
     self.setMarginWidth(0, fontmetrics.width("00000") + 6) 
     self.setMarginLineNumbers(0, True) 
     self.setMarginsBackgroundColor(QtGui.QColor("#cccccc")) 
     self.setBraceMatching(QsciScintilla.SloppyBraceMatch) 
     self.setCaretLineVisible(True) 
     self.setCaretLineBackgroundColor(QtGui.QColor("#E8E8FF")) 

     if language: 
      self.lexer = getattr(Qsci, 'QsciLexer' + language)() 
      self.setLexer(self.lexer) 

     self.SendScintilla(QsciScintilla.SCI_FOLDALL, True) 
     self.setAutoCompletionThreshold(1) 
     self.setAutoCompletionSource(QsciScintilla.AcsAPIs) 
     self.setFolding(QsciScintilla.BoxedTreeFoldStyle) 

     # Signals/Slots 
     self.cursorPositionChanged.connect(self.on_cursor_position_changed) 
     self.copyAvailable.connect(self.on_copy_available) 
     self.indicatorClicked.connect(self.on_indicator_clicked) 
     self.indicatorReleased.connect(self.on_indicator_released) 
     self.linesChanged.connect(self.on_lines_changed) 
     self.marginClicked.connect(self.on_margin_clicked) 
     self.modificationAttempted.connect(self.on_modification_attempted) 
     self.modificationChanged.connect(self.on_modification_changed) 
     self.selectionChanged.connect(self.on_selection_changed) 
     self.textChanged.connect(self.on_text_changed) 
     self.userListActivated.connect(self.on_user_list_activated) 

    def float_value_changed(self, v): 
     print(v) 

    def on_cursor_position_changed(self, line, index): 
     text = self.text(line) 
     for match in re.finditer('(?:^|(?<=\W))\d+(?:\.\d+)?(?=$|\W)', text): 
      start, end = match.span() 
      if start <= index <= end: 
       pos = self.positionFromLineIndex(line, start) 
       x = self.SendScintilla(
        QsciScintilla.SCI_POINTXFROMPOSITION, 0, pos) 
       y = self.SendScintilla(
        QsciScintilla.SCI_POINTYFROMPOSITION, 0, pos) 
       point = self.mapToGlobal(QtCore.QPoint(x, y)) 
       num = float(match.group()) 
       message = 'number: %s' % num 

       self.slider.setWindowTitle('line: {0}'.format(line)) 
       self.slider.adjust(num) 
       self.slider.move(point + QtCore.QPoint(0, 20)) 
       self.slider.show() 

       break 

    def on_copy_available(self, yes): 
     print('-' * 80) 
     print("on_copy_available") 

    def on_indicator_clicked(self, line, index, state): 
     print("on_indicator_clicked") 

    def on_indicator_released(self, line, index, state): 
     print("on_indicator_released") 

    def on_lines_changed(self): 
     print("on_lines_changed") 

    def on_margin_clicked(self, margin, line, state): 
     print("on_margin_clicked") 

    def on_modification_attempted(self): 
     print("on_modification_attempted") 

    def on_modification_changed(self): 
     print("on_modification_changed") 

    def on_selection_changed(self): 
     print("on_selection_changed") 

    def on_text_changed(self): 
     print("on_text_changed") 

    def on_user_list_activated(self, id, text): 
     print("on_user_list_activated") 


def show_requirements(): 
    print(sys.version) 
    print(QtCore.QT_VERSION_STR) 
    print(QtCore.PYQT_VERSION_STR) 

if __name__ == "__main__": 
    show_requirements() 

    app = QtWidgets.QApplication(sys.argv) 

    ex = QtWidgets.QWidget() 
    hlayout = QtWidgets.QHBoxLayout() 
    ed = SimpleEditor("JavaScript") 

    hlayout.addWidget(ed) 

    ed.setText("""#ifdef GL_ES 
precision mediump float; 
#endif 

#extension GL_OES_standard_derivatives : enable 

uniform float time; 
uniform vec2 mouse; 
uniform vec2 resolution; 

void main(void) { 

    vec2 st = (gl_FragCoord.xy/resolution.xy); 
    vec2 lefbot = step(vec2(0.1), st); 
    float pct = lefbot.x*lefbot.y; 
    vec2 rigtop = step(vec2(0.1), 1.-st); 
    pct *= rigtop.x*rigtop.y; 
    vec3 color = vec3(pct); 

    gl_FragColor = vec4(color, 1.0);""") 

    ex.setLayout(hlayout) 
    ex.show() 
    ex.resize(800, 600) 

    sys.exit(app.exec_()) 

私が対処する方法がわからないいくつかの問題があります。

  • は、私は、私のスライダウィジェットがウィジェットの幅私は値を変更するたびに変化していますaddStrecht(1)を試しましたが、ウィジェットの間に余分な空きスペースがあるため意図したとおりに機能しませんでした(レイアウト配置 - >スライダー| strecht |ラベル)
  • QScintillaウィジェットに数値を入力すると、FloatSliderウィジェットは表示され、それは間違いなく私がしないものです欲しいです。私はそれが左のマウスボタンや他の任意の組み合わせ(すなわち:ctrl + left_mouse)でこのような数値を押すときにだけ表示されたいです
  • QScintillaのテキスト(正規表現の一致)を正しく置き換える方法がわかりませんリアルタイム。理想的には唯一のQScintillaテキストを変更する必要がマッチした視覚効果は、それはこれらのほとんどのための3つの異なる質問を開いたように感じませんでした

かなり不気味になるので、例えば、私は、テキスト全体を交換する必要はありません疑問は大丈夫だったので、私は同じスレッドでそれらを集めることに決めました。うまくいけばOKです

+0

と言ってください。これらの「ちょっとした疑念」を実際に言うと、あなたはこの作業の複雑さを大幅に過小評価している可能性があります。 2番目の箇条書きポイントでは、スライダーを目立たせたいと思うのは間違いありません。 [khan academy example](http://www.khanacademy.org/computer-programming/tree-generator/822944839)を試してみると、入力中にギズモが見えることに気付くでしょう。これは、すべての自動補完機能、コールヒントなどが機能する方法です。私はあなたを落胆させたくありませんが、この作業の権利を得るにはたくさんの努力が必要です - 特にキーボードの操作。 – ekhumoro

+0

@ekhumoro間違いなく私はこのクールなウィジェットの作成を過小評価していません:)。いくつかの問題があります:1)良いglslパーサの作成、私はこの問題([https://github.com/nicholasbishop/pyglsl_parser]とhttps:// github .com/rougier/glsl-parser)2)qscintillaウィジェットの可能性をマスターする(私が遠くに習得しているのがわかるように)3)1/2/3dのglslタイプを扱うための適切なウィジェットを作成すると、同様のPyqtウィジェットは、[ここ](http://editor.thebookofshaders.com/)に提供されています。いずれにせよ、毎回小さな問題が1つあります:) – BPL

答えて

0
  • 使用setFixedWidthはスライダーかのどちらかを避けるために、すべての変更のラベル変更幅
  • あなただけではなく、特定の位置に特定のマッチを置き換えるための良い方法はを使用して代わりになりmouseReleaseEvent
  • を使用し、on_cursor_position_changedイベントを使うべきではありませんおよびSCI_DELETERANGEの方法を使用する。詳細については、QScintilla docs
1

2番目の箇条書き点では、スライダのための別のウィンドウ/ダイアログを持つというアイデアをあきらめるべきだと思います。代わりにポップアップを使用して、外側をクリックするかエスケープを押す(つまり、ツールチップやコンテキストメニューのように)まで、エディタの上にとどまるべきです。

はあなたにこれがどのように見えるかのアイデアを与える(しかし、他の潜在的な問題のいずれかを解決しようとせずに)、このような何かをしようとするには、次の

class FloatSlider(QtWidgets.QFrame):  
    value_changed = QtCore.pyqtSignal(float) 

    def __init__(self, value=0.0): 
     super().__init__() 
     ...  
     self.setFrameShape(QtWidgets.QFrame.Box) 
     self.setFrameShadow(QtWidgets.QFrame.Plain) 
     self.setParent(None, QtCore.Qt.Popup) 
     self.setFocusPolicy(QtCore.Qt.NoFocus) 

    def adjust(self, value): 
     ... 
     self.slider.setFocus() 
関連する問題