1

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_()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
wooloop
  • 41
  • 1
  • 7

2 Answers2

3

Qt has conventions to name its methods:

  • the getters: property()
  • the setters: setProperty()

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

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • 1
    Oh, that makes a lot more sense! Making that change stopped the error from happening but the plot still isn't showing. The file has the plot saved just fine though. Am I missing a display command or is QTextBrowser not compatible with Bokeh plots? – wooloop Jun 14 '19 at 20:53
  • @wooloop I can not answer anything since your code has little information, if you want help you must provide a [mcve] – eyllanesc Jun 14 '19 at 20:56
  • I edited the original post with a general example that has the same issue of saving a working Bokeh plot but not displaying it. Will that work? – wooloop Jun 14 '19 at 21:52
  • I was able to install with the given command and even double checked that QtWebEngineWidgets was in my PyQt5 folder, but importing leads to the following error - ImportError: cannot import name 'QtWebEngineWidgets' from 'PyQt5'. Reinstalling PyQt and related packages doesn't fix this error (I'm on a Windows 10 laptop if it matters). Do you know if there's another Widget that might work? – wooloop Jun 15 '19 at 04:26
  • execute `python -m pip install pyqt5 PyQtWebEngine` as admin, Is your PC 32 or 64 bits? Are you using any IDE? If so, are you sure that your IDE is using the python that has pyqtwebengine installed? – eyllanesc Jun 15 '19 at 04:31
  • My computer is 64 bit and I’ve been using Jupyter Notebook. I tried running the same thing in Spyder and ran into the same error. All of my installs have been run as admin and pyqtwebengine shows up when I run conda list in the anaconda prompt window. – wooloop Jun 15 '19 at 08:02
  • Probably a conda bug, try installing generic python using pip to install those packages – eyllanesc Jun 15 '19 at 08:11
  • More likely than a bug is that the Qt package was (unintentionally) installed in a different conda environment than the notebook (I have seen this countless times) – bigreddot Jun 16 '19 at 04:32
  • @bigreddot How would I check for that or fix it? – wooloop Jun 17 '19 at 17:51
  • @bigreddot I figured it out! Thank you both for the help and suggestions. Somehow my computer had installed two separate pythons and environments so pip install commands were putting new packages into one environment while Jupyter was running from another environment. Not sure how I managed to do this but I'm glad I got things figured out. – wooloop Jun 17 '19 at 18:52
0
from PyQt5.QtWidgets import QTextBrowser


output = QTextBrowser()
output.setHtml("test.html")  # path to the file
  • 2
    Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. **Would you kindly [edit] your answer to include additional details for the benefit of the community?** – Jeremy Caney Aug 31 '23 at 01:56