Render the whole content of QTableView to a pixmap
-
Hello, I have a QTableView implementation. The contents of this QTableView is bigger than the widget itself so both horizontal and vertical scrollbars are created when showing it on the screen.
What I want to do is to capture the "whole" content, not just the visible content. Including the horizontal and vertical headers of the table. The performance is not important since this operation will be rarely used. Think of taking a screenshot of the whole web site content on a browser even though not the whole web site is on view.
Using this code snippet:
QPixmap pixmap(myTableView->size()); myTableView->render(&pixmap);
Only captures what is seen on the screen and not the whole table contents.
Is this possible to do?
-
@canol said in Render the whole content of QTableView to a pixmap:
Is this possible to do?
No, not out-of-the-box. You have to implement it by yourself by e.g. making more pictures and stitching them together.
-
@Christian-Ehrlicher Thank you for your answer.
I came up with a solution where I calculate what the full height and width of the table should be, then setting the geometry of the table to that size temporarily and then rendering it to a pixmap and after I am done, I set the geometry back to what it was originally. It seems to work well so far. Here is the Python code:
def get_table_view_content_total_height(table_view): total_height = 0 # Add every row height v_header = table_view.verticalHeader() row_count = v_header.count() for i in range(row_count): if not v_header.isSectionHidden(i): total_height += v_header.sectionSize(i) # Add the horizontal header height h_header = table_view.horizontalHeader() if not h_header.isHidden(): total_height += h_header.height() return total_height def get_table_view_content_total_width(table_view): total_width = 0 # Add every column width v_header = table_view.horizontalHeader() column_count = v_header.count() for i in range(column_count): if not v_header.isSectionHidden(i): total_width += v_header.sectionSize(i) # Add the vertical header width v_header = table_view.verticalHeader() if not v_header.isHidden(): total_width += v_header.width() return total_width # Save some of the properties, which we will restore after we are done current_v_scroll_bar_value = table_view.verticalScrollBar().value() current_h_scroll_bar_value = table_view.horizontalScrollBar().value() current_geometry = table_view.geometry() # Calculate the height and width of the whole content of table view, including headers total_height = get_table_view_content_total_height(table_view) total_width = get_table_view_content_total_width(table_view) # Create a buffer which we will render into pixmap = QPixmap(total_width, total_height) # Make scrollbars disappear, set the geometry of the table view to full width and height and then render into pixmap table_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table_view.setGeometry(0, 0, total_width, total_height) table_view.render(pixmap) # Restore the properties table_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) table_view.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) table_view.setGeometry(current_geometry) table_view.horizontalScrollBar().setValue(current_h_scroll_bar_value) table_view.verticalScrollBar().setValue(current_v_scroll_bar_value)
I also made sure that I set the frame of the QTableView to NoFrame so that we don't need to take it into consideration in the calculations:
table_view.setFrameShape(QFrame.NoFrame)
From user's point of view, it doesn't appear changing sizes which is nice. And I tested it with a table >8000px height and it was pretty fast too.
-
@jeremy_k said in Render the whole content of QTableView to a pixmap:
Rather than saving and restoring the user's view of the table, have you tried creating a new view using the same model? It will probably require less code, and may even perform better.
I thought about it, it might work but then you need to make sure that both views look exactly the same. The width and height of the table content depends on column and row sizes, which can be changed by user. And these properties are part of the view not the model, so if you create an extra view, then you need to make sure its column and row sizes are exactly the same, also you need to make sure any property of the view that changes the size of the table (like border for example) is applied to the second view as well.