Re: Repainting QTableWidget
Is that combobox a separate widget or do you use it as an editor in the delegate?
Cheers,
_
Re: Repainting QTableWidget
It's a seperate widget...
Re: Repainting QTableWidget
So you have a slot connected to one of the combobox's signals?
And in that slot you update data in the tableview but it does not show that new data?
Cheers,
_
Re: Repainting QTableWidget
Exactly that's it :D
I mean, "updating the data" is what I'd like to do. I update the strings that were used in the reimplemented QItemDelegate::paint(..) function, but then I need a full update, hence, the repaint must follow
Added after 10 minutes:
That is my code (can have some errors, don't care):
Code:
{
// ...
connect(this->combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotIndexChanged(int)));
myItemDelegate *delegate = new myItemDelegate(this);
table->setItemDelegate(delegate);
// ...
}
void classWindow::slotIndexChanged(int index)
{
switch(index)
{
case 1:
this->stringForDelegate = "lalala";
case 2:
this->stringForDelegate = "lololo";
// ...
}
this->table->update(); // <--- doesn't work
this->table->repaint(); // <--- doesn't work
this->table->setFocus(); // <--- does work, but is not the "smart" way I guess
return;
}
{
painter->drawText(option.rect, this->stringForDelegate);
return;
}
Re: Repainting QTableWidget
Forget the delegate, it is not involved other than in painting.
Consider the delegate an implementation detail of the QTableWidget.
In slotIndexChanged() update the data in the QTableWidget.
It will automatically update all cells involved in the data change.
Cheers,
_
Re: Repainting QTableWidget
Quote:
In slotIndexChanged() update the data in the QTableWidget.
But how should I do that? I don't store the data into the table because (as you may remember from the last thread) QPainter is the only way to position the complex orientated strings into the table cells...
Re: Repainting QTableWidget
Quote:
Originally Posted by
Binary91
But how should I do that?
I believe QTableWidget gets its data from QTableWidgetItems.
Quote:
Originally Posted by
Binary91
I don't store the data into the table because (as you may remember from the last thread) QPainter is the only way to position the complex orientated strings into the table cells...
The delegate always uses QPainter for drawing cells.
A custom delegate can overwrite the paint() method and draw the cell data in any way it likes.
The table widget is still the place the data comes from.
It holds a model that provides the data interface for its base class, QTableView, which then uses the set delegate to display the data.
The application's interface to the data is through QTableWidgetItems.
Cheers,
_
Re: Repainting QTableWidget
Sorry, I still didn't get it I think...
I thought reimplementing QItemDelegate::paint(...) and using painter->drawText(...) is the only way to position complex data into cells, isn't it??
If yes, then what do you mean with using QTableWidgetItems for storing/getting the data? I know only one function to store data with items, that is "setText(..)". But I don't believe I can realize complex positioning with this function...
Can you give an example how you would store the data?
Re: Repainting QTableWidget
Quote:
Originally Posted by
Binary91
I thought reimplementing QItemDelegate::paint(...) and using painter->drawText(...) is the only way to position complex data into cells, isn't it??
Yes. We covered that in the other thread, I thought that this problem was solved?
Quote:
Originally Posted by
Binary91
If yes, then what do you mean with using QTableWidgetItems for storing/getting the data?
Well, the table has to get data somehow.
An empty table will paint nothing but empty cells, no matter which delegate you use.
Like when you print an empty page, you will get an empty page no matter if you are using an ink printer or a laser printer.
Quote:
Originally Posted by
Binary91
I know only one function to store data with items, that is "setText(..)".
Yes, that is the most convenient way if the cell has a single text value.
Quote:
Originally Posted by
Binary91
But I don't believe I can realize complex positioning with this function...
Why would you need that?
Your delegate handles the positioning.
Quote:
Originally Posted by
Binary91
Can you give an example how you would store the data?
Code:
item->setText("foo");
tableWidget->setItem(row, column, item);
Cheers,
_
Re: Repainting QTableWidget
Quote:
Yes. We covered that in the other thread, I thought that this problem was solved?
Yes, it was solved till now. I can paint text in complex position now, but I can do this only in the QITEMDELEGATE::PAINT function, because I need the painter and the rect of the corresponding cells.
Quote:
Well, the table has to get data somehow.
An empty table will paint nothing but empty cells, no matter which delegate you use.
I don't think so, or I don't know it better, but I never store any data into the table. Why should I do? I only know one way for it with setText(QString), but that is not possible for me because it only allows storing of ONE text string. If you could tell me how to store the data I'd like to position (lots of text strings in different positions of each cell, pixmaps and icons) with a QTableWidgetItem, then everything would be fine...
Quote:
Why would you need that?
Your delegate handles the positioning.
But how?? From where does it get the data to handle with?? In my items, I can hold one text string, not more...
Please, I still don't know how to store complex data into a table like you suggested. I mean, I would need a function to store many strings and give them different identifiers, so the delegate can differ between them and so on... How is this realizable?
The way I realize it is creating a class "TableCell" that holds the texts and its rects. After changing the QComboBox index, the list of TableCell instances will be updated. Then, finally, the QTableWidget must be updated (that was the problem of the very beginning of this thread). While updating, delegate gets TableCell members and paints it on the table.
As you can see, I never "STORE" any data into the table, instead, I only let the data paint over the table...
So if there is any better solution, please show me. Tell me how you would "store" such complex TableCell instances into the table and how would you then tell the delegate to handle them?
Re: Repainting QTableWidget
Quote:
Originally Posted by
Binary91
I can paint text in complex position now, but I can do this only in the QITEMDELEGATE::PAINT function, because I need the painter and the rect of the corresponding cells.
Yes, that is what delegates are there for.
Quote:
Originally Posted by
Binary91
I don't think so, or I don't know it better, but I never store any data into the table. Why should I do? I only know one way for it with setText(QString), but that is not possible for me because it only allows storing of ONE text string. If you could tell me how to store the data I'd like to position (lots of text strings in different positions of each cell, pixmaps and icons) with a QTableWidgetItem, then everything would be fine...
setData()
Methods like setText(), setBackground(), etc are just convenience wrappers around it.
You can even define your own roles and store complex objects in it as long as their types have been made known to the Qt type system with Q_DECLARE_METATYPE (see the QVariant documentation)
Quote:
Originally Posted by
Binary91
But how?? From where does it get the data to handle with?? In my items, I can hold one text string, not more...
Please, I still don't know how to store complex data into a table like you suggested. I mean, I would need a function to store many strings and give them different identifiers, so the delegate can differ between them and so on... How is this realizable?
Quote:
Originally Posted by
Binary91
The way I realize it is creating a class "TableCell" that holds the texts and its rects. After changing the QComboBox index, the list of TableCell instances will be updated. Then, finally, the QTableWidget must be updated (that was the problem of the very beginning of this thread). While updating, delegate gets TableCell members and paints it on the table.
Yes, that is also an option. In which case it doesn't make sense anymore to use the QTableWidget convenience wrapper, but using a QTableView with a custom model that operates on the cell data.
Cheers,
_
Re: Repainting QTableWidget
Ok, If I'm right, I have two possible ways to realize my purposes:
1. I do it like I do it till now, without storing any data into the table but only drawing the data directly with paint(..) function.
2. I do it like you mentioned it with QTableWidgetItem::setData(role, data).
It works for me with option 1, so I need to know if your second option with "real storing" has any benefits? If no, I will not do much unneccessary work.
If yes, then I would have to define my own data role, right? My data consists of strings and pixmaps, so it is a mix of two existing data roles, what is not supported, right? Or is it possible to use setData() two times, one for alle the strings and one for all the pixmaps? Is that possible?
So what would you do? Any benefits with the second method? Is it profitable to change the way I do and create an own data role, create QTableWidgetItems, pass them my data and let it paint?
Re: Repainting QTableWidget
You have two options
1) using QTableWidget and store the data using QTableWidgetItem
2) using QTableView and a QAbstractTableModel subclass to access data if you already have it in some tabular data structure.
When using (1), you make use of the QTableWidget's internal model.
In either case updates to the data let the model notify all views (that are currently using this model) that something has changed.
The views then update the respective cells.
The views do some of the drawing themselves, e.g. the cell grid, while they delegate the cell content drawing to delegates.
The delegates can retrieve any data from the model that the model has available, usually the data for the cell they are currently painting.
That data can be simple things like strings (e.g. Qt::DisplayRole) or pixmaps (e.g. Qt::DecorationRole) but also any complex type that can be put into a QVariant (using a custom role).
Or a combination of these.
Cheers,
_
Re: Repainting QTableWidget
Ok, I see. Storing the data has the benefit that changing the data immediately results in updating the table. That is whalt I need and it makes handling easier for me.
Then, how would I declare the data role? The link you gave me (Q_DECLARE_METATYPE) only explains how to specify new data types, but not how to define new ItemDataRoles that I need to pass to the QTableWidgetItem::setData(role, data) function...
That is what I do so far:
Code:
class CalendarTableCell
{
private:
QPixmap *pmEvent,
*pmImportantEvent,
*pmBirthday;
QColor colorBackground, colorDay, colorEvents;
public:
CalendarTableCell();
~CalendarTableCell();
QList<QPixmap*> getPixmaps();
};
Q_DECLARE_METATYPE(CalendarTableCell)
Is that now automatically a new ItemDataRole? Can I do the following now:
?? I don't think so.
What do I have to do now?
Re: Repainting QTableWidget
The role is just an int.
Most people define their own roles using enums
Code:
enum CalendarRoles {
CellRole = Qt::UserRole + 1
}
If you only use one custom role, you can also just use Qt::UserRole with setData()
Btw, don't make those pixmap pointers, that just means you need to define a copy constructor and assignment operator for your data type so each copy gets new pointers and can delete the pointers safely.
Cheers,
_
Re: Repainting QTableWidget
Ah, so that's what I was looking for, Qt::UserRole does the job for me.
Well, I solved it now with QTableWidget + subclass of QTableWidgetItem. In this subclass, I added a member that holds all data that has to be stored into the cell and also I reimplemented the setData method, so by calling setData() now, the member will be updated and set. And see, the table is immediatelly updated and repainted. Really great!
Now I recognized one more (little) problem. In my reimplemented paint function, I do text drawing with different text colors and different thickness. For this purpose, I create different QPens, like this:
Code:
{
QStyledItemDelegate::paint(pPainter, soviOption, miIndex);
myTableCellData cellData = this->myTable->item(miIndex.row(), miIndex.column())->data(Qt::UserRole).value<myTableCellData>();
QPen pPen
(pPainter
->pen
());
QRect rectStringDay
= soviOption.
rect, rectStringEvent
= soviOption.
rect;
rectStringEvent.setX(rectStringEvent.x() + 10);
pPainter->fillRect(soviOption.rect, cellData.colorBackground);
pPen.setColor(cellData.colorStringDay);
pPen.setWidth(10); // <--- doesn't work
pPainter->setPen(pPen);
pPainter->drawText(rectStringDay, cellData.stringDay);
pPen.setColor(cellData.colorStringEvents);
pPen.setWidth(2); // <--- doesn't work
pPainter->setPen(pPen);
for(int i = 0; i < 3; i++)
{
if(i >= cellData.slEvents.count())
break;
rectStringEvent.setY(soviOption.rect.y() + 3 + (i + 1) * 12);
pPainter->drawText(rectStringEvent, cellData.slEvents.at(i));
}
return;
}
Setting the different text colors always works, but changing the pen's thickness with QPen::setWidth(int) doesn't change anything. Do you know why? I also tried to manually set the cosmetic mode to false, but it still doesn't work.
Any suggestions?
Re: Repainting QTableWidget
Quote:
Originally Posted by
Binary91
Setting the different text colors always works, but changing the pen's thickness with QPen::setWidth(int) doesn't change anything. Do you know why? I also tried to manually set the cosmetic mode to false, but it still doesn't work.
I don't see any drawing operations that would draw lines, did you forget these in your posting?
Cheers,
_
Re: Repainting QTableWidget
What do you mean with "draw lines" ? I'd like to draw text. Text with different sizes and different thickness..
Re: Repainting QTableWidget
Ah, but text is not drawn of lines, it is rendered by a font engine.
You can increase the font size or draw the font scaled.
I.e. text doesn't have an outline, only filled area and that area is filled with the pen's brush.
Cheers,
_