Как создать делегат для QTreeWidget?
вот что я пытаюсь сделать (все родители и дети должны иметь закрыть кнопка справа, в будущем, только парящий элемент сможет показать * * кнопку Закрыть **):
мой код делегата:
class CloseButton : public QItemDelegate
{
Q_OBJECT
public:
CloseButton( QObject* parent = 0 )
: QItemDelegate( parent )
{};
QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
if ( index.column() == 1 )
{
QToolButton* button = new QToolButton( parent );
button->setIcon( QIcon( CLOSE_ICON ) );
//button->setFixedSize( 16, 16 );
//button->setAutoRaise( true );
//button->setVisible( true );
CONNECT( button, SIGNAL( clicked() ), this, SLOT( emitCommitData() ) );
return button;
}
return ( new QWidget );
}
private slots:
void emitCommitData()
{
emit commitData( qobject_cast< QWidget* >( sender() ) );
}
private:
//Q_DISABLE_COPY( CloseButton );
};
С QTreeWidget
подключение код:
recipientsView()->setItemDelegateForColumn( 1, new CloseButton( this ) );
здесь recipientsView()
- простой QTreeWidget
.
QToolButton
s не отображаются вообще (это должен быть во втором столбце, т. е. индекс столбца в дереве 1
). Что я делаю не так?
Я уже проверил все демонстрационные примеры Qt о делегатах и первый результат Google о QItemDelegate
и тому подобное.
3 ответов
можно использовать QStyledDelegate::paint
функция, чтобы нарисовать значок закрытия, без использования какого-либо виджета, и editorEvent
для получения событий мыши для элемента, даже если вы не используете редактор или сделать элемент редактируемым.
class CloseButton : public QStyledItemDelegate {
Q_OBJECT
public:
explicit CloseButton(QObject *parent = 0,
const QPixmap &closeIcon = QPixmap())
: QStyledItemDelegate(parent)
, m_closeIcon(closeIcon)
{
if(m_closeIcon.isNull())
{
m_closeIcon = qApp->style()
->standardPixmap(QStyle::SP_DialogCloseButton);
}
}
QPoint closeIconPos(const QStyleOptionViewItem &option) const {
return QPoint(option.rect.right() - m_closeIcon.width() - margin,
option.rect.center().y() - m_closeIcon.height()/2);
}
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const {
QStyledItemDelegate::paint(painter, option, index);
// Only display the close icon for top level items...
if(!index.parent().isValid()
// ...and when the mouse is hovering the item
// (mouseTracking must be enabled on the view)
&& (option.state & QStyle::State_MouseOver))
{
painter->drawPixmap(closeIconPos(option), m_closeIcon);
}
}
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QSize size = QStyledItemDelegate::sizeHint(option, index);
// Make some room for the close icon
if(!index.parent().isValid()) {
size.rwidth() += m_closeIcon.width() + margin * 2;
size.setHeight(qMax(size.height(),
m_closeIcon.height() + margin * 2));
}
return size;
}
bool editorEvent(QEvent *event, QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index)
{
// Emit a signal when the icon is clicked
if(!index.parent().isValid() &&
event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
QRect closeButtonRect = m_closeIcon.rect()
.translated(closeIconPos(option));
if(closeButtonRect.contains(mouseEvent->pos()))
{
emit closeIndexClicked(index);
}
}
return false;
}
signals:
void closeIndexClicked(const QModelIndex &);
private:
QPixmap m_closeIcon;
static const int margin = 2; // pixels to keep arount the icon
Q_DISABLE_COPY(CloseButton)
};
во-первых, я должен спросить, действительно ли вы используете QTreeWidget или, скорее, QTreeView? Вы не можете использовать пользовательские делегаты с QTreeWidget в соответствии с документацией для QTreeView, и вам придется использовать Qtree*View* и некоторую форму QAbstractItemModel, чтобы вы могли использовать пользовательский делегат.
Ах, к черту. Я вижу, что вы вызываете setItemDelegateForColumn, который является функцией QTreeView, но вы должны знать о разнице, поэтому я сохраняю вышеизложенное параграф. :)
Я бы проверил, что ваша модель флаги() функция возвращает Qt:: ItemIsEditable как часть своих флагов элементов. Метод createEditor () вызывается всякий раз, когда в представлении сообщается о событии редактирования. (События просмотра, которые вызовут редактирование, зависят от EditTriggers модели) обычно двойной щелчок по делегату вызовет редактирование по умолчанию, среди прочего.
Я сомневаюсь, что вы хотите, чтобы кнопка "Закрыть" появлялась только при двойном щелчке, хотя. Чтобы кнопка отображалась все время, вам придется переопределить функцию делегата paint (), чтобы нарисовать кнопку, среди прочего. Я нашел Qt пример StarDelegate Для быть весьма полезным в этом отношении, и я подозреваю, что Вы тоже найдете ее полезной.
вы можете использовать QItemDelegate с QTreeWidget таким образом (пример в PyQt, извините):
myTreeWidget = QtGui.QTreeWidget()
myTreeWidget.setItemDelegate(myDelegate())
class myDelegate(QtGui.QItemDelegate):
def paint(self, painter, option, index):
#Custom Draw Column 1
if index.column() == 1:
icon = QtGui.QIcon(index.data(QtCore.Qt.DecorationRole))
if icon:
icon.paint(painter, option.rect)
#You'll probably want to pass a different QRect
#Use the standard routine for other columns
else:
super(myDelegate, self).paint(painter, option, index)