Показаны сообщения с ярлыком Qt. Показать все сообщения
Показаны сообщения с ярлыком Qt. Показать все сообщения

среда, 14 января 2009 г.

Трабла setHidden у QTreeWidgetItem

Суть проблемы

Есть дерево (QTreeWidget) элементов (QTreeWidgetItem). По событию некоторые элементы нужно скрыть, а скрытые отобразить, для чего используется функция setHidden у QTreeWidgetItem. После фильтрации это все сортируется:

def add_subitems(self, root_item):        
'''Добавить элементы к корневому элементу'''

def add(text, hide=False):
sub_item = QtGui.QTreeWidgetItem(root_item)
sub_item.setText(0, text)
sub_item.setHidden(hide)

map(lambda val: add(*val), ( ('one',),
('two', True),
('three',) ))

def update_subitems(self, root_item):
'''Обновить под-элементы - скрыть или отобразить'''

for index in range(root_item.childCount()):
item = self.root_item.child(index)
# для упрощения скрываются видимые элементы,
# а скрытые отображаются
item.setHidden(not item.isHidden())

self.treeWidget.sortItems(0, QtCore.Qt.AscendingOrder)

Если update_subitems вызывается когда окно скрыто (свернуто в трей), часть вызовов setHidden отрабатывается не правильно и при восстановлении окна из трея пользователь видит не то, что должен видеть. Если убрать сортировку или не скрывать окно - все работает как надо.

Решение

Единственное решение, которое я нашел - отлавливать момент, когда окно отображается (QShowEvent) и обновлять дерево еще раз:
def event(self, ev):
if ev.type()==QtCore.QEvent.Show:
#....
self.update_subitems(root_item)

Read More...

воскресенье, 21 декабря 2008 г.

Qt Creator

Qt Software (так называется Trolltech после покупки компанией Nokia) выпустили бету новой кросс-платформенной IDE для работы с Qt - Qt Creator. На данном этапе среда поддерживает только компилятор gcc и дебагер gdb. Можно так же использовать Microsoft Visual Studio компилятор, но тогда не получится дебажить.

Qt Creator - это не попытка заменить Eclipse и Visual Studio:

Qt Creator is not an Eclipse replacement, but instead a lightweight IDE designed specifically for cross-platform Qt development.

Qt Creator is not a Visual Studio replacement, but instead a lightweight IDE designed specifically for cross-platform Qt development.

Финальный релиз намечается на начало 2009 года. Подробнее можно почитать здесь.

Выглядит это так:



Самореклама: мой второй блог

Read More...

четверг, 16 октября 2008 г.

PyQt in-depth: типы signal-slot соединений

В Qt слоты и сигналы являются платформенно-независимым средством обмена сообщениями между объектами. Подробнее писать о них я не собираюсь, так это хорошо сделали до меня прямо в документации Qt или, например, вот здесь. Я хочу выделить некоторые особенности их использования, с которыми мне удалось столкнуться.

Signal-slot механизм - это не просто вызов колбеков в чистом виде. Между сигналом и слотом устанавливается соединение, которое может быть 4-х типов:


  • DirectConnection - прямое соединение, когда сигнал моментально обрабатывается слотом;

  • QueuedConnection - сигнал добавляется в очередь и ожидает своего "выхода" в очереди сообщений, при этом поток, в котором возник сигнал не блокируется;

  • BlockingQueuedConnection - то же, что и QueuedConnection, но вызывающий поток блокируется, пока сигнал не будет обработан;

  • AutoConnection - автоматически выбирается DirectConnection, если сигнал вызывается из того же потока, в котором живет приемник, и QueuedConnection, если используются разные потоки.

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

Тип соединения указывается как параметр QObject.connect:

QObject.connect(doer, SIGNAL('event'), self.handle, Qt.DirectConnection)

Теперь, как это все работает на примере. Пусть есть задача, которую надо выполнить в отдельном потоке (класс Doer) и обработчик, который должен узнать о результате выполнения (класс Handler).

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

В случае DirectConnection, сигнал обрабатывается синхронно, в потоке, где выполнялась задача:

task in thread < Thread(Thread-1, started) >
handle in thread < Thread(Thread-1, started) >
handle finish
after notify


При QueuedConnection, сигнал обрабатывается асинхронно в главном потоке приложения:

task in thread < Thread(Thread-1, started) >
after notify
handle in thread < _MainThread(MainThread, started) >
handle finish


BlockingQueuedConnection заставляет поток, вызывающий сигнал, ждать обработки, которая происходит в главном потоке приложения:

task in thread < Thread(Thread-1, started) >
handle in thread < _MainThread(MainThread, started) >
handle finish
after notify


При AutoConnection ситуация такая же как и при QueuedConnection, так как сигнал и приемник в разных потоках:

task in thread < Thread(Thread-1, started) >
after notify
handle in thread <_MainThread(MainThread, started)>
handle finish


Но если изменить одну строчку кода результат будет таким же как при DirectConnection:

task in thread <_MainThread(MainThread, started)>
handle in thread <_MainThread(MainThread, started)>
handle finish
after notify


Тип соединения BlockingQueuedConnection стоит использовать только в многопоточных приложениях, так как в одном потоке может привести к dead lock'у, о чем Qt должно предупредить ворнингом:

Qt: Dead lock detected while activating a BlockingQueuedConnection

Таким образом, Qt позволяет гибко настраивать обработку сигналов в синхронном и асинхронном режиме, в одном или нескольких потоках.

Read More...