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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QComboBox + CheckBox Delegate  (Прочитано 10154 раз)
INZER
Новичок

Offline Offline

Сообщений: 20


Просмотр профиля
« : Июнь 04, 2022, 00:32 »

Есть выпадающий комбобокс с реализованным делегатом (итемы - чекбоксы)

Код:
class CheckBoxListDelegate;

class CheckBoxList: public QComboBox
{
    Q_OBJECT
 public:
    CheckBoxList(QString text, QWidget *widget = 0);
    virtual ~CheckBoxList();
    virtual void paintEvent(QPaintEvent *);
public slots:
    void SetDisplayText(QString strr);
    QString GetDisplayText() const;
private:
    CheckBoxListDelegate * delegate;
    QString m_DisplayText;
private slots:
    void act ();
};
CheckBoxList::CheckBoxList(QString text, QWidget *widget )
:QComboBox(widget),m_DisplayText(text)
{
    delegate = new CheckBoxListDelegate(this);
    view()->setItemDelegate(delegate);
    view()->setEditTriggers(QAbstractItemView::CurrentChanged);
    connect(delegate,SIGNAL(dataChanged()),this,SLOT(act()));
}


CheckBoxList::~CheckBoxList()
{
}


void CheckBoxList::act()
{
    emit activated(0);
}

void CheckBoxList::paintEvent(QPaintEvent *)
{
    QStylePainter painter(this);
    painter.setPen(palette().color(QPalette::Text));

    // draw the combobox frame, focusrect and selected etc.
    QStyleOptionComboBox opt;
    initStyleOption(&opt);

    // if no display text been set , use "..." as default
    if(m_DisplayText.isNull())
        opt.currentText = "...";
    else
        opt.currentText = m_DisplayText;
    painter.drawComplexControl(QStyle::CC_ComboBox, opt);

    // draw the icon and text
    painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
}


void CheckBoxList::SetDisplayText(QString strr)
{
    m_DisplayText = strr;
}

QString CheckBoxList::GetDisplayText() const
{
    return m_DisplayText;
}
Делегат:
Код:
class CheckBoxListDelegate : public QItemDelegate
{
    Q_OBJECT
signals:
    void dataChanged () const;
public slots:
    void dCH ()
    {
        emit dataChanged();
    }
public:
    CheckBoxListDelegate(QObject *parent)
         : QItemDelegate(parent)
    {
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const
    {
        //Get item data
        bool value = index.data(Qt::UserRole).toBool();
        QString text = index.data(Qt::DisplayRole).toString();

        // fill style options with item data
        const QStyle *style = QApplication::style();
        QStyleOptionButton opt;
        opt.state |= value ? QStyle::State_On : QStyle::State_Off;
        opt.state |= QStyle::State_Enabled;
        opt.text = text;
        opt.rect = option.rect;

        // draw item data as CheckBox
                style->drawControl(QStyle::CE_CheckBox,&opt,painter);
    }

    QWidget *createEditor(QWidget *parent,
         const QStyleOptionViewItem &,
         const QModelIndex &) const
    {
        // create check box as our editor
         QCheckBox *editor = new QCheckBox(parent);
         return editor;
    }

     void setEditorData(QWidget *editor,
                                         const QModelIndex &index) const
     {
         //set editor data
         QCheckBox *myEditor = static_cast<QCheckBox*>(editor);
         myEditor->setText(index.data(Qt::DisplayRole).toString());
         myEditor->setChecked(index.data(Qt::UserRole).toBool());

     }

     void setModelData(QWidget *editor, QAbstractItemModel *model,
                                        const QModelIndex &index) const
     {
         //get the value from the editor (CheckBox)
         QCheckBox *myEditor = static_cast<QCheckBox*>(editor);
         bool value = myEditor->isChecked();

         //set model data
         QMap<int,QVariant> data;
         data.insert(Qt::DisplayRole,myEditor->text());
         data.insert(Qt::UserRole,value);
         model->setItemData(index,data);
        emit dataChanged();
     }
 };

Использование во вью:
Код:
    QHBoxLayout * labLay = new QHBoxLayout (ui->gbLabel);
    cblLabel = new CheckBoxList (QString::fromLocal8Bit("Выберите метку ..."), ui->gbLabel);
    labLay->addWidget(cblLabel);
    connect(cblLabel,SIGNAL(activated(int)),this,SLOT(changedLabelSettings()));

ну и в конце концов данные в выпадающий список предостаялются моделью
Код:
cblLabel->setModel(metkaModel);

То есть изменение "отмеченности" чекбокса прокитдывается из делегата.
Код писался давно и по какому то примеру, точно уже не вспомню. Однако сомнения закрались в коректности такого подхода, прочетом статей, но без примеров как правильно уведомить вью об изменении данных

А так же коспилятор рисуте ворнинги напротив константных сигналов делегата и слота класса CheckBoxList. Однако константность убрать невозмоно так как сигнал эмитится констатнтным методом

Подскажите пожалуйста как сделать красиво.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 861


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #1 : Июнь 05, 2022, 14:40 »

А как с этой... этим комбобоксом работать? Есть минимальный проект?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
INZER
Новичок

Offline Offline

Сообщений: 20


Просмотр профиля
« Ответ #2 : Июнь 06, 2022, 18:39 »

Да, конечно


https://disk.yandex.ru/i/J_cX-kWAehPGSQ
Записан
INZER
Новичок

Offline Offline

Сообщений: 20


Просмотр профиля
« Ответ #3 : Июнь 07, 2022, 10:04 »

А как с этой... этим комбобоксом работать? Есть минимальный проект?

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

Меня смущают строки 33 и 45 filterDialog.h

Как избежать этого ворнинга
https://github.com/KDE/clazy/blob/1.10/docs/checks/README-const-signal-or-slot.md

Ну и вобще кажется что сам подход реализации неверен.
Проект доступен по ссылке:
https://disk.yandex.ru/d/Q5z-owgKKAguVg

Так же получая сигнал об изменении модели из метода делегата setModelData я оповещаю вью о всех изменениях элементов (в том числе об активации отдельных ячеек). Хотелось бы узнавать только об изменении состояния чекбокса.
« Последнее редактирование: Июнь 07, 2022, 12:49 от INZER » Записан
INZER
Новичок

Offline Offline

Сообщений: 20


Просмотр профиля
« Ответ #4 : Июнь 07, 2022, 16:57 »

Я впринципе разобрался, может кому будет полезно.
Сигнал об изменении (в моем случае выбор чекбокса в выпадающем списке) получаю не от делегата а из модели.
void QStandardItemModel::itemChanged(QStandardItem *item)



Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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