2016-09-24 3 views
0

J'ai eu ce petit code mcve:Pourquoi QColorDialog.getColor plante-t-il de façon inattendue?

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): 
     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) 
     color = QtWidgets.QColorDialog.getColor() 

    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_()) 

Pour une raison inconnue, quand j'appuyez sur OK après avoir écopé d'une couleur le script se bloque de façon inattendue, voici une video montrant ce que je veux dire.

Une idée pourquoi cela se produirait?

Répondre

1

Ouverture d'un dialogue avec un blocage exec() dans le gestionnaire de changement de curseur semble être une mauvaise idée, donc je ne suis pas surpris qu'il se bloque. Il sera beaucoup plus sûr d'ouvrir le dialogue de manière asynchrone et d'utiliser un signal/slot pour gérer le résultat. L'utilisation d'une fermeture avec show() semble le mieux, car il donnera accès aux variables locales actuelles:

class SimpleEditor(QsciScintilla): 
    def __init__(self, language=None, parent=None): 
     super().__init__(parent) 
     ... 
     self.colors = QtWidgets.QColorDialog(self) 

    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 

       def handler(): 
        print(message) 
        print(self.colors.selectedColor().name()) 
        self.colors.finished.disconnect() 

       self.colors.finished.connect(handler) 
       self.colors.show() 

       break 
+0

J'ai validé la réponse parce qu'il a expliqué exactement ce que je demandais. Je n'ai pas donné de +1 car cette approche est très compliquée avec la sélection/les curseurs d'une manière vraiment étrange une fois que vous avez appuyé sur OK. Voici un [exemple] (http://screencast.com/t/SgErzdN1E) de ce que je veux dire, une fois que j'ai appuyé sur OK, je n'appuie plus sur le bouton gauche, juste en déplaçant la souris. En tout cas, merci beaucoup ;-) – BPL

+0

@BPL. Eh bien, pour être juste, c'était votre * approche * d'ouvrir une boîte de dialogue à l'intérieur du gestionnaire de changement de curseur, ce que j'ai déjà dit était une mauvaise idée. Tout ce que j'ai fait, c'est d'essayer de réparer votre bug ;-) De toute façon, j'ai mis à jour ma réponse avec un correctif différent - mais notez que le dialogue doit être modélisé pour que cela fonctionne. – ekhumoro

+0

Mate génial, voilà le +1;). En attendant, j'ai codé un [deux widgets] (http://screencast.com/t/nBuWfycps) qui peuvent être utiles pour la tâche principale – BPL