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_()
Qt has conventions to name its methods:
property()
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_())