Sunday, July 6th 2008, 4:39pm UTC+1

You are not logged in.

  • Login
  • Register

Dear visitor, welcome to QtForum.org. If this is your first visit here, please read the Help. It explains how this page works. You must be registered before you can use all the page's features. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

mattG

Beginner

1

Tuesday, March 4th 2008, 8:21pm

QPushButton as Delegate in a QTableView

Hello,

I have an application based on the QT model view paradigm. I display model data in a QTableView and now I want to add a column showing a QPushButton (that allows the user to trigger some operation for the current row in the table). I have worked with delegates before and thought that a custom ButtonDelegate should be the right way to go - but I cannot figure out how to implement a QPushButton as part of a delegate.

Can anyone help me?


Thanks!


Matt
  • Go to the top of the page

2

Wednesday, March 5th 2008, 1:31am

RE: QPushButton as Delegate in a QTableView

I just paste you a part of my implementation o delegates, I hope you found it iteresting and helpul.

#include <QItemDelegate>
#include <QModelIndex>
#include <QObject>
#include <QSize>
#include <QSpinBox>

class SpinBoxDelegate : public QItemDelegate
{
Q_OBJECT
private:
SerialStringContainer *namecontainer;

public:
SpinBoxDelegate(QObject *parent, SerialStringContainer *cont);

QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;

void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;

void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const;
};


SpinBoxDelegate::SpinBoxDelegate(QObject *parent, SerialStringContainer *cont)
: QItemDelegate(parent)
{
namecontainer=cont;
}

QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */, const QModelIndex &index) const
{
if(index.column()==1)
{
QComboBox *editor=new QComboBox(parent);
editor->addItem(tr("Manual")); editor->addItem(tr("Auto"));
for(int b=0;b<8;b++) editor->addItem(QString(tr("Thermometer %0 - %1")).arg(b+1).arg(namecontainer->GetString(b+9)));
return editor;
}
QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
editor->setMinimum(0);
editor->setMaximum(50.1);
editor->setSingleStep(0.2);
editor->setDecimals(1);
editor->setSuffix(tr(" °C"));
editor->installEventFilter(const_cast<SpinBoxDelegate*>(this));
return editor;
}

void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(index.column()==1)
{
QString qs=index.model()->data(index, Qt::DisplayRole).toString();
QComboBox *cb = static_cast<QComboBox*>(editor);
cb->setCurrentIndex(cb->findText(qs));
return;
}
QString qs=index.model()->data(index, Qt::DisplayRole).toString();
qs.remove(tr(" °C")); // Remove terminating string for proper conversion to double
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
spinBox->setValue(qs.toDouble());
}

void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if(index.column()==1)
{
QComboBox *cb = static_cast<QComboBox*>(editor);
model->setData(index, cb->itemText(cb->currentIndex()));
return;
}
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
spinBox->interpretText();
model->setData(index,QString (tr("%1 °C")).arg(spinBox->value(),0,'f',1));
}

void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}

Its more complex, but I think you will catch the idea.
  • Go to the top of the page

mattG

Beginner

3

Wednesday, March 5th 2008, 5:01pm

RE: QPushButton as Delegate in a QTableView

Thanks a lot for your example!
I think I have seen a similar example based on the QSpinBox before but I have trouble transfering this to a delegate using a QPushButton. With a QPushButton I do not really edit any data but am interested in a triggered event whenever the user clicks on the button. I do not really know how this is realized with the "setModelData" method. Any ideas?

Thanks!


Matt
  • Go to the top of the page

4

Wednesday, March 5th 2008, 5:26pm

RE: QPushButton as Delegate in a QTableView

Take a closer look into my example. Depending on column I inserted a QComboBox or QDoubleSpinBox. The same you can do with QPushButton or any QWidget derivative. If you want to get some feedback from your button just connect it using signals/slots to other member. It doesn't matter if button is on the widget or in listbox. Even you can insert a derived class from QPushButton with already implemented methods responsible for user action.
  • Go to the top of the page

mattG

Beginner

5

Wednesday, March 5th 2008, 7:58pm

RE: QPushButton as Delegate in a QTableView

Thanks for pointing that out again! I think I understand it now... :)

However, my new problem is that the delegate is completely ignored by the application (The constructor seems to be the only method that is ever called during program execution) and the column in the table does not show a button. Another delegate I use in the same table (that is derived from QAbstractItemDelegate) works fine.
After some searching around I found that this problem does not only appear in my application but also when I compile the SpinBox delegate example provided by Trolltech in "examples/itemviews/spinboxdelegate". Again, the table is shown without the SpinBox provided by the delegate... ?(

Does anyone have an idea what I might be doing wrong?


Thanks!


Matt
  • Go to the top of the page

mattG

Beginner

6

Wednesday, March 5th 2008, 8:18pm

RE: QPushButton as Delegate in a QTableView

Uppps. The SpinBox delegate example works fine. I had not realized that I have to (double) click on a table field for the spin box to appear.

However, the problem with my ButtonDelegate persists. Here is my current (minimal) ButtonDelegate implementation:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <QPushButton>
#include "buttonDelegate.h"
 
#include <iostream>
using namespace std;

ButtonDelegate::ButtonDelegate(QObject *parent) : QItemDelegate(parent)
{
	cerr << "TEST 1\n";
}


QWidget* ButtonDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
{
	QPushButton *editor = new QPushButton("Test", parent);
	cerr << "TEST 2\n";

	return editor;
}


void ButtonDelegate::setEditorData(QWidget * /* editor */, const QModelIndex & /* index */) const
{
	cerr << "TEST 3\n";
}


void ButtonDelegate::setModelData(QWidget * /* editor */, QAbstractItemModel */* model */, const QModelIndex & /* index */) const
{
	cerr << "TEST 4\n";
}


void ButtonDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
	cerr << "TEST 5\n";
	editor->setGeometry(option.rect);
}


Does anyone know what is missing here?


Thanks,


Matt
  • Go to the top of the page

mattG

Beginner

7

Friday, March 7th 2008, 7:46pm

RE: QPushButton as Delegate in a QTableView

Ok, after some more searching around I now think that it is not possible to show a button using the "createEditor" method of "QItemDelegate". I am now considering to subclass "QAbstractItemDelegate" since I have complete freedom what to show by implementing the "paint" method. Here is my question: Can I somehow pass the "paint"-call to a "QPushButton" object to have a button drawn? Any ideas?


Thanks,


Matt
  • Go to the top of the page

Major

Beginner

8

Thursday, May 15th 2008, 9:48am

RE: QPushButton as Delegate in a QTableView

Hello, you need some more code for showing the buttons permanently.

Make your model editable:

Source code

1
2
3
4
5
6
7
Qt::ItemFlags ButtonTableModel::flags( const QModelIndex & index ) const
{
	if (!index.isValid())
         return Qt::ItemIsEnabled;

     return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}


Show the buttons permanently, e.g. in column 4:

Source code

1
2
for ( int i = 0; i < model->rowCount(); ++i )
		ui.tableView->openPersistentEditor( model->index(i, 4, QModelIndex()) );


You don't need to implement an inherited "QAbstractItemDelegate" class.
  • Go to the top of the page

Rate this thread