pythonpyqtpyqt5bokehqtextbrowser

How do I load/display an html file into my QTextBrowser widget?


I'm teaching myself how to code UI in python with PyQt5. One of the things I want to do is take an html document saved in the same folder as my app and display its contents. It looked like QTextBrowser was the proper widget to load/display html documents but I'm having trouble figuring out what command to use and how to use it. I'm sorry if this is a stupid question but I'm still new to both Python and UI coding so I'm having trouble understanding the documentation and what I'm doing wrong.

The documentation for QTextBrowser mentioned QUrl, setSource, and source for ways to load documents. I've tried putting my html document's name into each of those but none of them work. The userSet is a dataset determined from user input and the user input and data generation works fine because I was able to display a table of the data using the QTableView widget.

import sys
from PyQt5 import QtCore, QtGui, uic, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QTableWidget, QTableWidgetItem

class MyApp(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.submitButton.clicked.connect(self.handleInput)
        self.htmlView = QtWidgets.QTextBrowser(self)

    def handleInput(self):
        #Display Hexbin
        p = figure(plot_width = 300, plot_height = 300)
        p.hexbin(userSet.day, userSet.score, size = 1)
        html = output_file("userHexbin.html")
        save(p)
        self.oLayout.addWidget(self.htmlView)
        self.htmlView.source("userHexbin.html")

I expect the app to display the hexbin plot I have saved at userHexbin.html but I get the following error - TypeError: source(self): too many arguments. I don't know where else I'm supposed to put my document name though.

EDIT:

from bokeh.plotting import figure, output_file, show, save
from bokeh.resources import CDN
import pandas as pd
import sys
from PyQt5 import QtCore, QtGui, uic, QtWidgets
from PyQt5.QtWidgets import *
app = QApplication([])
button = QPushButton('Submit')
def on_button_clicked():
    p = figure(plot_width = 300, plot_height = 300)
    data = {'Day':[0, 1, 2, 3, 0, 1], 'Num':[0, 0, 1, 1, 2, 3]}
    df = pd.DataFrame(data)
    p.hexbin(df.Day, df.Num, size = .5) 
    html = output_file("test.html")
    save(p)
    output = QTextBrowser()
    output.setSource(QtCore.QUrl.fromLocalFile("test.html"))

button.clicked.connect(on_button_clicked)
button.show()
app.exec_()

Solution

  • Qt has conventions to name its methods:

    In your case, source() is a getter that is what you do not want, you must use setSource().

    On the other hand setSource() requires a QUrl so you must convert from the path using QUrl.fromLocalFile(...).

    self.htmlView.setSource(QtCore.QUrl.fromLocalFile("userHexbin.html"))
    

    QTextBrowser does not support javascript so it is not the right widget to show it, in this case I would recommend using QWebEngineView (to install it use pip install PyQtWebEngine), also it is not necessary to create a file, you can load it directly:

    import pandas as pd
    from bokeh import plotting, embed, resources
    from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
    
    
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
    
            button = QtWidgets.QPushButton("Submit")
            self.m_output = QtWebEngineWidgets.QWebEngineView()
    
            button.clicked.connect(self.on_button_clicked)
    
            lay = QtWidgets.QVBoxLayout(self)
            lay.addWidget(button)
            lay.addWidget(self.m_output)
            self.resize(640, 480)
    
        @QtCore.pyqtSlot()
        def on_button_clicked(self):
            p = plotting.figure(plot_width=300, plot_height=300)
            data = {"Day": [0, 1, 2, 3, 0, 1], "Num": [0, 0, 1, 1, 2, 3]}
            df = pd.DataFrame(data)
            p.hexbin(df.Day, df.Num, size=0.5)
            html = embed.file_html(p, resources.CDN, "my plot")
            self.m_output.setHtml(html)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        w = Widget()
        w.show()
    
        sys.exit(app.exec_())
    

    enter image description here