Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » PyQt: новый стиль подключения сигнал-слот [RSS Feed]

#1 Май 14, 2012 15:01:37

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

Пробую использовать новый стиль подключения сигналов и слотов.

Есть диалоговое окно с QDialogButtonBox, на котором две кнопки OK и Close. В процессе работы надо сделать так, чтобы нажатие на Close не закрывало диалог, а вызывало другой слот. Раньше делал так

self.btnClose = self.buttonBox.button( QDialogButtonBox.Close )
# отсоединение
QObject.disconnect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
# и подключение к другому слоту
QObject.connect( self.btnClose, SIGNAL( "clicked()" ), self.stopProcessing )
....
# восстанавливаем исходное состояние
QObject.disconnect( self.btnClose, SIGNAL( "clicked()" ), self.stopProcessing )
QObject.connect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
и все работало как надо. При этом слот self.reject в коде отсутствует, т.е. вызывался слот родителя (QDialog). Теперь делаю с использованием нового стиля
self.btnClose = self.buttonBox.button( QDialogButtonBox.Close )
self.buttonBox.rejected.disconnect( self.reject )
self.btnClose.clicked.connect( self.stopProcessing )
...
self.btnClose.clicked.disconnect( self.stopProcessing )
self.buttonBox.rejected.connect( self.reject )
И при выполнении получаю следующую ошибку
line 147, in prepareProcess
self.buttonBox.rejected.disconnect( self.reject )
TypeError: disconnect() failed between ‘rejected’ and ‘reject’
Заменяю эти строки подключения на старый стиль — все работает. В чем может быть дело или это у меня карма плохая?



Офлайн

#2 Май 14, 2012 17:33:20

iroln
От:
Зарегистрирован: 2010-11-22
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

Есть диалоговое окно с QDialogButtonBox…
Окно создано в Designer, а код сгенерирован через pyqt-uic? Если так, то он генерирует код в котором соединение ‘rejected’ к ‘reject’ выполняется старым способом.

QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), Dialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), Dialog.reject)

Мне кажется, проблема может быть в том, что соединение создано старым способом, а разрыв соединения вы пытаетесь сделать по-новому. Но эта теория, конечно, требует проверки.



Офлайн

#3 Май 14, 2012 18:38:59

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

Странно.
Попробовал на PySide, там работает нормально. Только если второй раз пытаешься disconnect сделать, тогда вылетает исключение.

На PyQt работает способ с отсоединением всех слотов т.е.

self.ui.buttonBox.rejected.disconnect()
В случае с диалогом, думаю, это допустимо.

Офлайн

#4 Май 14, 2012 19:06:21

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

iroln
Окно создано в Designer, а код сгенерирован через pyqt-uic?
Да, именно так: интерфейс создается в Designer а потом при помощи pyuic4 получаем код
iroln
Если так, то он генерирует код в котором соединение ‘rejected’ к ‘reject’ выполняется старым способом.
Похоже, проблема как раз в этом. Отредактировал сгенерированный pyuic4 код, заменив старый стиль на новый и все заработало. Но это костыльное решение, править автоматически генерируемые файлы не самый лучший вариант. Получается новый стиль еще не польностью готов к использованию.

reclosedev, я правильно понимаю, что у тебя на PyQt это воспроизводится? Можешь запостить используемые версии Qt, PyQt и Python? Попробую написать в рассылку.



Офлайн

#5 Май 14, 2012 19:20:44

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

voltron
reclosedev, я правильно понимаю, что у тебя на PyQt это воспроизводится?
Да, воспроизводится.
voltron
Можешь запостить используемые версии Qt, PyQt и Python? Попробую написать в рассылку.

Win32
Python 2.7.3, PyQt 4.9, Qt 4.8.0
Python 3.2.2, PyQt 4.9.1, Qt 4.8.0

Отредактировано reclosedev (Май 14, 2012 19:21:01)

Офлайн

#6 Май 14, 2012 19:58:37

iroln
От:
Зарегистрирован: 2010-11-22
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

voltron
Похоже, проблема как раз в этом. Отредактировал сгенерированный pyuic4 код, заменив старый стиль на новый и все заработало. Но это костыльное решение, править автоматически генерируемые файлы не самый лучший вариант. Получается новый стиль еще не польностью готов к использованию.
Мда… это провал. Если нет совместимости между api соединения сигналов, когда широко используется и то и то, подобные “прелести” будут лезть как из рога изобилия особенно в тех местах, где что-то генерирует код. Данный пример очень показательный, надо обязательно зарепортить баг в PyQt4.



Офлайн

#7 Май 15, 2012 20:54:42

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

Отписал в рассылку, посмотрим что скажут.



Офлайн

#8 Май 17, 2012 16:18:32

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

Получил ответ. Вот объяснение почему так происходит:

PyQt allows connections to be made to any Python callable.

With old style connections a proxy slot is created under the covers whenever a callable is used (as opposed to when SLOT() is used to refer to a C++ slot). Therefore, in your example, a proxy is always created for the connection to Dialog.reject even though that refers to the object that wraps the C++ slot (as there is no Python reimplementation of reject()).

New style connections are a bit smarter in that they treat slot objects that refer to a wrapped C++ slot and objects that refer to some real Python code differently - a proxy is only created in the latter case.
В качестве workaround'а предлагается реализовать слот-заглушку reject() вида
 def reject(self):
   QDialog.reject(self)
Это заставит подключения нового стиля создавать прокси и использовать его при вызове disconnect().

Разработчики согласны, что это баг, однако исправлять его не будут, т.к. для этого необходимо внести значительные изменения в старый код соединения сгналов-слотов, что в свою очередь может привести к появлению новых ошибок и уменьшить стабильность. Но обещают обновить документацию и добавить туда описание причин и способ решения.



Офлайн

#9 Май 18, 2012 15:42:45

iroln
От:
Зарегистрирован: 2010-11-22
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQt: новый стиль подключения сигнал-слот

Ясно. Хорошо, что хотя бы доку поправят. Отзывчивые разработчики. :)



Офлайн

  • Начало
  • » GUI
  • » PyQt: новый стиль подключения сигнал-слот[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version