Results 1 to 20 of 22

Thread: Calendar with QTableWidget and QItemDelegate

Hybrid View

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

    Default Calendar with QTableWidget and QItemDelegate

    Hi,

    I'm not familiar with QItemDelegate/QStyledItemDelegate and I don't have any clue, how to use it to realize my purposes.

    I'd like to display a calendar in a QTableWidget. Each QTableWidget cell represents a calendar day. If the user inserts some to-do points to a qlistwidget, these strings should be stored into the corresponding table cell, vertically aligned on the left of the cell.
    Also, the user can mark some to-do points as more or less important. Depending on the importance, some different pictograms should also be stored into the table cell, positioned on the top right of the cell.

    So all in all, I need to render my table cells with multiple strings in a block that should be aligned left centered in the cell and also some pictograms (e.g. .gif, .png, .jpg) in the top left corner of the cell.

    I think, I can realize that with a QItemDelegate/QStyledItemDelegate, but I don't have any clue how to do that.
    I was googleing for a long time now and I don't understand it. I know, I have to subclass Q(Styled)ItemDelegate and reimplement some basic functions like e.g. paint(...).

    What I don't know is:
    1. When and how are these functions called?
    2. Which functions do I need for my purposes?
    3. What do I have to do in these reimplemented functions?

    When I try to google for it, I only get examples how to store QSpinBoxes or stuff like that into a table cell, but I need to know how to store multiple data and how to align each data differently in the corresponding table cell...

    I would be really glad if someone could help me with that..

    Thank you in anticipation!
    Binary

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

    Default Re: Calendar with QTableWidget and QItemDelegate

    Is there really nobody who knows how to place multiple data into a QTableWidget cell like the following draft ("-" means empty space):

    #######################
    #---------------------pictogram#
    # string_1---------------------#
    # string_2---------------------#
    #------------------------------#
    #######################

    I mean, layouts like the one above are often used in calendars, so there has to be a way to do it... If there is a better way than using QItemDelegate, feel free to tell me

  3. #3
    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: Calendar with QTableWidget and QItemDelegate

    Quote Originally Posted by Binary91 View Post
    Is there really nobody who knows how to place multiple data into a QTableWidget cell like the following draft ("-" means empty space):
    Oh, I am sure there are plenty of people who know that.
    In fact I remember several threads with similar discussions.

    How did you arrive at the assumption that nobody knows how to do that?

    Cheers,
    _

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

    Default Re: Calendar with QTableWidget and QItemDelegate

    Hi anda_skoa,

    well, I just thought it because I didn't get any answers. I don't like a full compilable solution, a little hint would be enough. Nevertheless, I got a hint from somewhere else. The functionallity I was looking for can be found in the QPainter class itsself. That's why I couldn't find anything in the QItemDelegate documentation. My problem was/is, that I don't understand the handling of the QItemDelegate functions like paint(). I know now, that the paint() function is called everytime, a QTableWidget item has to be painted, right? So if I have a table with 50 cells and I create it the first time, the QItemDelegate:aint(...) function is called 50 times, right? And each time, it uses the QPainter settings (default if not modified in reimplementation) to draw the cell, right?

    So I tried to reimplement the paint() function, modified the passed QPainter instance and used the drawText() method to place an example string. I used a QRect(10, 10, 100, 20) to place the string. But the result was not what I expected. The QString is absolute positioned on the table and does not check for cell borders! What happened there? I thought, each QPainter is bound to its item or its index, so why can I position the QString everywhere on the table?

  5. #5
    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: Calendar with QTableWidget and QItemDelegate

    Quote Originally Posted by Binary91 View Post
    well, I just thought it because I didn't get any answers.
    There were just a couple of hours between your postings.

    Quote Originally Posted by Binary91 View Post
    The functionallity I was looking for can be found in the QPainter class itsself. That's why I couldn't find anything in the QItemDelegate documentation.
    The painter is the first argument of the function and it is called "painter", in a function called "paint", so the documentation writers probably thought that it was obvious enough that the painter would be used for painting

    Quote Originally Posted by Binary91 View Post
    I know now, that the paint() function is called everytime, a QTableWidget item has to be painted, right?
    Yes, otherwise it would be pretty useless

    Quote Originally Posted by Binary91 View Post
    So if I have a table with 50 cells and I create it the first time, the QItemDelegate:aint(...) function is called 50 times, right?
    If all the 50 cells have content, yes.

    Quote Originally Posted by Binary91 View Post
    And each time, it uses the QPainter settings (default if not modified in reimplementation) to draw the cell, right?
    The base implementation does, yes.

    Quote Originally Posted by Binary91 View Post
    So I tried to reimplement the paint() function, modified the passed QPainter instance and used the drawText() method to place an example string. I used a QRect(10, 10, 100, 20) to place the string. But the result was not what I expected. The QString is absolute positioned on the table and does not check for cell borders! What happened there? I thought, each QPainter is bound to its item or its index, so why can I position the QString everywhere on the table?
    You get the rectangle of the cell via the "option" argument.

    Cheers,
    _

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

    Default Re: Calendar with QTableWidget and QItemDelegate

    The painter is the first argument of the function and it is called "painter", in a function called "paint", so the documentation writers probably thought that it was obvious enough that the painter would be used for painting
    Good one...
    You get the rectangle of the cell via the "option" argument.
    Ok, but basically the painter doesn't look for cell borders. That is interesting. What if I'd like to place clickable links into the cell. If the link can be placed everywhere on the table, how can I know to which cell they belong to?
    Or if the user resizes the window to a smaller size --> how can I handle it that the string still cares for cell borders? I mean, the string could flow over the border into the next cell...

    There were just a couple of hours between your postings.
    Yeah yeah, patience is not my strength
    Last edited by Binary91; 9th September 2015 at 17:36.

  7. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Calendar with QTableWidget and QItemDelegate

    One would think that QTableWidget::itemAt() would be just the thing you need to map between a mouse click position and the QTableWidgetItem at that location. Or a slot to handle the QTableWidget::itemClicked() signal.

    (9 minutes' turnaround. Is that fast enough for you?)

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

    Default Re: Calendar with QTableWidget and QItemDelegate

    Well, when I like to get the cell clicked when a user clicks the text, then I get the cell that is hovered by the mouse, but it is maybe not the cell that holds the text, because QPainter::drawText(..) handles absolute positioning. That is what I don't understand. What's the matter with that? Is there any sence or any reason why the cells text should appear over another cell?

    The other problem, as I already mentioned, is that I get problems when the user changes the windows size. As a result, even the exactly positioned strings won't be positioned exactly anymore, because they are displayed as ghost strings over the table... Isn't there any way to "store" them exactly into the cells?

    (9 minutes' turnaround. Is that fast enough for you?)
    You're on the right way..

  9. #9
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Calendar with QTableWidget and QItemDelegate

    Is there any sence or any reason why the cells text should appear over another cell?
    You have the wrong coordinates, probably. I don;t know if the coordinates you are receiving are relative to the QTableWidget, to the QMainWindow, or to the screen. When you click somewhere, do the coordinates make sense? If you click in the top left cell, do you get coordinates that are reasonable for being in that cell? If not, you might have to do some mapping between screen, table, or main window coordinates.

    And since you are painting the content of the cell yourself, then you'll have to figure out whether the position within the cell corresponds to where you have painting the link text.

    The other problem, as I already mentioned, is that I get problems when the user changes the windows size. As a result, even the exactly positioned strings won't be positioned exactly anymore, because they are displayed as ghost strings over the table... Isn't there any way to "store" them exactly into the cells?
    So you aren't using a delegate for this? You're just painting from an override of QTableWidget:aintEvent()?

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

    Default Re: Calendar with QTableWidget and QItemDelegate

    You have the wrong coordinates, probably. I don;t know if the coordinates you are receiving are relative to the QTableWidget, to the QMainWindow, or to the screen. When you click somewhere, do the coordinates make sense? If you click in the top left cell, do you get coordinates that are reasonable for being in that cell? If not, you might have to do some mapping between screen, table, or main window coordinates.
    When I use x = 0 and y = 0, the QString is positioned on the top left corner of the top left cell of the table. The problem is, the QString corresponds to another cell. That's what I don't understand. Why isn't it positioned on the top left of the corresponding cell?

    Let's take an example: I have 5 columns and 5 rows. Column 2 has a custom QItemDelegate that should display a QString on the top left corner of each cell in Column 2.
    So I subclass QItemDelgate (or QStyledItemDelegate), reimplement the paint(..) function and use QPainter::drawText(QRect(0,0,50,20), "TestString"). So a string "TestString" should be positioned on each top left corner of the cells in column 2. BUT instead, all 5 TestStrings are positioned on the top left corner of the top left cell (index 0,0).
    I don't see any sense in this behaviour. Why can data that is painted in the paint() function that is called for each table cell leave the cell frontiers?

    So you aren't using a delegate for this? You're just painting from an override of QTableWidget:aintEvent()?
    No, I do subclass, that is my code:
    Table.h
    Qt Code:
    1. class test : public QWidget
    2. {
    3. Q_OBJECT
    4.  
    5. private:
    6. QVBoxLayout *layoutMain;
    7. QTableWidget *tableTest;
    8.  
    9. public:
    10. test(QWidget *parent = 0);
    11. ~test();
    12.  
    13. private:
    14. void buildWindow();
    15. };
    16.  
    17. class testDelegate : public QStyledItemDelegate
    18. {
    19. public:
    20. testDelegate(QWidget *widgetParent = 0);
    21. ~testDelegate();
    22.  
    23. virtual void paint(QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const;
    24. };
    To copy to clipboard, switch view to plain text mode 
    Table.cpp
    Qt Code:
    1. void test::buildWindow()
    2. {
    3. this->layoutMain = new QVBoxLayout;
    4. this->tableTest = new QTableWidget;
    5. this->tableTest->setRowCount(5);
    6. this->tableTest->setColumnCount(5);
    7. QHeaderView *headerV = this->tableTest->verticalHeader();
    8. QHeaderView *headerH = this->tableTest->horizontalHeader();
    9. headerV->setSectionResizeMode(QHeaderView::Stretch);
    10. headerH->setSectionResizeMode(QHeaderView::Stretch);
    11.  
    12. testDelegate *delegateTest = new testDelegate(this);
    13. this->tableTest->setItemDelegateForColumn(2, delegateTest);
    14. this->layoutMain->addWidget(this->tableTest);
    15.  
    16. this->setLayout(this->layoutMain);
    17. this->setWindowTitle("TestTable");
    18. this->setMinimumSize(500,300);
    19. return;
    20. }
    21.  
    22. void testDelegate::paint(QPainter *pPainter, const QStyleOptionViewItem &soviOption, const QModelIndex &miIndex) const
    23. {
    24. pPainter->drawText(QRect(0,0,50,20), "TestString");
    25. QStyledItemDelegate::paint(pPainter, soviOption, miIndex);
    26. return;
    27. }
    To copy to clipboard, switch view to plain text mode 
    Unfortunatelly, all TestString strings are positioned on the top left of the table instead of the top left corners of each cell in column 2... This behaviour is strange and makes window resize handling much more complicated, because the QItemDelegate doesn't store the data into the cells but lays the data over the cells without careing about the cell borders... While changing the window size, the table cells adjust but the data doesn't .... this shouldn't go this way, should it??

    EDIT:
    The most interesting and confusing fact is, that when I do it like anda_skoa mentioned and use the QRect() that is given when calling the option.rect member for positioning, then everything works as I expected! The strings are applied correctly on each top left corner of the cells in column 2 AND they correctly move while resizing the window! But where is the difference to my manually created QRect() ?? I mean, I could also check in a if-else condition which cell of column 2 has index and create a corresponding QRect() to position the strings. But they will not move correctly while resizing the window, they are not stored into the cell but only hover it... Can you tell me why?
    Last edited by Binary91; 9th September 2015 at 22:03.

  11. #11
    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: Calendar with QTableWidget and QItemDelegate

    Quote Originally Posted by Binary91 View Post
    What's the matter with that? Is there any sence or any reason why the cells text should appear over another cell?
    Likely not, but there are different ways to handle this.
    Imposing one would likely be inflexible for very little gain.

    The implementation of paint() could take the coordinates from the rect and paint with that, or it could translate the painter and paint with relative coordinates.
    It could restrict its painting or make the painter clip.

    So always translating and clipping would be very inefficient if the paint code takes care of that itself, e.g. painting a pixmap, or just filling the rectangle.

    if you want the painter to be translated, just tell it to. Same for clipping.

    Cheers,
    _

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

    Default Re: Calendar with QTableWidget and QItemDelegate

    Well, I still don't understand it. I mean, assuming that option.rect returns a QRect(100,0,50,20) for cell1 in column2 and a QRect(100,50,20,20) for cell2 in column2. Where is the difference when I create the QRect manually with the same coordinates and pass it to the drawText function?? I mean, the compiler should replace both QRects with the same data, doesn't it?? So why does the first example show correct behaviour with correct positioning of each string on the top left of each cell and respecting cell borders, while the second example results in absolute positioning at the top left of the whole table and "hovering" the strings over all cells??

    EDIT:
    I catched the option.rect coordinates for all 5 cells of column 2 and printed them via qDebug() to get the x, y, w, h of the rect.
    X is always 185
    Y is a multiple of 51
    w is always 91
    h is always 50

    So the following to methods do exactly the same (correct) positioning (I tested it):
    Qt Code:
    1. painter->drawText(option.rect, "TestString");
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. painter->drawText(QRect(185,index.row()*51,91,50), "TestString");
    To copy to clipboard, switch view to plain text mode 
    BUT the difference is, that the first example stores the strings INTO the cells (changing window size also lets the strings move with its corresponding cells). The second example doesn't. In the second example, the strings are layed over the table, they don't belong to a cell and fly over their borders when resizing the window... They are like ghosts!

    Can you explain this behaviour?

    EDIT 2:
    Ok, everything is clear now. I forgot the fact that paint(..) is also called while resizing and I would always override the new rect in option.rect with my own calculations...

    Thread is solved
    Last edited by Binary91; 9th September 2015 at 23:06.

  13. #13
    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: Calendar with QTableWidget and QItemDelegate

    Quote Originally Posted by Binary91 View Post
    I mean, the compiler should replace both QRects with the same data, doesn't it??
    Yes, the compiler will use the same code for all instances of QRect, only their data differs.
    If two instances of QRect have the same data, then the same operations will have the same result.

    Cheers,
    _

Similar Threads

  1. Syncing Android Calendar with our own calendar?
    By Awareness in forum Qt for Embedded and Mobile
    Replies: 0
    Last Post: 16th February 2014, 19:17
  2. Replies: 4
    Last Post: 9th October 2013, 15:27
  3. calendar
    By santhosh in forum Newbie
    Replies: 10
    Last Post: 17th March 2011, 10:02
  4. QTablewidget and QItemDelegate?
    By whitefurrows in forum Qt Programming
    Replies: 3
    Last Post: 28th April 2010, 15:33
  5. QItemDelegate use in QTableWidget
    By arpspatel in forum Qt Programming
    Replies: 2
    Last Post: 27th October 2009, 22:18

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.