2016-09-24 46 views
0

我這個小MCVE代碼:爲什麼QColorDialog.getColor意外崩潰?

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

對於一些未知的原因,當我按OK拿起顏色後腳本會意外崩潰,這裏有一個video展示了我的意思。

任何想法爲什麼會發生這種情況?

回答

1

在遊標更改處理程序中打開一個阻塞爲exec()的對話框似乎是一個壞主意,所以我並不驚訝它崩潰。以異步方式打開對話並使用信號/插槽來處理結果會更安全。使用封閉與show()似乎最好,因爲它會給當前的局部變量的訪問:

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

我驗證過的答案,因爲它解釋正是我問。我沒有給予+1因爲一旦你按下ok,這個方法就會以非常奇怪的方式與選擇/遊標混淆。下面是我的意思的例子(http://screencast.com/t/SgErzdN1E),一旦我按下確定,我不再按下左鍵,只需移動鼠標即可。無論如何,非常感謝你;-) – BPL

+0

@BPL。那麼,公平地說,它是*你的*方法來在光標更改處理程序中打開一個對話框,我已經說過這是一個糟糕的主意。我所做的只是嘗試解決你的錯誤;-)無論如何,我已經用不同的修補程序更新了我的答案 - 但請注意,該對話框必須是無模式的才能工作。 – ekhumoro

+0

真棒隊友,在這裏你去+1;)。與此同時,我編寫了一些[小工具](http://screencast.com/t/nBuWfycps),這對於主要任務可能是有用的 – BPL