Найти - Пользователи
Полная версия: PyQt. Схлопываются диалоговые окна в OS Windows 7
Начало » GUI » PyQt. Схлопываются диалоговые окна в OS Windows 7
1 2
KriO
reclosedev
Похоже вот на это http://python.su/forum/post/88673/

Спасибо. Попробовала. Не помогло. Возможно я что-то сделала не так.
В приведённом (по ссылке) примере комбобокс сам является делегатом, а из него вызывается диалог.
У меня для QTreeView назначен делегат:
class ColorDelegate(QtGui.QItemDelegate):
    def __init__(self, treeD, parent=None):
        super(ColorDelegate, self).__init__(parent)
        self.treeD = treeD     #виджет, помещённый в QDockWidget
        self.newcolor = QtGui.QColor()
        self.fullName = ""
    def createEditor(self, parent, option, index):
        editor = ColorDialog(self.treeD)
        editor.accepted.connect(self.emitColorData)
        editor.rejected.connect(self.rejectColorData)
        editor.installEventFilter(self)
        editor.canFocusOut = True
        return editor
    def setEditorData(self, editor, index, value):
#        editor.canFocusOut = False
        editor.setFocus()
        print "ColorDelegate>  setEditorData: editor.canFocusOut=", editor.canFocusOut
        color = QtGui.QColor(value)
        if color.isValid():
            editor.setCurrentColor(color)
    def setModelData(self, editor, model, index, scene):
        self.scene = scene
        row = index.row()
        self.ind = index.sibling(row, config.AttrNameColumnNumber)
        indN = index.sibling(row, config.AttrFullNameColumnNumber)
        self.fullName = EgcString(index.model().data(indN, QtCore.Qt.DisplayRole))
        self.newcolor = editor.currentColor()
    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)
    def emitColorData(self):
        objName = self.treeD.getCurrObjName()
        script = "sets(\""+ objName + "." + self.fullName +"\"," + "\"" + str(self.newcolor.name()) + "\")"
        EgcJouExecScript(self.scene, script)
        self.treeD.setNeedUpdateAttrTree()
        EgcDrawPicture(self.scene)
        self.commitData.emit(self.sender())
    def rejectColorData(self):
        self.result = QtGui.QDialog.Rejected
    def eventFilter(self, editor, event):
#        print "ColorDelegate>  eventFilter: editor.canFocusOut=", editor.canFocusOut, "event=", event
        if event.type() == QtCore.QEvent.FocusOut and hasattr(editor, 'canFocusOut'):
            print "ColorDelegate> -1- eventFilter: editor.canFocusOut=", editor.canFocusOut
            if not editor.canFocusOut: return False
        return QtGui.QItemDelegate.eventFilter(self, editor, event)
В делегате назначается editor:
class ColorDialog(QtGui.QColorDialog):
    def __init__(self, parent=None):
        super(ColorDialog, self).__init__(parent)
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.canFocusOut = False
#        self.canFocusOut = True
        
    def accept(self):
        self.done(QtGui.QDialog.Accepted)
    def reject(self):
        self.done(QtGui.QDialog.Rejected)
    def showEvent(self, event):
        print "ColorDialog> showEvent  self.canFocusOut=", self.canFocusOut
        self.canFocusOut = True
    def closeEvent(self, event):
        if not self.canFocusOut:
            event.ignore()
Событие FocusOut приходит, метод возвращает False, но диалог схлопывается всё равно. Я уже от безысходности поставила в closeEvent проверку и игнорирую событие close, но Винда плевать хотела на мои екзерсисы. В линухе всё работает как часы. Винда у меня в виртуалбоксе. В тест я уже начала добавлять всякую всячину из реального проекта, но он всё равно работает правильно - диалоги не схлопываются. Но не переносить же мне в точности весь проект в тест!
Я не понимаю, почему, если выдвинуть доквиджет из главного окна, то всё работает правильно.
py.user.next
KriO
но в тесте диалоги не схлопываются, всё нормально работает
закинь сюда минимальный тест
KriO
Вот тест в аттаче. Я по возможности сохранила структуру наследования классов. В тесте ColorDialog не схлопывается. В реальном процессе схлопывается сразу после засветки в винде, если QDockWidget не выдвигать из главного окна. Может возникнуть вопрос: “Ззачем такая структура классов?” Проект большой и сложный. На базе этих классов ещё работают другие классы и другое приложение.
py.user.next
нашёл пару ошибок

1)
похоже, ошибка перекочевала из реального проекта
[guest@localhost 23c8]$ python dialog_test.py 
Traceback (most recent call last):
File "dialog_test.py", line 146, in createEditor
self.editor = editor
UnboundLocalError: local variable 'editor' referenced before assignment
[guest@localhost 23c8]$

2)
кодировка там неправильно выставлена
кодировка вверху относится к кодировке самого исходника, она сообщает интерпретатору, как раскодировать данные после объявления кодировки (типа как на html-странице делают для браузера)

внёс изменения
https://gist.github.com/23c8e5d16fc82489d931/revisions

KriO
В OS Windows 7 диалог появляется и тут же схлопывается
надо учесть, что диалог появляется - то есть запуск настроен
имеешь в виду модальный диалог выбора цвета ?
попробуй модальность убрать
KriO
py.user.next
нашёл пару ошибок1)похоже, ошибка перекочевала из реального проекта
нее, это я не аккуратно тест сделала. В реальном проекте проверяются ещё другие колонки и editor создается для них, т.е. не бывает ситуации, когда он не создаётся до этого присваивания.

py.user.next
2)
кодировка там неправильно выставлена
кодировка вверху относится к кодировке самого исходника, она сообщает интерпретатору, как раскодировать данные после объявления кодировки (типа как на html-странице делают для браузера)

внёс изменения
https://gist.github.com/23c8e5d16fc82489d931/revisions
Спасибо.
Исошная кодировка используется, т.к. изначально проект разрабатывался в CentOS5, а там у нас эта кодировка использовалась по умолчанию. В реальном проекте проблем с этой кодировкой не возникает ни в линухе ни в винде. Всё перекодируется как надо.

py.user.next
имеешь в виду модальный диалог выбора цвета ?
попробуй модальность убрать

да, я про диалог выбора цвета, в данном случае. А в реальном пректе все остальные диалоги, вызываемые из делегата, тоже появляются, а потом схлопываются. Проблема эта появилась, когда я вместо диалога настройки атрибутов в дереве, сделала аналогичный виджет и поместила его в доквиджет. Когда это дерево было в диалоге, всё работало нормально.
Модальность убрала, проблема осталась.

py.user.next
посмотри новый коммит, я там добавил отладку

от запуска до после изменения цвета пишет
cd init
cd init
cd create editor
cd set editor data
cd set model data
cd emit color data

проверь на винде
KriO
py.user.next
посмотри новый коммит, я там добавил отладкуот запуска до после изменения цвета пишет
py.user.next
проверь на винде

Поставила печати во все методы делегата и диалога. В винде последняя печать из метода setEditorData. Ещё я поставила в реальный проект печать всех событий в метод eventFilter в ColorDelegat-е. Вот лог из линукса:
=========
ColorDelegate> init
ColorDelegate> createEditor
ColorDialog> init
ColorDelegate> setEditorData
(203) QEvent.WinIdChange
(75) QEvent.Polish
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(70) QEvent.ChildInserted
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(13) QEvent.Move (x=1216 y=517)
(14) QEvent.Resize
(17) QEvent.Show
ColorDialog> showEvent self.canFocusOut= False
(26) QEvent.ShowToParent
(8) QEvent.FocusIn
(67)
(74) QEvent.PolishRequest
(76) QEvent.LayoutRequest
(77) QEvent.UpdateRequest
(76) QEvent.LayoutRequest
(76) QEvent.LayoutRequest
(12) QEvent.Paint
(24) QEvent.WindowActivate
(99) QEvent.ActivationChange
(8) QEvent.FocusIn
(13) QEvent.Move (x=1220 y=542)
(10) QEvent.Enter
(77) QEvent.UpdateRequest
(12) QEvent.Paint
(77) QEvent.UpdateRequest
(12) QEvent.Paint
(77) QEvent.UpdateRequest
(12) QEvent.Paint
(77) QEvent.UpdateRequest
(12) QEvent.Paint
(77) QEvent.UpdateRequest
(3) QEvent.MouseButtonRelease (x=300 y=58)
(11) QEvent.Leave
(10) QEvent.Enter
(77) QEvent.UpdateRequest
(12) QEvent.Paint
(9) QEvent.FocusOut
ColorDelegate> eventFilter (event.type() == QtCore.QEvent.FocusOut) editor.canFocusOut= False
(77) QEvent.UpdateRequest
(12) QEvent.Paint
(77) QEvent.UpdateRequest
(77) QEvent.UpdateRequest
(12) QEvent.Paint
ColorDialog> accept
(25) QEvent.WindowDeactivate
(99) QEvent.ActivationChange
ColorDelegate> setModelData
(77) QEvent.UpdateRequest
(18) QEvent.Hide
(27) QEvent.HideToParent
ColorDelegate> finishedColorData
ColorDelegate> emitColorData
(52) QEvent.DeferredDelete
(71) QEvent.ChildRemoved
(203) QEvent.WinIdChange
(16)
=========
а вот из винды:
=========
ColorDelegate> init
ColorDelegate> createEditor
ColorDialog> init
ColorDelegate> setEditorData
(203) QEvent.WinIdChange
(75) QEvent.Polish
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(69) QEvent.ChildPolished
(13) QEvent.Move (x=1229 y=380)
(14) QEvent.Resize
(17) QEvent.Show
ColorDialog> showEvent self.canFocusOut= False
(24) QEvent.WindowActivate
(99) QEvent.ActivationChange
(8) QEvent.FocusIn
(26) QEvent.ShowToParent
(74) QEvent.PolishRequest
(76) QEvent.LayoutRequest
(77) QEvent.UpdateRequest
(12) QEvent.Paint
(25) QEvent.WindowDeactivate
(99) QEvent.ActivationChange
(9) QEvent.FocusOut
ColorDelegate> eventFilter (event.type() == QtCore.QEvent.FocusOut) editor.canFocusOut= False
(18) QEvent.Hide
(27) QEvent.HideToParent
(76) QEvent.LayoutRequest
(52) QEvent.DeferredDelete
(71) QEvent.ChildRemoved
(203) QEvent.WinIdChange
(16)
==========

Вопрос: “Откуда берётся событие Hide сразу после FocusOut в винде? Кто его вызывает? Почему в линухе другой список событий?”
KriO
Нашла. У виджета, который в центральном виджете главного окна, устанавливается сигнал update(), по которому вызывается слот update_attr_tree(), в котором модель для дерева создаётся заново. В делегате дерева отредактированное значение я не засылаю напрямую в дерево, а формирую некий скрипт и вызываю глобальную функцию выполнения этого скрипта и затем вызываю функцию перерисовки картинки, а она уже формирует сигнал update(), по которому дерево обновляется. Почему-то в винде этот сигнал срабатывал раньше, чем в делегате успевали что-то отредактировать. Я поставила блокировку сигнала пока не выйдут из делегата.

Прошу прощения, что вам пришлось потратить своё время на мои заморочки. Спасибо за готовность помочь.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB