PDA

View Full Version : How does the QItemDelegate work?



SailinShoes
2nd March 2008, 10:27
Hello,

I have followed the example of creating a spinboxdelegate in a QTableWidget.
http://doc.trolltech.com/4.3/itemviews-spinboxdelegate.html

I have subclassed the QTableWidget in order to specify the return as hotkey for both open(F2) and close(return) the spinbox delegate. To do that I have overrided the keyPressEvent. This is the example code of the KeyPressEvent:


void MyTableWidget::keyPressEvent(QKeyEvent *e)
{

QKeyEvent *n;

if(e->key() == Qt::Key_Return)
{

n = new QKeyEvent(e->type(), Qt::Key_F2, e->modifiers(), e->text(), e->isAutoRepeat(), e->count());

}
else
{

n = e;

}

QTableWidget::keyPressEvent(n);

}

I use:
tableWidget->setItemDelegateForColumn(1, new SpinBoxDelegate);

instead of the example codes:
SpinBoxDelegate delegate;
tableView.setItemDelegate(&delegate);

When I crosscompile & and transfer the example code to an embedded system (Arm9, QTopia 4.3) the spinbox delegate and its methods createEditor and setEditorData is never called when the cell is opened for editing?

I really need this to work. I have no idea why the spinbox delegate does not work on the embedded system? If you need further info to be able to help I will provide it for you.

Thank you in advance...

wysota
2nd March 2008, 10:43
Why do you override the key event like that? How about handling the key by calling QAbstractItemView::edit() on the cell you want to edit? Just make sure your key handler is called at all.

SailinShoes
2nd March 2008, 11:08
Hi wysota,

I dont know if i follow you...do you mean something like this?


void MyTableWidget::keyPressEvent(QKeyEvent *e)
{

QKeyEvent *n;

if(e->key() == Qt::Key_Return)
{

QAbstractItemView::edit(currentIndex())

}

QTableWidget::keyPressEvent(n);

}

SailinShoes
2nd March 2008, 11:21
Sorry the previous dont work...I mean like this:


void MyTableWidget::keyPressEvent(QKeyEvent *e)
{

QAbstractItemView::edit(currentIndex(), QAbstractItemView::EditKeyPressed, e);
QTableWidget::keyPressEvent(e);

}

jpn
2nd March 2008, 11:47
Using QShortcut is also an option. If you want to edit with any key you might want to take a look at QAbstractItemView::editTriggers.

SailinShoes
2nd March 2008, 11:54
Hello again,

These solutions you have proposed works just fine on my laptop...but neither one of them make it possible to use the spinbox delegate on the arm9 and QTopia? It just opens the cell for editing and there is no contact with the spinbox delegate?

jpn
2nd March 2008, 12:10
So, there's a QLineEdit editor or what? Could you assure that SpinBoxDelegate::createEditor() gets called?

wysota
2nd March 2008, 12:17
You are allocating the delegate on the stack and it gets out of scope immediately after you return from the method that sets the delegate and the delegate gets destroyed and a default delegate takes its place.

SailinShoes
2nd March 2008, 12:28
So, there's a QLineEdit editor or what?

How do you mean? I think there is yes?

Could you assure that SpinBoxDelegate::createEditor() gets called?

On my laptop yes. The SpinBoxDelegate::createEditor() is called on my laptop...I can set a toggle break point in it and debug it when called...

But It never stops at the break point when debugging on the arm9? I also have qDebug output traces in each SpinBoxDelegate method but none is called on the arm9?

Im somewhat confused and cannot understand why? Could it be some limitation in QTopia? Differencies in the plattforms?

SailinShoes
2nd March 2008, 12:51
wysota I qoute you:

"You are allocating the delegate on the stack and it gets out of scope immediately after you return from the method that sets the delegate and the delegate gets destroyed and a default delegate takes its place."

This sounds very reasonable, it could be. I will look into this tomorrow monday. I was just passing my job to check my mails, but was stuck on this problem I have had for a while.

SailinShoes
3rd March 2008, 09:25
If I can override the F2 (open edit) another hotkey using:

QAbstractItemView::edit(currentIndex(), QAbstractItemView::EditKeyPressed, e);

How do I override the up & down buttonwhen in edit mode?

wysota
3rd March 2008, 12:54
Reimplement the key event handler for your editor returned by the delegate or install an event filter on the editor and handle those keys in the filter.

SailinShoes
3rd March 2008, 16:03
Thank you for your reply wysota
"Reimplement the key event handler for your editor returned by the delegate or install an event filter on the editor and handle those keys in the filter."

I have done this on a subclassed QDoubleSpinbox:



void DoubleSpinBox::keyPressEvent(QKeyEvent *e)
{

// UP
if(e->key() == Qt::Key_Launch6)
{

double value = this->text().toDouble();
value = value + singleStep;
emit valueChanged(value);

}
// DOWN
else if(e->key() == Qt::Key_Launch7)
{

double value = this->text().toDouble();
value = value - singleStep;
emit valueChanged(value);

}

}

...and runned the subclassed spinbox on the embedded system and it works alright.

But I still cant get the spinbox delegate example to work on the embedded system with an overrided keypress?



void MyTableWidget::keyPressEvent(QKeyEvent *e)
{

switch(e->key())
{

case Qt::Key_Launch5:
{

QAbstractItemView::edit(currentIndex(), QAbstractItemView::EditKeyPressed, e);

}
break;
default:
break;

}

QTableWidget::keyPressEvent(e);

}

...open the cell to be edited but the spinbox delegate is still not called (createEditor and setEditorData)? I have taken your previous advice about stack allocation into thought, but I cant see that this is the case?

jpn
3rd March 2008, 16:40
...and runned the subclassed spinbox on the embedded system and it works alright.

Actually I'm surprised if your DoubleSpinBox::keyPressEvent() works at all because I don't see the value being set anywhere. All you do is reading the value, adjusting it and then you emit a signal which QDoubleSpinBox is supposed to emit on its own when its value changes. Oh, and again, why not use QShortcut which does the trick in one line of code per step direction:


QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
QShortcut* upShortcut = new QShortcut(Qt::Key_Launch6, spinBox, SLOT(stepUp()));
...




But I still cant get the spinbox delegate example to work on the embedded system with an overrided keypress?

Are you using #ifdef's anywhere in your application to do things differently on the embedded device?

SailinShoes
3rd March 2008, 18:47
Hi jpn,

This is my subclassed QDoubleSpinBox.h code :



#ifndef DOUBLESPINBOX_H
#define DOUBLESPINBOX_H



#include <QDoubleSpinBox>
#include <QKeyEvent>
#include <QDebug>



class DoubleSpinBox : public QDoubleSpinBox
{

Q_OBJECT

public:
DoubleSpinBox(QWidget *parent);
virtual void keyPressEvent(QKeyEvent *e);
~DoubleSpinBox();

public slots:
virtual void setValue(double value);

private:
double presentvalue;
double singleStep;

};

#endif


...and this is my subclassed QDoubleSpinbox.cpp code :



#include "DoubleSpinBox.h"

DoubleSpinBox::DoubleSpinBox(QWidget *parent)
: QDoubleSpinBox(parent)
{



}

void DoubleSpinBox::keyPressEvent(QKeyEvent *e)
{

if(e->key() == Qt::Key_A)
{

double value = this->text().toDouble();
value = value + singleStep;
setValue(value);

}
else if(e->key() == Qt::Key_B)
{

double value = this->text().toDouble();
value = value - singleStep;
setValue(value);

}

}

void DoubleSpinBox::setValue(double value)
{

int decimals;
static double oldValue;

decimals = 0;
singleStep = 0;

qDebug() << "value = "<< value;

if( value >= 0.500 && value <= 0.999 )
{

decimals = 3;
singleStep = 0.001;

if(oldValue == 1.00)
{

value = 0.999;

}

}
else if(value >= 1.00 && value <= 9.99)
{

decimals = 2;
singleStep = 0.01;

if(oldValue == 10.0)
{

value = 9.99;

}

}
else if(value >= 10.0 && value <= 99.9)
{

decimals = 1;
singleStep = 0.1;

if(oldValue == 100)
{

value = 99.9;

}

}
else if(value >= 100 && value <= 999)
{

decimals = 0;
singleStep = 1;

}

setDecimals(decimals);
setSingleStep(singleStep);

oldValue = value;

QDoubleSpinBox::setValue(value);

}

DoubleSpinBox::~DoubleSpinBox()
{



}

I have not tried your solution yet...i will. I still cant open a cell (with a spinbox delegate) for editing when running the embedded system. I have no idea why?

SailinShoes
3rd March 2008, 18:54
I have just tried this keyPressEvent in the DoubleSpinBox to see if I can increase decrease the value with the DoubleSpinBox running isolated.

It is not supposed to have the KeyPressEvent. It is just the overrided slot set Value That should be there.

jpn
3rd March 2008, 18:59
Why are you making things over-complex? What's the point of shadowing QDoubleSpinBox::setValue() and keeping your own versions of value & single step which are already properties of QDoubleSpinBox? All you need is to start using the built-in class properly.

SailinShoes
3rd March 2008, 19:10
Why are you making things over-complex? What's the point of shadowing QDoubleSpinBox::setValue() and keeping your own versions of value & single step which are already properties of QDoubleSpinBox? All you need is to start using the built-in class properly.

I want my spinbox to have minimum 0.5 and maximum 999. The value should always have three significant digits. How do I solve that if dont subclass the QDoubleSpinBox?

jpn
3rd March 2008, 19:18
I want my spinbox to have minimum 0.5 and maximum 999. The value should always have three significant digits. How do I solve that if dont subclass the QDoubleSpinBox?

QDoubleSpinBox::minimum
QDoubleSpinBox::maximum
QDoubleSpinBox::decimals
QDoubleSpinBox::singleStep


And if you really need some custom fancy formatting you reimplement QDoubleSpinBox::textFromValue() and QDoubleSpinBox::valueFromText(). You don't "rewrite" non-virtual setValue().

PS. There are buttons for quotes and code snippets. Could you start using them, please?

SailinShoes
3rd March 2008, 19:37
And if you really need some custom fancy formatting you reimplement QDoubleSpinBox::textFromValue() and QDoubleSpinBox::valueFromText(). You don't "rewrite" non-virtual setValue().

jpn, I will follow your advices.

wysota
3rd March 2008, 23:32
As for your Qtopia problem - did you create the delegate on heap as advised?