Название: [РЕШЕНО] Делегат для QComboBox
Отправлено: navrocky от Октябрь 11, 2012, 12:51
Хочу сделать комбобокс, отображающий стили линий (сплошная, прерывистая...). Сперва накидал свой делегат для комбобокса, но быстро пришел к тому, что довольно тяжко отрисовать его так-же как и стандартный QComboBoxDelegate. Тут надо разбираться со стилями.
Теперь вот попытался разобраться как сделать прокси-делегат над QComboBoxDelegate, но тоже не получается. QComboBox владеет текущим делегатом и нет возможности его оттуда выдернуть, чтобы завернуть в прокси. QComboBoxDelegate - внутренний класс, от него нет возможности отнаследоваться.
Как эту проблему попроще можно решить?
Сейчас имею такую картинку со своим делегатом: (http://wstaw.org/m/2012/10/11/plasma-desktopVq1948.png)
Название: Re: Делегат для QComboBox
Отправлено: GreatSnake от Октябрь 11, 2012, 12:59
Я не парился с делегатами, а просто накидал иконки: C++ (Qt) Qt::PenStyle styles[] = { Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine, Qt::DashDotDotLine }; QSize sz( 92, 16 ); cb->setIconSize( sz ); for( int i = 0; i < 5; i++ ) { QBitmap pix( sz ); pix.clear(); QPainter painter( &pix ); painter.setRenderHint( QPainter::Antialiasing ); painter.setPen( QPen( Qt::black, 4, styles[i], Qt::RoundCap ) ); painter.drawLine( 2, sz.height() / 2, sz.width() - 2, sz.height() / 2 ); cb->addItem( pix, QString() ); }
QComboBoxDelegate - внутренний класс, от него нет возможности отнаследоваться. Создай свой делегат от QStyledItemDelegate и установи его на QComboBox::view().
Название: Re: Делегат для QComboBox
Отправлено: navrocky от Октябрь 11, 2012, 13:04
И как оно смотрится? Иконки наверное ровняются по левому краю и не растягиваются по ширине комбика.
Я тоже об иконках думал, но хотелось как всегда странного )
Название: Re: Делегат для QComboBox
Отправлено: GreatSnake от Октябрь 11, 2012, 13:28
И как оно смотрится? Иконки наверное ровняются по левому краю и не растягиваются по ширине комбика.
Нет, конечно. А разве такой комбобокс не должен иметь фиксированную ширину? На самом деле, без иконок через делегаты нормальный комбобокс не сделаешь, т.к. делегаты отрисоваются только во вью, а при отрисовке самого комбобокса они не используются. И я бы вместо комбобокса использовал QToolButton с меню, в которое и накидал бы эти иконки.
Название: Re: Делегат для QComboBox
Отправлено: navrocky от Октябрь 11, 2012, 19:01
Всё-таки я победил через делегат. С иконами было не красиво, в списке справа был пустой отступ под текст.
Рисование текущего элемента сделано в paintEvent комбобокса.
(http://wstaw.org/m/2012/10/11/plasma-desktopXi1938.png)
Название: Re: Делегат для QComboBox
Отправлено: GreatSnake от Октябрь 11, 2012, 21:35
в списке справа был пустой отступ под текст.
Вот эта проблема как раз легко и решалась через QToolButton с меню.
Название: Re: Делегат для QComboBox
Отправлено: navrocky от Октябрь 12, 2012, 10:56
В меню тоже икона позиционируется слева, а не по центру. Я уже пробовал. Можно только через CSS ее передвинуть...
Название: Re: [РЕШЕНО] Делегат для QComboBox
Отправлено: navrocky от Октябрь 12, 2012, 11:15
На всякий случай код: framescombobox.h C++ (Qt) #pragma once #include <QComboBox> #include <QAbstractItemDelegate> #include "../common/prop_ctl_iface.h" namespace vd { namespace prop_dialogs { enum frame_type_t { ft_stylized = 0, ft_solid = 1, ft_dashed = 2, ft_dotted = 3, ft_microdashed = 4 }; class styles_combo_item_delegate : public QAbstractItemDelegate { Q_OBJECT public: styles_combo_item_delegate(QObject *parent); QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class frames_combo_box : public QComboBox, public prop_ctl_iface { Q_OBJECT Q_PROPERTY(QString style_property READ style_property WRITE set_style_property) Q_PROPERTY(QString frame_property READ frame_property WRITE set_frame_property) Q_PROPERTY(bool enum_mode READ enum_mode WRITE set_enum_mode) public: frames_combo_box(QWidget *parent); bool enum_mode() const {return enum_mode_;} void set_enum_mode(bool value); QString style_property() const {return style_property_;} void set_style_property(const QString& v) {style_property_ = v;} QString frame_property() const {return frame_property_;} void set_frame_property(const QString& v) {frame_property_ = v;} protected: virtual void selection_changed(); void paintEvent(QPaintEvent *e); QSize sizeHint() const; private slots: void update_property(); private: void update_items(); QString style_property_; QString frame_property_; bool enum_mode_; bool block_updating_; }; } }
framescombobox.cpp: C++ (Qt) #include "framescombobox.h" #include <QPainter> #include <QDebug> #include <QApplication> #include <QStyle> #include <common/scoped_tools.h> #include <entities/props/float_entity_property.h> namespace vd { namespace prop_dialogs { const QSize c_icon_size(80, 20); void draw_item(QPainter* painter, const QRect& rect, frame_type_t ft, QColor line_color) { int vcenter = rect.center().y(); switch (ft) { case ft_stylized: { painter->setRenderHint(QPainter::Antialiasing, true); QRectF r = rect; r.adjust(0.5, 0.5, -0.5, -0.5); QLinearGradient grad(0, 0, 0, r.height()); grad.setColorAt(0.0, QColor(255, 255, 255)); grad.setColorAt(1.0, QColor(149, 192, 0)); painter->setPen(Qt::darkGray); painter->setBrush(grad); painter->drawRoundedRect(r, 4, 4); break; } case ft_solid: { QPen pen(line_color); pen.setWidth(2); painter->setPen(pen); painter->drawLine(rect.left(), vcenter, rect.right(), vcenter); break; } case ft_microdashed: { QPen pen(line_color); pen.setWidth(2); pen.setStyle(Qt::DashLine); painter->setPen(pen); painter->drawLine(rect.left(), vcenter, rect.right(), vcenter); break; } case ft_dotted: { QPen pen(line_color); pen.setWidth(2); pen.setStyle(Qt::DotLine); painter->setPen(pen); painter->drawLine(rect.left(), vcenter, rect.right(), vcenter); break; } case ft_dashed: { QPen pen(line_color); pen.setWidth(2); pen.setStyle(Qt::DashLine); pen.setDashPattern(QVector<qreal>() << 10 << 10); painter->setPen(pen); painter->drawLine(rect.left(), vcenter, rect.right(), vcenter); break; } } } //////////////////////////////////////////////////////////////////////////////// styles_combo_item_delegate::styles_combo_item_delegate(QObject *parent) : QAbstractItemDelegate(parent) { } void styles_combo_item_delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QRect rect = option.rect.adjusted(4, 4, -4, -4); QStyle* style = QApplication::style(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter); QColor line_color = option.palette.color(QPalette::WindowText); frame_type_t type = static_cast<frame_type_t>(index.data(Qt::UserRole).toInt()); draw_item(painter, rect, type, line_color); } QSize styles_combo_item_delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { return QSize(70,20); } //////////////////////////////////////////////////////////////////////////////// frames_combo_box::frames_combo_box(QWidget *parent) : QComboBox(parent) , enum_mode_(false) , block_updating_(false) { setItemDelegate(new styles_combo_item_delegate(this)); update_items(); connect(this, SIGNAL(currentIndexChanged(int)), SLOT(update_property())); } void frames_combo_box::update_items() { SCOPE_COCK_FLAG(block_updating_); clear(); // QColor col = palette().color(QPalette::WindowText); #define ADD_ITEM(x) addItem(QString(), x); ADD_ITEM(ft_stylized); ADD_ITEM(ft_solid); if (!enum_mode_) { ADD_ITEM(ft_dashed); ADD_ITEM(ft_dotted); ADD_ITEM(ft_microdashed); } } void frames_combo_box::update_property() { foreach (entity* en, prop_ctx()->selection) { // en->change_prop_value<float_entity_property>(frame_property_, currentIndex()); } // prop_ctl_iface::update_property(); } void frames_combo_box::selection_changed() { float_entity_property* prop = 0; // prop_by_name<float_entity_property>(property_); if (!prop) return; setCurrentIndex(prop->value()); setToolTip(prop->get_class()->description()); } void frames_combo_box::paintEvent(QPaintEvent* e) { QStyleOptionComboBox opt; initStyleOption(&opt); QStyle* style = QApplication::style(); QPainter p(this); style->drawComplexControl(QStyle::CC_ComboBox, &opt, &p, this); QRect r = style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); r.adjust(2, 2, -2, -2); draw_item(&p, r, ft_stylized, Qt::black); } QSize frames_combo_box::sizeHint() const { QSize sz = QComboBox::sizeHint(); sz.setWidth(60); return sz; } void frames_combo_box::set_enum_mode(bool v) { if (enum_mode_ == v) return; enum_mode_ = v; update_items(); } } }
|