Page 1 of 2 12 LastLast
Results 1 to 20 of 21

Thread: Repainting QTableWidget

  1. #1
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Repainting QTableWidget

    Hi,

    I've got a QTableWidget with a custom item delegate and I'd like to repaint it when the user selects an item in a QComboBox.
    I tried both, QTableWidget::update() and, directly, QTableWidget::repaint(), but it didn't work. I think, the problem is that QTableWidget doesn't have focus but QComboBox does after selecting an item. If I replace QTableWidget::update() with QTableWidget::setFocus(), it works great and it does the repainting automatically.

    Hence, I could do it with QTableWidget::setFocus(), but I think it is not the usual way and I'd like to do it the smart way... Does anyone know how I can update the QTableWidget without setting the focus to it?

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Repainting QTableWidget

    Is that combobox a separate widget or do you use it as an editor in the delegate?

    Cheers,
    _

  3. #3
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Repainting QTableWidget

    It's a seperate widget...

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default 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,
    _

  5. #5
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Repainting QTableWidget

    Exactly that's it
    I mean, "updating the data" is what I'd like to do. I update the strings that were used in the reimplemented QItemDelegate:aint(..) 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):
    Qt Code:
    1. classWindow::classWindow(QWidget *parent) : QWidget(parent)
    2. {
    3. // ...
    4. QComboBox *combobox = new QComboBox;
    5. connect(this->combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotIndexChanged(int)));
    6. QTableWidget *table = new QTableWidget;
    7. myItemDelegate *delegate = new myItemDelegate(this);
    8. table->setItemDelegate(delegate);
    9. // ...
    10. }
    11.  
    12. void classWindow::slotIndexChanged(int index)
    13. {
    14. switch(index)
    15. {
    16. case 1:
    17. this->stringForDelegate = "lalala";
    18. case 2:
    19. this->stringForDelegate = "lololo";
    20. // ...
    21. }
    22. this->table->update(); // <--- doesn't work
    23. this->table->repaint(); // <--- doesn't work
    24. this->table->setFocus(); // <--- does work, but is not the "smart" way I guess
    25. return;
    26. }
    27.  
    28. void myItemDelegate::paint(QPainter *painter, QStyleOptionViewItem *option, QModelIndex *index)
    29. {
    30. painter->drawText(option.rect, this->stringForDelegate);
    31. return;
    32. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by Binary91; 14th September 2015 at 13:18.

  6. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default 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,
    _

  7. #7
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Repainting QTableWidget

    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...

  8. #8
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Repainting QTableWidget

    Quote Originally Posted by Binary91 View Post
    But how should I do that?
    I believe QTableWidget gets its data from QTableWidgetItems.

    Quote Originally Posted by Binary91 View Post
    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,
    _

  9. #9
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Repainting QTableWidget

    Sorry, I still didn't get it I think...
    I thought reimplementing QItemDelegate:aint(...) 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?

  10. #10
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Repainting QTableWidget

    Quote Originally Posted by Binary91 View Post
    I thought reimplementing QItemDelegate:aint(...) 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 View Post
    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 View Post
    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 View Post
    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 View Post
    Can you give an example how you would store the data?
    Qt Code:
    1. item->setText("foo");
    2. tableWidget->setItem(row, column, item);
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

  11. #11
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Repainting QTableWidget

    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.

    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...

    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?
    Last edited by Binary91; 15th September 2015 at 00:09.

  12. #12
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Repainting QTableWidget

    Quote Originally Posted by Binary91 View Post
    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 View Post
    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 View Post
    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 View Post
    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,
    _

  13. #13
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default 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?
    Last edited by Binary91; 15th September 2015 at 10:04.

  14. #14
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default 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:isplayRole) or pixmaps (e.g. Qt:ecorationRole) but also any complex type that can be put into a QVariant (using a custom role).
    Or a combination of these.

    Cheers,
    _

  15. #15
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default 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:
    Qt Code:
    1. class CalendarTableCell
    2. {
    3. private:
    4. QString stringDay;
    5. QStringList slEvents, slBirthdays;
    6. QPixmap *pmEvent, *pmImportantEvent, *pmBirthday;
    7. QColor colorBackground, colorDay, colorEvents;
    8.  
    9. public:
    10. CalendarTableCell();
    11. ~CalendarTableCell();
    12. QString getDay();
    13. QStringList getEvents();
    14. QStringList getBirthdays();
    15. QList<QPixmap*> getPixmaps();
    16. QColor getColorBackground();
    17. QColor getColorDay();
    18. QColor getColorEvents();
    19. };
    20. Q_DECLARE_METATYPE(CalendarTableCell)
    To copy to clipboard, switch view to plain text mode 
    Is that now automatically a new ItemDataRole? Can I do the following now:
    Qt Code:
    1. QTableWidgetItem::setData(Qt::CalendarTableCell, data)
    To copy to clipboard, switch view to plain text mode 
    ?? I don't think so.
    What do I have to do now?

  16. #16
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Repainting QTableWidget

    The role is just an int.
    Most people define their own roles using enums

    Qt Code:
    1. enum CalendarRoles {
    2. CellRole = Qt::UserRole + 1
    3. }
    To copy to clipboard, switch view to plain text mode 
    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,
    _

  17. #17
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default 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:
    Qt Code:
    1. void myItemDelegate::paint(QPainter *pPainter, const QStyleOptionViewItem &soviOption, const QModelIndex &miIndex) const
    2. {
    3. QStyledItemDelegate::paint(pPainter, soviOption, miIndex);
    4. myTableCellData cellData = this->myTable->item(miIndex.row(), miIndex.column())->data(Qt::UserRole).value<myTableCellData>();
    5.  
    6. QPen pPen(pPainter->pen());
    7. QRect rectStringDay = soviOption.rect, rectStringEvent = soviOption.rect;
    8. rectStringEvent.setX(rectStringEvent.x() + 10);
    9.  
    10. pPainter->fillRect(soviOption.rect, cellData.colorBackground);
    11.  
    12. pPen.setColor(cellData.colorStringDay);
    13. pPen.setWidth(10); // <--- doesn't work
    14. pPainter->setPen(pPen);
    15. pPainter->drawText(rectStringDay, cellData.stringDay);
    16.  
    17. pPen.setColor(cellData.colorStringEvents);
    18. pPen.setWidth(2); // <--- doesn't work
    19. pPainter->setPen(pPen);
    20. for(int i = 0; i < 3; i++)
    21. {
    22. if(i >= cellData.slEvents.count())
    23. break;
    24. rectStringEvent.setY(soviOption.rect.y() + 3 + (i + 1) * 12);
    25. pPainter->drawText(rectStringEvent, cellData.slEvents.at(i));
    26. }
    27. return;
    28. }
    To copy to clipboard, switch view to plain text mode 
    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?

  18. #18
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Repainting QTableWidget

    Quote Originally Posted by Binary91 View Post
    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,
    _

  19. #19
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Repainting QTableWidget

    What do you mean with "draw lines" ? I'd like to draw text. Text with different sizes and different thickness..

  20. #20
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default 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,
    _

Similar Threads

  1. how to bypass repainting a containing widget?
    By RolandHughes in forum Qt Programming
    Replies: 3
    Last Post: 31st January 2014, 10:42
  2. [qt5] repainting qwidget
    By zodiac in forum Qt Programming
    Replies: 11
    Last Post: 25th July 2012, 15:10
  3. Repainting a QGraphicsView
    By Luc4 in forum Qt Programming
    Replies: 8
    Last Post: 29th April 2010, 14:09
  4. QGraphicsItem not repainting
    By eijnuhs in forum Qt Programming
    Replies: 3
    Last Post: 20th September 2008, 08:54
  5. Repainting widget
    By fear in forum Qt Programming
    Replies: 3
    Last Post: 26th March 2008, 08:37

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.