将一个 QWidget 保存为图像。

huangapple go评论62阅读模式
英文:

save a QWidget as an image

问题

在pyqt5中,我尝试:

fileName = "qtable_widget.png"
pixmap = QtGui.QPixmap(self.parent_self.main_self.ui_scheduled_transmitions_create_window.review_table.size())
self.parent_self.main_self.ui_scheduled_transmitions_create_window.review_table.render(pixmap)
pixmap.save("qtable_widget.png", "PNG", -1)

但这仅捕获了QTableWidget的视图区域。QTableWidget有一个垂直滚动条。有没有办法捕获整个QTableWidget?

英文:

In pyqt5 i try:

fileName = "qtable_widget.png"
pixmap = QtGui.QPixmap(self.parent_self.main_self.ui_scheduled_transmitions_create_window.review_table.size())
self.parent_self.main_self.ui_scheduled_transmitions_create_window.review_table.render(pixmap)
pixmap.save("qtable_widget.png", "PNG", -1)

But this captures only the view area of the QTableWidget. The QTableWidget has a vertical scrollbar.
Is there any way to capture all the qtablewidget?

答案1

得分: 0

滚动区域是这样实现的,只有可见的内容才会被绘制,而且只有当它们在视口内可见时才会被绘制。

这意味着你不能简单地调用绘制函数(这就是render()做的事情),因为你总是会得到小部件的可见矩形。

解决方案是临时调整表格的大小以显示所有内容。

我的建议是使用一个临时表格视图,并在原始表格上设置相同的模型。

关键是获取正确的内容区域,它包括从视口位置开始的矩形,并且大小基于viewportSizeHint()。为了使其正常工作,视图应该禁用滚动条,以便你可以获得正确的大小提示,然后调整矩形的左上角到视图原点(0, 0),并使用frameWidth()添加右边和底边边距。

这是上述内容的一个简单示例:

# 只是一个示例表格
original = QTableWidget(100, 100)
for r in range(100):
    for c in range(100):
        original.setItem(r, c, QTableWidgetItem('{} {}'.format(r, c)))

temp = QTableView()
temp.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
temp.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
temp.setModel(original.model())

rect = QRect(temp.viewport().pos(), temp.viewportSizeHint())
rect.setTopLeft(QPoint())
margins = temp.contentsMargins()
temp.resize(rect.size() + QSize(margins.right(), margins.bottom()))

image = temp.grab()
image.save('qtable_widget.png')
temp.deleteLater()
英文:

A scroll area is implemented in a way that only the visible contents are actually painted, and only when they are exposed within the viewport.

This means that you cannot simply call painting functions (which is what render() does) as you will always get the visible rectangle of the widget.

The solution is then to temporarily resize the table in order to expose all the contents.

My suggestion is to use a temporary table view, and set the same model on the original one.

The trick is to get the proper content area, which includes a rectangle starting from the viewport position and has a size based on the viewportSizeHint(). In order for this to work properly, the view should have both scroll bars disabled, so that you can get the proper size hint, then adjust the rectangle top left to the view origin point (0, 0), and add the right and bottom margins using the frameWidth().

This is a simple example of the above:

# just an example table
original = QTableWidget(100, 100)
for r in range(100):
    for c in range(100):
        original.setItem(r, c, QTableWidgetItem('{} {}'.format(r, c)))


temp = QTableView()
temp.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
temp.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
temp.setModel(original.model())

rect = QRect(temp.viewport().pos(), temp.viewportSizeHint())
rect.setTopLeft(QPoint())
margins = temp.contentsMargins()
temp.resize(rect.size() + QSize(margins.right(), margins.bottom()))

image = temp.grab()
image.save('qtable_widget.png')
temp.deleteLater()

huangapple
  • 本文由 发表于 2023年6月18日 18:11:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76500007.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定