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個不同的問題懷疑是可以的,所以我決定把它們放在同一個線程中。希望沒關係
您稱之爲「小懷疑」的事實讓我懷疑您大量低估了此任務的複雜性。在第二個項目符號上 - 你絕對會**做**希望滑塊保持可見狀態。如果您嘗試[khan學院示例](http://www.khanacademy.org/computer-programming/tree-generator/822944839),您會注意到在鍵入時該小控件仍然可見。這就是所有自動完成者,呼叫提示和類似工作的方式。我不想讓你灰心,但它需要付出很多努力來獲得這個工作權利 - 特別是鍵盤處理。 – ekhumoro
@ekhumoro當然,我不低估這個酷小部件的創建:)。它涉及以下幾個方面:1)創建一個好的glsl解析器,我有一些麻煩,使得[一個]工作(https://github.com/nicholasbishop/pyglsl_parser)和這個[一個](https:// github 2)掌握qscintilla小部件的可能性(你可以看到我遠離掌握它)3)創建合適的小部件來處理1/2/3d glsl類型,我將創建類似的pyqt小部件提供[這裏](http://editor.thebookofshaders.com/)。無論如何,每次都有一個小問題:) – BPL