Russian Qt Forum
Октябрь 04, 2024, 08:26 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Делегат для QComboBox  (Прочитано 9078 раз)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« : Октябрь 11, 2012, 12:51 »

Хочу сделать комбобокс, отображающий стили линий (сплошная, прерывистая...). Сперва накидал свой делегат для комбобокса, но быстро пришел к тому, что довольно тяжко отрисовать его так-же как и стандартный QComboBoxDelegate. Тут надо разбираться со стилями.

Теперь вот попытался разобраться как сделать прокси-делегат над QComboBoxDelegate, но тоже не получается. QComboBox владеет текущим делегатом и нет возможности его оттуда выдернуть, чтобы завернуть в прокси. QComboBoxDelegate - внутренний класс, от него нет возможности отнаследоваться.

Как эту проблему попроще можно решить?

Сейчас имею такую картинку со своим делегатом:
 
« Последнее редактирование: Октябрь 12, 2012, 10:56 от navrocky » Записан

Гугль в помощь
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Октябрь 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().
« Последнее редактирование: Октябрь 11, 2012, 13:03 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #2 : Октябрь 11, 2012, 13:04 »

И как оно смотрится? Иконки наверное ровняются по левому краю и не растягиваются по ширине комбика.

Я тоже об иконках думал, но хотелось как всегда странного )
Записан

Гугль в помощь
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #3 : Октябрь 11, 2012, 13:28 »

И как оно смотрится? Иконки наверное ровняются по левому краю и не растягиваются по ширине комбика.
Нет, конечно. А разве такой комбобокс не должен иметь фиксированную ширину?
На самом деле,  без иконок через делегаты нормальный комбобокс не сделаешь, т.к. делегаты отрисоваются только во вью, а при отрисовке самого комбобокса они не используются.
И я бы вместо комбобокса использовал QToolButton с меню, в которое и накидал бы эти иконки.
Записан

Qt 5.11/4.8.7 (X11/Win)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #4 : Октябрь 11, 2012, 19:01 »

Всё-таки я победил через делегат. С иконами было не красиво, в списке справа был пустой отступ под текст.

Рисование текущего элемента сделано в paintEvent комбобокса.

Записан

Гугль в помощь
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #5 : Октябрь 11, 2012, 21:35 »

в списке справа был пустой отступ под текст.
Вот эта проблема как раз легко и решалась через QToolButton с меню.
Записан

Qt 5.11/4.8.7 (X11/Win)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #6 : Октябрь 12, 2012, 10:56 »

В меню тоже икона позиционируется слева, а не по центру. Я уже пробовал. Можно только через CSS ее передвинуть...
Записан

Гугль в помощь
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #7 : Октябрь 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();
}
 
}
}
 
Записан

Гугль в помощь
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.203 секунд. Запросов: 23.