How to change QStyleOptionButton's text?



  • Now There 's a QTableView that show some data. At last column of the table,the value's type is bool,it's a switch of a kind of device.
    Thanks to the programme need to allow user to control the device,so I put a QPushButton ont the last column of QTableView by delegate. According to my design,the button's text is "Launch",when user click this button ,the button's text is "Stop:,if user click this button again ,the button's text will change to "Launch".
    So,I plain to use QItemDelegate and QStyleOptionButton,I produce a class that's name is SwitchButton inheriten QItemDelegate.
    First,I implement the QItemDelegate::paint();

    void SwitchDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        if(index.column() == 3)
        {
            QStyleOptionButton* btn = new QStyleOptionButton;
            btn->rect = option.rect;
            btn->text = tr("Launch");
            btn->state |= QStyle::State_Enabled;
            QApplication::style()->drawControl(QStyle::CE_PushButton,btn,painter);
            const_cast<SwitchDelegate*>(this)->switchButton_Map.insert(index,btn);
        }
        else
            QItemDelegate::paint(painter,option,index);
    }
    

    So far here ,everything is OK,the programme looks like this
    alt text

    Second,I replement editorEvent() for user can change the button's text by click the button.

    bool SwitchDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
    {
        if(event->type() == QEvent::MouseButtonPress && static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton)
        {
            if(switchButton_Map.keys().contains(index))
            {
                QStyleOptionButton* btn = switchButton_Map.value(index);
                if(btn->text == tr("Launch"))  //here,nothing to change...
                    btn->text = tr("Stop");
                else if(btn->text == tr("Stop"))
                    btn->text = tr("Launch");
    
            }
        }
        return QItemDelegate::editorEvent(event,model,option,index);
    }
    

    Arccording to my original design,the button's text will be changed when user clicked the button,but in fact ,there's no change when I click the button.

    How to change the text of QStyleOptionButton?



    • you should subclass QStyledItemDelegate, not QItemDelegate
    • you are leaking the QStyleOptionButton
    • if(index.column() == in a delegate is bad design. this ties the delegate to the particular model you are using. You should use QAbstractItemView::setItemDelegateForColumn instead
    • you don't need to reimplement editorEvent you can just connect to clicked
    • you need to store the changed boolean value in the model
    class SwitchDelegate : public QStyledItemDelegate{
        Q_OBJECT
        Q_DISABLE_COPY(SwitchDelegate)
    public:
        explicit SwitchDelegate(QObject* parent = Q_NULLPTR) 
            : QStyledItemDelegate(parent)
        {}
        void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const Q_DECL_OVERRIDE
        {
            QStyleOptionButton btn;
            btn.rect = option.rect;
            btn.text = textForValue(index.data().toBool());
            btn.state |= QStyle::State_Enabled;
            (option.widget ? option.widget.style() : QApplication::style())->drawControl(QStyle::CE_PushButton,&btn,painter);
        }
        QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE{
            return new QPushButton(parent);
        }
        void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE{
            QPushButton* button = qobject_cast<QPushButton*>(editor);
            Q_ASSERT(button);
            const bool started = index.data().toBool();
            button->setProperty("Started",started);
            button->setText(textForValue(started));
            QObject::connect(button,&QPushButton::clicked,button,[button]()->void{
                const bool started = button->property("Started").toBool();
                button->setProperty("Started",!started);
                button->setText(textForValue(!started));
            });
        }
        void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE{
            QPushButton* button = qobject_cast<QPushButton*>(editor);
            Q_ASSERT(button);
            model->setData(index,button->property("Started").toBool());
        }
    private:
        QString textForValue(bool val) const {
            if(val)
                return tr("Stop");
            return tr("Launch");
        }
    };
    


  • @VRonin
    Thank you very much.
    But there's till a problem.....when user open QTableView first,they will look a button on the one column of the table,in my hope,user can change the switch by click the button.but in fact ,user only change switch after doubleClick the button.How to show the button when user click the button rather than doubleClick



  • @VRonin
    I got it ,thanks


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.