PDA

View Full Version : QTableWidget issues



Djony
16th November 2006, 12:28
Hi!

I am relatively new with Qt and trying to develop an application with two QTableWidget in it. (That is not my idea, my chief asked for it). Now, those tho qtable widget should be in one section, same context view (like there are two items in one qlistviewidget, where listwidget is scrolling for tho tables). I even have a picture what should it look like. This is the picture: http://img137.imageshack.us/my.php?image=ev3jr3.jpg
The lower qtablewidget widget should be smaller then the upper. Whole section should be scrolling at the same time with the bigger (upper) qtablewidget. Does any of you know, how can I implement this? Should I use same widget which needs to be parent of both qtablewidgets? If that's the case, which widget I need to use? Or, plan B: the upper qtablewdiget needs to be parent of lower qtablewidget (how to implement this)? I am really clueless, and I hope I've explained what is the problem (have no idea how to implement this).

I'll appreciate any answer, thanx!

wysota
16th November 2006, 14:08
I think you should start from simple things and then work your way up until you reach the exact solution. The exact arrangement of widgets can be done at later stage. You should start with syncing scrolling of those two views (which should be achievable simply by connecting appropriate signals and slots between them). When you have that, you can continue with something more complex.

Djony
16th November 2006, 15:08
Yeah, I understand what you say, but I 've pretty much done all that already (I am talking about table's). But now I have issues about how I need to organize them, and what paretn widget I need to use, and how to achieve proper scrolling etc... So, thank you for your reply, but it doesn't solve my problem.

Hm... I am reading your post again, and thinking maybe we didn't undertand each other completely. How do you think I can get widget scrolling in sync if I haven't organize them? The widgets that should be scrolling in sync are not tables, but bigger table and area in which are tables. But I don't have no idea what parent widget I need to use, nor do I now how to get everything in sync (Yes, I've heard for connecting signals and slots, but the qustion is whose signals with whose slots?).

Sorry for my bad English, and thank you for reply :)

wysota
16th November 2006, 16:38
But I don't have no idea what parent widget I need to use, nor do I now how to get everything in sync
The parent has nothing to do with it. It can be for example QWidget.

If you're asking about the child widgets, then in general if you want to have a scrollable canvas with widgets inside, you should use QScrollArea and if you want to scroll something which is not a widget, then go for one of the views.


(Yes, I've heard for connecting signals and slots, but the qustion is whose signals with whose slots?).
Connect the scrollbars, so that if you move one of them, the other moves as well. It is possible that you'll need to do that through a custom slot which will scale between scrollbars as they will probably have different ranges.

Djony
17th November 2006, 09:50
When I say parent, I mean what "display object" I need to use to get tables in one area and bigger table scrolling with that area. I know it should be widget, but don't have clue what widget to use. Yo've named QScrollArea. But, correct me if I am wrong, QScrollArea can only have one child widget. Am I wright. The whole problem seems to be (at least that's my point of view at the moment) which display object to use, so tables can be shown in it as child widgets. That means, to have autoscroll, when lower table is formed (because tables are not created at the same time, lower table needs to be created when item is selected in upper table), so the user can scroll that big display object in which are tables. So, which display object to use?

Thanx for your replies on both topics :)

wysota
17th November 2006, 10:05
When I say parent, I mean what "display object" I need to use to get tables in one area and bigger table scrolling with that area.
I think I don't understand :)


But, correct me if I am wrong, QScrollArea can only have one child widget. Am I wright.
Basically you're right but in the end you're wrong - QScrollArea may have a single child widget which in turn has many-many-many child widgets of its own, resulting in the scrollarea having multiple widgets displayed in it.


The whole problem seems to be (at least that's my point of view at the moment) which display object to use, so tables can be shown in it as child widgets.
I still don't understand what you mean by "display object". My answer (QWidget) still stands... It is a "display object" after all...


That means, to have autoscroll, when lower table is formed (because tables are not created at the same time, lower table needs to be created when item is selected in upper table), so the user can scroll that big display object in which are tables. So, which display object to use?

QScrollArea? :)

I think you should just open Qt Designer and start experimenting. Just remember you won't be able to place a scrollarea with child widgets directly on a form, so eventually you'll have to subclass and implement some of the details manually.

Djony
17th November 2006, 10:15
"Display object" is that big white background in which are those tables placed (look at the picture again). That's what I mean when I write "display object". If that object is QscrollArea, I can place one table in it. What to do with the lower table? And that white background should be resized when I place lower table in it. The scrollbar of that background "display object" should become longer. I hope I've explained it now :)

wysota
17th November 2006, 10:32
"Display object" is that big white background in which are those tables placed (look at the picture again). That's what I mean when I write "display object".
Oh, then that's perfectly legitimate QWidget :)


If that object is QscrollArea, I can place one table in it. What to do with the lower table? And that white background should be resized when I place lower table in it. The scrollbar of that background "display object" should become longer. I hope I've explained it now :)

You should read about layouts (doc.trolltech.com/4.2/layouts.html)...

Djony
27th November 2006, 12:01
Now that I have solved some things, back to this problem :) Are you suggesting me to place two qtablewidgets on one layout, which would be an item of QScroll Area? (Asking just to clarify... ) But, will Layout resize itself automatically when tables get bigger (number of rows for tables is unpredictable)?

wysota
27th November 2006, 18:54
Please read about layouts before asking such questions :)

Djony
29th November 2006, 16:15
Ok, I will stop with that for now (although I don't quite get it beside reading the link you gave me). Is it possible to fill cell table with colors like they are colored on picture (multiple colors, size of colored areas in proportion to percentage...)?

P.S.
I am wondering the same thing when we are talking about display of whole application. Is it possible to do it that way? To look and behave on described manner? Sorry for asking so much questions, but I am such a newbie :(

wysota
29th November 2006, 21:49
Ok, I will stop with that for now (although I don't quite get it beside reading the link you gave me). Is it possible to fill cell table with colors like they are colored on picture (multiple colors, size of colored areas in proportion to percentage...)?

Yes. Reimplement the delegate if you want to change the looks of items in Q*{View,Widget}


P.S.
I am wondering the same thing when we are talking about display of whole application. Is it possible to do it that way? To look and behave on described manner? Sorry for asking so much questions, but I am such a newbie :(

Yes. QPalette and/or subclassing and reimplementing paintEvents/styles/etc. are your friends.

Djony
30th November 2006, 13:05
Thank you for the answer.
If I understood you right, you mean to make class which inherits qtablewidgetitem and implement a method of that class which colors the cell in adequate manner? But, the question is, how can I control the size of areas in one cell (if you look at the picture, you will notice that there are 3 areas in one cell: green, red, blue parts). The height is the height of cells, but width? Thanx for any replies!

wysota
30th November 2006, 13:47
If I understood you right, you mean to make class which inherits qtablewidgetitem and implement a method of that class which colors the cell in adequate manner?
No, I meant to subclass QItemDelegate or QAbstractItemDelegate and reimplement painting and/or drawBackground routines.


But, the question is, how can I control the size of areas in one cell (if you look at the picture, you will notice that there are 3 areas in one cell: green, red, blue parts). The height is the height of cells, but width?

You have to reimplement the delegate's paint or drawDisplay() methods and draw the rectangles yourself.

Djony
30th November 2006, 14:42
How can I get positions and dimensions of these rectangles? They are inside table cells.

wysota
30th November 2006, 20:43
You get the width of the whole cell rectangle. You can then calculate lengths of each of the bars knowing the percentage to be displayed.

Djony
1st December 2006, 14:40
Thanx for reply, but I don't get it completely. I am looking at some examples in Qt Assistant and I can't catch when are those methods from QItemDelegate's class child called. Where is in my case, drawDisplay() method called?

wysota
1st December 2006, 14:44
The delegate is used by the view to render items. So every time an item needs to be drawn, the delegate is called to do that. drawDisplay is called by paint() which in turn is called by the view.

Djony
1st December 2006, 14:58
The delegate is used by the view to render items. So every time an item needs to be drawn, the delegate is called to do that. drawDisplay is called by paint() which in turn is called by the view.
In my case, is that going to happen when I insert row in my table or when I set new QTableWidgetItem for my new cell? Should paint() be called in code, or "automatically"?

wysota
1st December 2006, 22:42
The delegate is called automatically whenever the view feels like repainting an item.

Djony
4th December 2006, 08:58
Thanx for replies and sorry for stupid questions :) . What methods I need to reimplement in order to get my QItemDelegate to paint only 6th colum? Secondly, the painting depends on data (3 integer variables), as you can see on picture. How can I send those integers to QItemDelegate so the delegate can paint cell properly? Is there another way?

wysota
4th December 2006, 10:49
What methods I need to reimplement in order to get my QItemDelegate to paint only 6th colum?

paint() and/or drawDisplay(), depending on which class you subclass. It also depends how you install the delegate. You can install it for a single column only or for all columns (then you have to reimplement paint() to call the base class implementation for columns other then 6th.


Secondly, the painting depends on data (3 integer variables), as you can see on picture. How can I send those integers to QItemDelegate so the delegate can paint cell properly? Is there another way?

There are different ways to do this. I'd suggest using different item roles for each "colour" or setting a list of values as the data for the display role (setData(6, Qt::DisplayRole, QList<int>() << 1 << 2 << 3)) and then retrieve each value from within the delegate.

And I think it would be easier for you to subclass QItemDelegate and reimplement its paint() method than to go for drawDisplay().

Djony
4th December 2006, 14:22
paint() and/or drawDisplay(), depending on which class you subclass. It also depends how you install the delegate. You can install it for a single column only or for all columns (then you have to reimplement paint() to call the base class implementation for columns other then 6th.
How can I install delegate for just single column? I have decided to use QItemDelegate and to reimplement it's paint metod.


There are different ways to do this. I'd suggest using different item roles for each "colour" or setting a list of values as the data for the display role (setData(6, Qt::DisplayRole, QList<int>() << 1 << 2 << 3)) and then retrieve each value from within the delegate.
Maybe I've explained it wrong in previous post :) The data shown in that "colored column" will not be changed by the user. It should be shown and "colored" by the delegate based upon the values that some other class reads from SQLITE 3 database. If you mean't the same thing, which methods from QItemDelegate I need to reimplement and how (in which direction, I don't have any idea)? How can I "send" those integers to delegate so he can color cells?

wysota
4th December 2006, 22:37
How can I install delegate for just single column?
First thing to do is to browse QAbstractItemView docs and find the answer there.



If you mean't the same thing,
I did.


which methods from QItemDelegate I need to reimplement and how (in which direction, I don't have any idea)? How can I "send" those integers to delegate so he can color cells?

My previous answer still stands. Please read about item roles and Qt MVC implementation.

Djony
13th December 2006, 15:37
Thank you for replies. I've read documentation about item roles, models, views, delegates etc. If I understood you right, you are suggesting me to create model and reimplement it's setData() method and to store list of values in it (I am wondering at the moment which model class should I use, considering the fact that I am using QTableWidget. Should it be QStandardItemModel or I need to subclass QAbstractItemModel class?). After that, my delegate class will with data() get list of values and based on those values color the cell. That's cool.
But, when reimplementing paint() method I need to know cordinates (and dimensions) of whole cell, so I can paint properly. How can I retrieve cordinates (and dimensions) of whole cell in delegate class? (Maybe I've asked this before, but I don't get it...)
Again, thanx for replies :)

wysota
13th December 2006, 18:53
If you use QTableWidget, then you don't need to touch the model, as QTableWidget already implements one for you. Just use QTableWidgetItem::setData() to store data and implement a custom delegate to display it.

Djony
14th December 2006, 09:56
OK, but can you please tell me how can I retrieve width of table cell in my delegate class?

wysota
14th December 2006, 10:11
QStyleOptionViewItem::rect

Djony
15th December 2006, 12:54
Thanx
I have subclassed QTableWidgetItem and implemented setData() and data() methods. But, I have now problem with storing data (sending those 3 ints). Don't know how to store a list of ints a pass them as QVariant. This is my code:


listVariant2.clear();

listVariant2.append(QVariant(countOfFail));

//countOfFail is int, listVariant is QList <QVariant> type

listVariant2.append(QVariant(countOfPass)); //countOfPass is int
listVariant2.append(QVariant(countOfNA)); //countOfNA is int

tableItem->setData(Qt::DisplayRole,QVariant(listVariant2)); /*tableItem is type of class which inherits QTableWidgetItem class
*/

I have debugged and discovered that code crashes when calling last instruction (I got segmentation fault, SIGSEV). Probably because of that "QVariant thing"...
This is probably wrong way of thinking (I am talking about my code), but the best I could think of right now. Could you please give me instructions where to look to find better way to pass those 3 integers ? How to store them in a list as QVariant? Or some example/solution? Thanx for any reply

wysota
15th December 2006, 14:16
I have subclassed QTableWidgetItem and implemented setData() and data() methods.
What for? What was wrong with them?


But, I have now problem with storing data (sending those 3 ints). Don't know how to store a list of ints a pass them as QVariant.


QVariantList lst;
lst << 1 << 2 << 3;
tableItem->setData(QVariant(lst), Qt::DisplayRole);

Djony
15th December 2006, 14:30
What for? What was wrong with them?
Aren't they virtual?

wysota
15th December 2006, 14:37
If a function is virtual it doesn't mean you have to reimplement it but that you may do it if you need to.

Djony
15th December 2006, 15:58
Thank you, you are right. But, now, that I've solved this, paint method of my delegate's class is never called (code never enters in that function). I set delegate for whole table like this:

tableTestSuits->setItemDelegate(new TableDelegate (this));
//tableSuits is QTableWidget type and TableDelegate inherits QItemDelegate


What can be wrong?

jpn
15th December 2006, 16:05
The signature of the function must match exactly, including return type, argument types, constness and such:

void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const

Djony
15th December 2006, 16:58
Thank you, you are right (const at the end was missing). But now I have weird behaviour of application. All cells are empty (before implementing delegate there were strings shown in cells). Here is the body of paint method of my delegate's class:



QRect tempRect,rectangleCell=option.rect;

int widthCell=rectangleCell.width();

if (index.column()==4)
{
//painting only for 5th column


tempVariant=index.model()->data(index,Qt::DisplayRole);

//retrieving data from appropriate model

listOfVariants=tempVariant.toList();
numberOfFails=listOfVariants.at(0).toInt(); //listOfVariants is QList <QVariant>
numberOfPass=listOfVariants.at(1).toInt();
numberOfNa=listOfVariants.at(2).toInt();

//retrieving numbers to color in proper way

.....

//piece of code which fills rectangle with adequate color, manipulation with values
// that are stored in rectangleCell

}
}

Do you have any idea what is wrong? Thanx for reply

jpn
15th December 2006, 17:07
As if I understood, you are painting only some specific column(s). Other colums don't get painted at all. Maybe you want something like this:


if (index.column()==4)
{
// your custom painting for the 5th column
}
else
{
// let QItemDelegate paint when other columns in question
QItemDelegate::paint(painter, option, index);
}

Djony
16th December 2006, 13:28
You rock! Now I have problem with retrieving integers from QVariant that I've previosly stored via setData() (look above how wysota showed me to store integers in qvariantlist). I am getting very wierd values for integers. Here is my code where I try to retrieve integers:


tempVariant=index.model()->data(index,Qt::DisplayRole);
listOfVariants=tempVariant.toList();
numberOfFails=listOfVariants.at(0).toInt(); //numberOfFails is int
numberOfPass=listOfVariants.at(1).toInt(); //numberOfPass is int
numberOfNa=listOfVariants.at(2).toInt(); //numberOfNa is int
//those 3 integers I later use for painting my cell

I don't know what I am doing wrong. Is there better way to retrieve integers?

jpn
17th December 2006, 09:17
I can't spot anything particular in the code above that could be causing the problem. The bug must be elsewhere. I suggest you to double check the part of the code which sets the values.

Nevertheless you could check if the conversion from variant to int succeeds:


bool ok = false;
numberOfFails=listOfVariants.at(0).toInt(&ok);
if (!ok)
// failed


By the way,


tempVariant=index.model()->data(index,Qt::DisplayRole);
// could be simply written as
tempVariant=index.data(Qt::DisplayRole);
// or even as
tempVariant=index.data();

It actually ends up calling the same what you have written but is more readable, isn't it..? ;)

Djony
18th December 2006, 07:31
You are right, values are OK. Can you tell me, when I do inside my delegate:

QRect rectangleCell=option.rect;
Does rectangleCell then holds the dimensions of whole table or just current cell?

jpn
18th December 2006, 07:54
It contains the geometry of the index to be painted, so the current cell.

Djony
18th December 2006, 09:58
I got it, thanx. Is there a way to change the color of the text which will be drawn over the colored area. For example, I sometimes need white fonts, sometimes black.

Djony
19th December 2006, 22:48
Is there really no way to change the colors of text which paint() method of my delegate's class draws over the colored area? I am using drawText() method of painter.

wysota
19th December 2006, 23:27
Is there really no way to change the colors of text which paint() method of my delegate's class draws over the colored area? I am using drawText() method of painter.

Ah, sorry, didn't notice your question :)

You can control the colour using QPainter::setPen().