Название: Resize у QListView
Отправлено: Tapak от Января 29, 2009, 01:59
Написал небольшой виджет (QPopup) на основе QListView с использованием QItemDelegate для самостоятельной отрисовки. Хотелось бы, чтобы ширина виджета зависела от ширины элементов. Однако sizeHint делегата на виджет никак не влияет. Есть ли выход? C++ (Qt) struct QCountry { QCountry (const QString & n, const QPixmap & i) : name (n), image (i), selected (false) {}; QCountry() {}; // QVariant (metaType) compatible QCountry (const QString & n) : name (n) {}; // implicit ctor - convenient for indexOf bool operator == (const QCountry & c) const // indexOf comparator { return name.compare (c.name, Qt::CaseInsensitive) == 0; } QString name; QPixmap image; bool selected; }; typedef QList <QCountry> QCountryList; class QPopup : public QListView { class QDelegate : public QItemDelegate { public: QDelegate (QObject * parent) : QItemDelegate (parent) {}; void paint (QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const; QSize sizeHint (const QStyleOptionViewItem &, const QModelIndex &) const; const static int _margin = 4; }; class QListModel : public QAbstractListModel { public: QListModel (QObject * parent, QCountryList & list) : QAbstractListModel (parent), _list (list) {}; int rowCount (const QModelIndex & parent = QModelIndex()) const {return _list.size();} QVariant data (const QModelIndex & id, int /*role*/) const { return QVariant::fromValue (_list[id.row()]); } private: QCountryList & _list; }; public: QPopup (QCountryView * parent, QCountryList & list); private: bool event (QEvent *); QSize sizeHint() const {return QSize (140, 0);} // TEMP }; ... QCountryView::QPopup::QPopup (QCountryView * parent, QCountryList & list) : QListView (parent) { setWindowFlags (Qt::Popup); setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Expanding); setModel (new QListModel (this, list)); setItemDelegate (new QDelegate (this)); connect (this, SIGNAL (clicked (const QModelIndex &)), parent, SLOT (onPopupClick (const QModelIndex &))); } void QCountryView::QPopup::QDelegate::paint (QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { if(index.data().canConvert <QCountry> ()) { QCountry country = index.data().value <QCountry> (); QRect rect = option.rect; QPoint imgPos = rect.topLeft() + QPoint (_margin, (rect.height() - country.image.height())/2); painter->drawPixmap (imgPos, country.image); rect.setLeft (rect.left() + country.image.width() + _margin * 2); painter->setPen (country.selected ? Qt::black : Qt::lightGray); painter->drawText (rect.adjusted (0, 1, 0, 0), Qt::AlignLeft, country.name); } } QSize QCountryView::QPopup::QDelegate::sizeHint (const QStyleOptionViewItem & option, const QModelIndex & index) const { if(index.data().canConvert <QCountry> ()) { QCountry country = index.data().value <QCountry> (); QFontMetrics fm (option.font); int height = country.image.height() + 5; int width = fm.width (country.name) + country.image.width() + _margin * 3; return QSize (width, height); } return QSize(); }
Название: Re: Resize у QListView
Отправлено: kirill от Января 29, 2009, 09:03
sizeHint делегата влияет на делегат-эдитор. Попробуй QWidget::sizeHint() или QWidget::setSizePolicy();
Название: Re: Resize у QListView
Отправлено: lit-uriy от Января 29, 2009, 09:35
>Однако sizeHint делегата на виджет никак не влияет. И это правильно, ведь один из элементов может оказаться, в общем случае, много длинее других. Можно использовать вариант, который предложил kirill. Можно дать пользователю возможность изменять размер спискового представления, по аналогии с примером (http://wiki.crossplatform.ru/index.php/Изминение_размера_у_popup_списка_QComboBox)
Название: Re: Resize у QListView
Отправлено: Tapak от Января 29, 2009, 13:30
Попробуй QWidget::sizeHint() Сейчас именно так и делаю. setCornerWidget не хотел бы использовать. И это правильно, ведь один из элементов может оказаться, в общем случае, много длинее других. Но иногда нужно именно такое поведение. Чтобы виджет подстраивался под размер элементов.
|