pythonpython-3.xpyqtpyqt5qtextbrowser

Insert blob image into QPixMap from sqlite db to QTextBrowser in PyQt5


I can't insert qpixmap image to qtextbrowser with html tags. (I need to insert with html not other methods)

I tried the code below.

def readImage(self):
        cur = self.db.cursor()
        covers = cur.execute("select cover from covers")
        pm = QPixmap()
        for cover in covers:
            pm.loadFromData(cover[0])
            self.ui.textBrowser.setHtml("<img src=pm /img>")

The result is just a small icon which appears in qtextbrowser, but it doesn't show the actual image. please don't give me a qt c++ doc page i can't understand those c++ stuff.


Solution

  • It is not necessary to convert the data to QPixmap, if QtSql will return a QByteArray that can encode it to base64 making it possible to add the image to the QTextEdit:

    from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
    
    
    def create_connection(path=":memory:"):
        db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName(path)
        if not db.open():
            QtWidgets.QMessageBox.critical(
                None,
                QtWidgets.qApp.tr("Cannot open database"),
                QtWidgets.qApp.tr(
                    "Unable to establish a database connection.\n"
                    "This example needs SQLite support. Please read "
                    "the Qt SQL driver documentation for information "
                    "how to build it.\n\n"
                    "Click Cancel to exit."
                ),
                QtWidgets.QMessageBox.Cancel,
            )
            return False
        return True
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.text_edit = QtWidgets.QTextEdit()
            self.setCentralWidget(self.text_edit)
    
            query = QtSql.QSqlQuery("SELECT cover FROM covers")
            while query.next():
                ba = query.value(0)
                base64 = ba.toBase64().data().decode()
                self.text_edit.insertHtml(
                    """<img height="200" width="200" src="data:image/png;base64,{}"/>""".format(base64)
                )
            self.resize(640, 480)
    
    
    if __name__ == "__main__":
        import os
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        current_dir = os.path.dirname(os.path.realpath(__file__))
        path = os.path.join(current_dir, "rap.sqlite")
    
        if not create_connection(path):
            sys.exit(-1)
    
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    

    If you want to continue using sqlite3 then you must convert the bytes to QByteArray and apply the same logic:

    import os
    import sqlite3
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.text_edit = QtWidgets.QTextEdit()
            self.setCentralWidget(self.text_edit)
    
            current_dir = os.path.dirname(os.path.realpath(__file__))
            path = os.path.join(current_dir, "rap.sqlite")
    
            conn = sqlite3.connect(path)
            c = conn.cursor()
    
            covers = c.execute("SELECT cover FROM covers")
            for cover in covers:
                data, *_ = cover
                ba = QtCore.QByteArray(data)
                base64 = ba.toBase64().data().decode()
                self.text_edit.insertHtml(
                    """<img height="200" width="200" src="data:image/png;base64,{}"/>""".format(base64)
                )
            self.resize(640, 480)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())