在qtooltip上显示一个numpy阵列,而无需保存

发布于 2025-02-07 21:36:25 字数 1829 浏览 0 评论 0 原文

帖子如何显示悬停图像时如何显示工具图像按钮pyqt5 表明可以在 qtooltip 上显示保存的图像。是否可以在不保存的情况下以 numpy nd数组表示的图像上获得同等结果?

更确切地说,如果 panda.jpg c 驱动器下保存的映像,则从上面的参考链接运行以下代码运行:

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        pybutton = QPushButton('Display Image via Tool Tip', self)
        pybutton.setToolTip(r'<img src="C:\panda.jpg">')

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )

代码给出:

现在要考虑:

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import numpy as np

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        pybutton = QPushButton('Display Image via Tool Tip', self)
        imarray = np.random.rand(1000,1000,3) * 255
        #pybutton.setToolTip(imarray) #This line is not working

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )

有没有办法在没有任何保存的情况下获得同等结果?转换为 qimage 似乎无济于事。

这个问题的动机是因为:

  1. 我有很多通过许多工具提示显示的数组,并且在工具提示上显示它们后将根本不使用它们。

  2. 我有一个工具提示,我想显示一个视频,一旦我知道如何使用数组显示一个图像而无需保存,我就可以做到这一点/代码>和数组的更新。

The answer in the post How to show tooltip image when hover on button pyqt5 shows that one can display a saved image on QToolTip. Is there way to achieve an equivalent result on an image represented by an numpy nd array without saving?

More precisely, if panda.jpg is a saved image right under C drive, then the following code modifed from the above reference link runs:

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        pybutton = QPushButton('Display Image via Tool Tip', self)
        pybutton.setToolTip(r'<img src="C:\panda.jpg">')

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )

The code gives:

enter image description here

Consider now instead:

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import numpy as np

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        pybutton = QPushButton('Display Image via Tool Tip', self)
        imarray = np.random.rand(1000,1000,3) * 255
        #pybutton.setToolTip(imarray) #This line is not working

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )

Is there a way to attain an equivalent result without any saving? Converting to QImage does not seem to help.

This question is motivated because:

  1. I have lots of array to display via a lot of tooltips and none of them will be used at all after they are displayed on the tooltip.

  2. I have one tooltip where I want to display a video, which I will be able to do as soon as I know how to display one image using arrays without any saving because all I will need then is the QTime and update of the array.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

下雨或天晴 2025-02-14 21:36:25

QT对HTML的支持为限制为较小的子集 html4,该支持非常合规且一致,包括 base64 编码嵌入式图像数据。

然后,该解决方案将图像数据作为存储器缓冲区中的图像文件作为图像数据,将其内容转换为基本64编码,并将其用于 img 标签。

请注意:base64是一个六位编码,任何未编码的数据都不能用该数据大小来划分字节的 padding 。显然,这意味着存储数据的内存足迹始终相等(很少)或比原始数据更大(很可能)。

在下面的示例中,我将随机图像显示为QPIXMAP设置的QLABEL,并且可以通过悬停它来看到该图像的工具提示。

我还添加了一个基本的文本查看器,以显示“原始数据”的实际内容,以实现每个可能的图像工具提示的大小(和内存要求)。请注意,QT显然将使用内存 base64数据缓存图像。

如果您对工具提示图像的高质量不感兴趣,则显然可以使用“ JPG”格式:质量结果会有所不同,但是您肯定会得到较小的内存要求。

请记住,以上非常重要:QToolTip的内容在运行时进行动态评估,并且由于每次A 不同的工具提示内容都将显示,因此下一个工具提示的整个内容都会可以评估,这将添加一个相当大的开销:QT将检查工具提示文本是否包含丰富的文本,然后创建一个新的qtextDocument,解析HTML并将其转换为自己的布局,计算所有必需的尺寸,并最终更新新的尺寸QTooltip带有更新并布置内容。使用 Extreme 的意识,尤其是对于高分辨率图像,在设置工具提示内容之前,您应该真正考虑调整大小。

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        imarray = np.random.rand(256, 256, 3) * 255
        image = QImage(imarray, imarray.shape[1], imarray.shape[0], 
            QImage.Format_RGB888)

        central = QWidget()
        layout = QVBoxLayout(central)
        self.setCentralWidget(central)

        label = QLabel()
        layout.addWidget(label, alignment=Qt.AlignCenter)
        label.setPixmap(QPixmap.fromImage(image))

        monospace = QFont()
        monospace.setFamily('monospace')
        dataView = QPlainTextEdit(readOnly=True, font=monospace)
        dataView.setWordWrapMode(QTextOption.WrapAnywhere)
        layout.addWidget(dataView)

        bytearray = QByteArray()
        buffer = QBuffer(bytearray)
        image.save(buffer, 'PNG')
        base64data = bytes(bytearray.toBase64()).decode()

        dataView.appendHtml('''
            Raw image data size: {}<br/>
            Saved image data size: {}<br/>
            Base64 data size: {}<br/>
            Ratio: {}<br/><br/>
            Base64 contents:<br/><br/>
            {}
        '''.format(
            imarray.size, 
            len(bytearray), 
            len(base64data), 
            len(base64data) / imarray.size, 
            base64data
        ))
        dataView.moveCursor(QTextCursor.Start)

        imageData = '''
            <img src="data:image/png;base64,{}" width=128 height=128>
        '''.format(base64data)
        label.setToolTip('This is a tooltip.<br/>' + imageData)

    def sizeHint(self):
        return QApplication.primaryScreen().size()

While Qt support for HTML is limited to a smaller subset of HTML4, that support is quite compliant and consistent, including the Base64 encoding for embedded image data.

The solution is then to save the image data as an image file in a memory buffer, convert its contents to the base 64 encoding and use that for the img tag.

Be aware: base64 is a six-bit encoding, and any unencoded data cannot be divided with that data size will cause padding of the bytes. This obviously means that the memory footprint of the stored data will always be equal (rarely) or bigger (most likely) than the original.

In the following example I'm showing the random image as a QPixmap set for a QLabel, and the tooltip of that image can be visible by hovering it.

I also added a basic text viewer to show the actual contents of the "raw data" in order to realize the possible size (and memory requirement) for each possible image tooltip. Note that Qt will obviously use memory for both the base64 data and the cached image.

If you are not interested in high quality of the tooltip image, you can obviously use the 'JPG' format: quality results will vary, but you will certainly get a smaller memory requirement.

Remember that the above is quite important: the contents of a QToolTip are evaluated dynamically at runtime, and since every time a different tool tip content is going to be shown, the whole contents of the next tool tip will be evaluated, this will add a considerable overhead: Qt will check if the tool tip text possibly contains rich text, then create a new QTextDocument, parse the HTML and convert it to its own layout, compute all required sizes, and finally update the new QToolTip with the updated and laid out contents. Use this with extreme awareness, especially for high resolution images, for which you should really consider resizing before setting the tool tip contents.

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        imarray = np.random.rand(256, 256, 3) * 255
        image = QImage(imarray, imarray.shape[1], imarray.shape[0], 
            QImage.Format_RGB888)

        central = QWidget()
        layout = QVBoxLayout(central)
        self.setCentralWidget(central)

        label = QLabel()
        layout.addWidget(label, alignment=Qt.AlignCenter)
        label.setPixmap(QPixmap.fromImage(image))

        monospace = QFont()
        monospace.setFamily('monospace')
        dataView = QPlainTextEdit(readOnly=True, font=monospace)
        dataView.setWordWrapMode(QTextOption.WrapAnywhere)
        layout.addWidget(dataView)

        bytearray = QByteArray()
        buffer = QBuffer(bytearray)
        image.save(buffer, 'PNG')
        base64data = bytes(bytearray.toBase64()).decode()

        dataView.appendHtml('''
            Raw image data size: {}<br/>
            Saved image data size: {}<br/>
            Base64 data size: {}<br/>
            Ratio: {}<br/><br/>
            Base64 contents:<br/><br/>
            {}
        '''.format(
            imarray.size, 
            len(bytearray), 
            len(base64data), 
            len(base64data) / imarray.size, 
            base64data
        ))
        dataView.moveCursor(QTextCursor.Start)

        imageData = '''
            <img src="data:image/png;base64,{}" width=128 height=128>
        '''.format(base64data)
        label.setToolTip('This is a tooltip.<br/>' + imageData)

    def sizeHint(self):
        return QApplication.primaryScreen().size()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文