2012-06-25 2 views
2

Я пытаюсь заставить QStyledItemDelegate вести себя как пользовательский QWidget, который я написал, поэтому я могу переключить свой код на подход модели/представления.Как использовать пользовательский виджет с событиями/сигналами как QStyledItemDelegates?

Пользовательский QWidget представляет собой сложную кнопку, которая показывает четыре «суб-кнопки» в своих углах над мышью (так что всего в ней пять сигналов). Это также перетащить & с возможностью перемещения с помощью настраиваемой пиксельной карты. Для этого я использую mousePressEvent, mouseReleaseEvent, mouseMoveEvent, enterEvent и leaveEvent. Это то, что она выглядит с и без «вспомогательных кнопок», показанных при наведении мышей: enter image description here

С тех пор я переключил свой основной код, чтобы использовать модель/представление подход, и я пытаюсь использовать этот виджет как QStyledItemDelegate для мой индивидуальный ListView. Я попытался назначить пользовательский виджет как редактор, как это:

class ToolButtonDelegate(QStyledItemDelegate): 

    def __init__(self, parent=None): 
     super(ToolButtonDelegate, self).__init__(parent) 
     self.parent = parent 

    def createEditor(self, parent, option, index): 
     if not index.isValid(): 
      return False 
     btn = FancyButton(index.data(Qt.UserRole), parent=parent) 
     return btn 

Это кажется перспективным, как он рисует класс «FancyButton» для пункта I щелкнул. Тем не менее, мне нужно, чтобы это было мышью над событием. После немного больше исследований я попытался подключить слот QAbstractItemView.entered к QAbstractItemView.edit сигнала:

self.entered.connect(self.edit) 

Это работает только для первого элемента я двигаю курсор мыши над, то я получаю эти ошибки:

edit: editing failed 

Так что теперь я застрял снова с этими проблемами:

  • как правильно закрыть редактор (нет «QAbstractItemView.leave» событие или подобное).
  • как обеспечить, чтобы щелчки мыши фактически вызвать кнопки в классе FanyButton, а не просто взаимодействовать с QAbstractIremView

У меня есть чувство, что я заголовок в неправильном направлении здесь, так что любая помощь будет очень оценили.

Приветствия, откровенны

+0

Функция drag & drop явно работает, но я не вижу способа назначить любой из этих фильтров событий. Например. как я могу поймать ввод мыши и оставить событие для элемента в структуре модели/представления? –

+0

Кто-нибудь? Я немного застрял с этим сейчас. Мне в основном нужно нарисовать существующий пользовательский виджет со всеми его событиями мыши в (или как) делегат элемента. У меня есть мыши над эффектами, а drag & drop работает над виджетами, но не знаю, как использовать его в своем представлении как делегат сейчас. –

+0

@FrankRuer. Как насчет отправки вашего решения в качестве приемлемого ответа? ;-) – Beachwalker

ответ

0

AFAIK, вы не можете использовать пользовательские виджеты для просмотра элементов в списке/Table/Tree-View-делегатов. Вы можете использовать их для редактирования, но если для режима просмотра требуется что-то другое, кроме просто перерисовывания, вы довольно туманны.

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

Причина может заключаться в том, что представления должны быть быстрыми и способны отображать множество элементов, а наличие большого количества виджетов не является быстрым, поэтому они решили просто разрешить пользовательскую функцию перерисовки (которая позволяет им использовать только один контейнерный виджет с пользовательской покраской в ​​разных областях.)

Возможно, есть способ обойти его, и если так, я был бы рад услышать об этом.

Update

Если вам нужно перехватывать события, возможно, вы можете установить фильтр событий для представления контейнера, а затем использовать QListView::indexAt, чтобы найти правильный пункт/виджет/делегат отправить событие?

Затем вы можете использовать openPersistentEditor и closePersistentEditor на mouseenter/leave, чтобы разрешить редактирование, т. Е. Показать/закрыть свой пользовательский виджет на элементе.

+0

Я решил отказаться от делегатов и попытаться написать собственное представление, в котором вместо этого используются виджеты. Пока это работает, хотя я еще не совсем дошел до толпы. –

1

Я призываю вас вернуться к делегатам вместо виджетов, чисто из соображений производительности =)

Вы можете работать с делегатами мыши над событиями в методе краски с использованием состояний, в частности, QStyle :: State_MouseOver. Что касается кликов на кнопках, вы можете переопределить editorEvent, который получает все события мыши, а затем работает с областями, где произошли щелчки мыши. Например:

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    if (option.state & QStyle::State_MouseOver) 
    { 
     // draw stuff which appears on mouse over 
    } else { 
     // draw stuff that appears when mouse is not over control 
    } 
} 

bool editorEvent(QEvent *event, QAbstractItemModel*, const QStyleOptionViewItem &option, const QModelIndex &index) 
{ 
     // Emit a signal when the icon is clicked 
     if(event->type() == QEvent::MouseButtonRelease) 
     { 
      QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); 
      QRect editButtonRect = editIcon.rect().translated(editIconPos(option)); 
      QRect deleteButtonRect = deleteIcon.rect().translated(deleteIconPos(option)); 

      if(editButtonRect.contains(mouseEvent->pos())) 
      { 
       emit editIndexClicked(index); 
      } else if (deleteButtonRect.contains(mouseEvent->pos())) { 
       emit deleteIndexClicked(index); 
      } 
     } 
     return false; 
    } 

Также вы можете проверить эту тему HowTo create delegate for QTreeWidget?, это для QTreeWidget, но я думаю, что одни и те же методы будут применяться к вашему делу тоже.

+0

спасибо, но на этом этапе у меня есть виджеты, работающие с хорошей производительностью. Если это станет проблемой, я рассмотрю ваше предложение. –

Смежные вопросы