So I made an App that shows dash graphs inside a pyqt5 which takes data from a table widget. the App fonctions well at the first data but after if I change the data in the table i can't see changes in the graph as well, so can where is the problem occurring?
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'test.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import dash
import dash_core_components as dcc
import dash_html_components as html
import threading
import plotly.figure_factory as ff
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(956, 701)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.webEngineView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.webEngineView.setUrl(QtCore.QUrl("http://127.0.0.1:8050"))
self.webEngineView.setObjectName("webEngineView")
self.verticalLayout.addWidget(self.webEngineView)
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
self.verticalLayout.addWidget(self.tableWidget)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 956, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.tableWidget.setColumnCount(3)
self.tableWidget.setRowCount(3)
self.tableWidget.setHorizontalHeaderLabels(('X', 'Y1','Y2'))
header = self.tableWidget.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
self.pushButton.clicked.connect(self.Clicked)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def Clicked(self):
df=[]
data = []
for c in range(self.tableWidget.columnCount()):
data.append([])
for r in range(self.tableWidget.rowCount()):
data[c].append(self.tableWidget.item(r,c).text())
for r in range(self.tableWidget.rowCount()):
df.append(dict(Task=data[0][r], Start=data[1][r], Finish=data[2][r]))
print(df)
threading.Thread(target=self.run_dash, args=([df]), daemon=True).start()
def run_dash(self,df):
fig = ff.create_gantt(df)
app = dash.Dash()
app.layout = html.Div([
dcc.Graph(figure=fig)
])
app.run_server(debug=True, use_reloader=False)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
from PyQt5 import QtWebEngineWidgets
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory.create('Fusion'))
Optimizer = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(Optimizer)
Optimizer.show()
sys.exit(app.exec_())
Note : the seconde and third columns are date columns to show a gantt chart. so data entry in those two columns shauld be like: 2020-07-27 | 2020-07-30
Dash launches a server that updates the information but this is rendered by the browser, this means that although the server has updated information on the client side, it must request that updated information and repaint it. This can be done by reloading the page:
import sys
import threading
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.figure_factory as ff
class QDash(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._app = dash.Dash()
self.app.layout = html.Div()
@property
def app(self):
return self._app
def update_graph(self, df):
fig = ff.create_gantt(df)
self.app.layout = html.Div([dcc.Graph(figure=fig)])
def run(self, **kwargs):
threading.Thread(target=self.app.run_server, kwargs=kwargs, daemon=True).start()
class Mainwindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.browser = QtWebEngineWidgets.QWebEngineView()
self.table = QtWidgets.QTableWidget()
self.button = QtWidgets.QPushButton("Press me")
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(self.browser, stretch=1)
lay.addWidget(self.table, stretch=1)
lay.addWidget(self.button)
self.resize(640, 480)
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(("X", "Y1", "Y2"))
header = self.table.horizontalHeader()
for i in range(self.table.columnCount()):
header.setSectionResizeMode(i, QtWidgets.QHeaderView.Stretch)
self.qdask = QDash()
self.qdask.run(debug=True, use_reloader=False)
self.browser.load(QtCore.QUrl("http://127.0.0.1:8050"))
self.button.clicked.connect(self.update_figure)
current_date = QtCore.QDateTime.currentDateTime()
for i in range(3):
self.append_row(
task="Task{}".format(i),
start=current_date,
finish=current_date.addDays(i + 1),
)
@QtCore.pyqtSlot()
def update_figure(self):
df = []
for i in range(self.table.rowCount()):
task = self.table.item(i, 0).data(QtCore.Qt.DisplayRole)
start = (
self.table.item(i, 1)
.data(QtCore.Qt.DisplayRole)
.toString(QtCore.Qt.ISODateWithMs)
)
finish = (
self.table.item(i, 2)
.data(QtCore.Qt.DisplayRole)
.toString(QtCore.Qt.ISODateWithMs)
)
d = dict(Task=task, Start=start, Finish=finish)
df.append(d)
print(df)
self.qdask.update_graph(df)
self.browser.reload()
def append_row(
self,
task="",
start=QtCore.QDateTime.currentDateTime(),
finish=QtCore.QDateTime.currentDateTime(),
):
row = self.table.rowCount()
self.table.insertRow(row)
for column, value in enumerate((task, start, finish)):
it = QtWidgets.QTableWidgetItem()
it.setData(QtCore.Qt.DisplayRole, value)
self.table.setItem(row, column, it)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
w = Mainwindow()
w.show()
sys.exit(app.exec_())