Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to check uncheck a checkbox when clicking on text



  • Hi,

    I created a group of checkboxes in a combo box. It works fine, but I would also like to click on the text next to the check box besides the check box itself to check and uncheck the box.

    Any ideas how to do it. Multiselect doesn't seem to do the trick.

    QList<QStandardItem *> typeCheckBoxes;
    QStringList typeNames;
    QStandardItemModel *typeModel;

    typeNames << "ujkkl" << "alkjbs" << "djklef" << "hijkl";

    for(int i = 0; i < selectedNames.size(); i++)
    {
    typeCheckBoxes << new QStandardItem();
    typeCheckBoxes[i]->setText(typeNames[i]);
    typeModel->setItem(i, 0, typeCheckBoxes[i]);

         typeCheckBoxes[i]->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
         typeCheckBoxes[i]->setData(Qt::Checked, Qt::CheckStateRole);
         typeCheckBoxes[i]->setCheckable(true);
    

    }

    Thanks in advance.



  • I would play around with connecting the signal from the combo box when an item/row is clicked QComboBox::activated(int index) and connecting that to a slot that flips the check state of the box for that index.



  • Does it detect clicking on the text, nit just the checkbox?



  • It would detect clicking on the row of the combobox popup that contains the checkbox widget.



  • Well, I tried it and it doesn't work.

    Assume I declared the slot in .h file

    connect(ui->typeComboBox, SIGNAL(activated(int)), this, SLOT(onComboboxActivated(int)));

    void MainWindow::onComboboxActivated(int index)
    {
    qDebug() << index; //always returns 0 and sometimes does not eturn anything. Doesn't even detect the checkbox checked.
    }



  • Hmm I thought that would be enough to get it to work. What I have found out about QComboBox is that it is a lot more difficult to get them to do anything custom than one might like. I have a whole class I made for my applications that extends QComboBox and makes it become a "selectable combobox".

    The way I handle it within my class is to create a QListView and QStandardItemModel. Then I set the combobox's view as the listview. I connect QListView::clicked(const QModelIndex& index) with a slot I made to handle the click.

    Here is a loose example of how I have been able to do it, although this is non-working since I stripped out a lot of additional things the code does and don't want to post all headers and such. It ends up looking something like this:

    QComboBox* combobox = new QComboBox(this);
    QListView* listview = new QListView(this);
    QStandardItemModel* model = new QStandardItemModel(this);
    listview->setModel(model);
    
    connect(listview, &QListView::clicked, this, &SelectableComboBox::ButtonClicked);
    
    void SelectableComboBox::ButtonClicked(const QModelIndex& index)
    {
       auto model = this->model();
      bool isSelected = index.data(Qt::CheckStateRole).toInt() == static_cast<int>(Qt::Checked);
      model->setData(index, !isSelected, Qt::CheckStateRole);
    }
    

    I also then pair this up with a custom item delegate that paints the checkbox widgets how the should be painted.
    This stackoverflow thread ended up being one of the most useful posts to get me on the right track.

    Here is a quick example of what you could potentially do if you customize QComboBox by using your own listview and painting.
    SelectableComboBox.gif



  • Thank you. This is useful but it maybe a big rewrite with what I already have.



  • Well, with a lot of investigation plus presstab's help I found a simpler solution. At least I'm at the point where I can click on the text and get the signal.

    QList<QStandardItem *> typeCheckBoxes;
    QStringList typeNames;
    QStandardItemModel *typeModel;

    eventsByName->setModel(typeModel);

    typeNames << "ujkkl" << "alkjbs" << "djklef" << "hijkl";

    for(int i = 0; i < selectedNames.size(); i++)
    {
    typeCheckBoxes << new QStandardItem();
    typeCheckBoxes[i]->setText(typeNames[i]);
    typeModel->setItem(i, 0, typeCheckBoxes[i]);

     typeCheckBoxes[i]->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
     typeCheckBoxes[i]->setData(Qt::Checked, Qt::CheckStateRole);
     typeCheckBoxes[i]->setCheckable(true);
    

    }

    ui->typeComboBox->setModel(typeModel);
    //the following line is key!!
    ui->typeComboBox->setView(eventsByName); //assign the QListView of items (labels) so users can click on the label to get the same results

    //now for the signal/slot; thanks presstab!
    connect(eventsByName, SIGNAL(clicked(const QModelIndex &)), this, SLOT(typeLabelClicked(const QModelIndex &)));

    //slot handle processing here - will try presstab solution or a version of it :D
    void MainWindow::typeLabelClicked(const QModelIndex &index)
    {
    qDebug() << index.data(0).toString();
    }



  • Forgot this declaration:
    QListView *eventsByName = new QListView;


Log in to reply