2016-09-23 2 views
2

obtenu ce simple morceau de code mcve:Comment afficher les boîtes de dialogue à une certaine position dans un widget QScintilla? Je

import sys 
import re 

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


class SimpleEditor(QsciScintilla): 

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

     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 on_cursor_position_changed(self, line, index): 
     print("on_cursor_position_changed") 

    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") 


if __name__ == "__main__": 
    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_()) 

Je suis en train de coder une solution similaire à celle fournie sur ce site. Comme vous pouvez le voir, sur ce site, l'utilisateur ne peut modifier les valeurs numériques qu'en cliquant dessus, une petite boîte de dialogue apparaîtra et l'utilisateur pourra modifier les valeurs en temps réel.

Maintenant, la première chose que je dois comprendre est quels sont les signaux que je dois considérer lorsque l'utilisateur clique sur le widget QScintilla (j'utilise ces docs). Lequel est/sont le/s je devrais vraiment m'en préoccuper.

Dans tous les cas, en supposant que j'utilise le bon signal pour faire apparaître mon dialogue contenant des curseurs, comment pourrais-je trouver la bonne position où mon dialogue devrait apparaître?

+0

Qu'est-ce qui vous empêche actuellement de commencer à ce code vous-même? Les questions sur SO devraient se concentrer sur * un problème de programmation spécifique * - sinon, il semblerait que vous demandiez aux gens d'écrire tout le code pour vous. – ekhumoro

+0

@ekhumoro Ok, j'ai les mains sales avec la tâche et j'ai édité ma question pour essayer de la rendre plus spécifique, pourriez-vous me confirmer que le format est maintenant quelque chose de plus traitable? De plus, je me débarrasse de tous mes commentaires offtopiques afin que le fil ne soit pas pollué. J'espère que le titre de la question/le contenu ne sont plus larges, SVP faites le moi savoir. Merci. – BPL

+0

Merci d'avoir pris la peine d'améliorer votre question. – ekhumoro

Répondre

2

Le signal cursorPositionChanged peut être utilisé pour détecter chaque fois que la souris ou le clavier déplace le curseur vers une position dans un nombre. Une expression rationnelle peut ensuite être utilisée pour trouver où le nombre commence et se termine sur la ligne en cours. Une fois que vous avez cela, vous pouvez utiliser certaines fonctions de bas niveau pour calculer la position globale du nombre.

La méthode ci-dessous utilise cette approche pour montrer une info-bulle ci-dessous le texte pertinent:

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 
      break 
    else: 
     point = QtCore.QPoint(0, 0) 
     message = '' 
    QtWidgets.QToolTip.showText(point, message) 
+0

Merci beaucoup! C'est plus que suffisant pour commencer. La prochaine étape sera de créer les différents widgets pour gérer tous les différents types que le langage glsl offre (float, vec2, vec3) et les analyser correctement. Btw, quelques questions rapides supplémentaires, savez-vous pourquoi l'utilisation de 'QtWidgets.QColorDialog.getColor()' à la place QToolTip me donnerait un plantage? Aussi, quelle est la meilleure façon de remplacer du texte sur QScintilla? En tout cas, merci pour votre belle réponse, vraiment appréciée ;-) – BPL

+0

@BPL. Je pense que vous devrez poster de nouvelles questions pour ces autres questions. – ekhumoro