在 PyQt5 GUI 中嵌入 Plotly-Dash 图:握手失败,SSL 错误
Embedding a Plotly-Dash plot in a PyQt5 GUI: Handshake Failed, SSL Error
我正在尝试构建一个 GUI 来帮助我的团队以信号的形式快速比较大量测试数据。我设想以类似于 Audacity 的格式进行高度模块化、交互式的绘图。我正在 PyQt5 中构建 GUI,目前正在尝试决定使用什么进行绘图;我计划使用 matplotlib,但对于预期用途来说它会非常笨重。 Plotly and/or Dash 似乎更有前途;然而,它们只在浏览器中显示交互图,所以我需要使用嵌入在 GUI 中的某种浏览器显示。因此,QWebEngineView。
我的 GUI 本身将在我开发的 QTabWidget 中的选项卡中放置图表,其他选项卡填充有占位符 matplotlib 图,我想替换它们,因为它们缺乏简单的交互性。我能够在浏览器中成功显示网页 (google.com)。
在 PyQt5 GUI 中的 QTabWidget 中的 QWebEngineView 对象中成功显示网页
然而,当我将它指向我的 Dash plot 的地址时(出于开发目的,我在另一个内核中的单独程序 运行 中创建了该地址),它给出了一个错误:This site can't provide安全连接:
虚线图未显示
On the GUI's Kernel, the error is "[29477:29512:0716/121826.555372:ERROR:ssl_client_socket_impl.cc(1050)] handshake failed; returned -1, SSL error code 1, net_error -107".
In the kernel running the dash plot, the message is:
127.0.0.1 - - [16/Jul/2019 12:18:26] code 400, message Bad request version ('**À+À/À,À0̨̩À\x13À\x14\x00\x9c\x00\x9d\x00/\x005\x00')
127.0.0.1 - - [16/Jul/2019 12:18:26] "µ±ª~ÜÎÌDñB¤¦jËfM½;*÷hå¸GÛ¼i©Tè**À+À/À,À0̨̩ÀÀ/5" HTTPStatus.BAD_REQUEST -
这仅在 QTabsWidget 中。破折号图在单独的独立应用程序中显示良好(下面提供了作为占位符破折号图的工作代码)。
在简单的 PyQt5 GUI 中成功显示虚线图
我用谷歌搜索了这个错误,但没有找到任何相关信息。我不明白为什么这在第一个 url 上运行良好,但是当我将它指向我的 Dash 图时失败了,特别是考虑到我能够在我的精简原型中的 QWebEngineView 中查看破折号图代码。
虚线图工作代码:
import sys
import threading
from PyQt5 import QtWidgets
import dash
import dash_core_components as dcc
import dash_html_components as html
def run_dash(data, layout):
app = dash.Dash()
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Graph(
id='example-graph',
figure={
'data': data,
'layout': layout
})
])
app.run_server(debug=False)
class MainWindow(QtWidgets.QMainWindow):
pass
if __name__ == '__main__':
data = [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
layout = {
'title': 'Dash Data Visualization'
}
threading.Thread(target=run_dash, args=(data, layout), daemon=True).start()
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
根据运行这段代码,内核提供绘图地址。在我的机器上,它是 http://127.0.0.1:8050.
原型 GUI 嵌入代码:
import sys
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
web = QWebEngineView()
#web.load(QUrl("https://www.google.com"))
web.load(QUrl("http://127.0.0.1:8050"))
web.show()
sys.exit(app.exec ())
来自我实际 PyQt5 GUI 的代码片段:
web = QWebEngineView()
# web.load(QUrl("https://www.google.com")) web.load(QUrl("https://127.0.0.1:8050/"))
web.show()
self.ui.TabsContainer.addTab(web, "QWebEngineView Object")
# TabsContainer is a QTabsWidget
如何解决阻止我在 GUI 中嵌入绘图的错误?
编辑:我认为这可能与 QTabWidget 有关,所以我编写了以下简单代码来测试该想法,并且我的 Dash 图显示良好。然而,它并没有显示在我需要它的主多线程 GUI 中,尽管它是以相同的方式构造的。
import sys
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class CustomMainWindow(QMainWindow): # MainWindow is a subclass of QMainWindow
def __init__(self, *args, **kwargs):
super(CustomMainWindow, self).__init__(*args, **kwargs)
# a = 1
self.setWindowTitle("Window Title")
label = QLabel("Label")
label.setAlignment(Qt.AlignCenter)
#
layout = QVBoxLayout()
# layout.addWidget(Color('red'))
# layout.addWidget(Color('green'))
layout.addWidget(Color('blue'))
TW = QTabWidget()
web1 = QWebEngineView()
web1.load(QUrl("http://www.google.com"))
#web1.load(QUrl("http://127.0.0.1:8050"))
web2 = QWebEngineView()
web2.load(QUrl("http://127.0.0.1:8050"))
TW.addTab(web1, 'web1')
TW.addTab(web2, 'web2')
layout.addWidget(TW)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
class Color(QWidget):
def __init__(self, color, *args, **kwargs):
super(Color, self).__init__(*args, **kwargs)
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
app = QApplication(sys.argv)
CMWindow = CustomMainWindow() # Instead of using QMainWindow, we now use our custom window subclassed from QMainWindow
CMWindow.show()
sys.exit(app.exec ())
嗯,原来答案很简单:
在我发布的工作示例中,我加载了 QUrl("http://127.0.0.1:8050")。在不起作用的代码中,我使用了 https:// 。显然,Dash 图不使用 https。
我正在尝试构建一个 GUI 来帮助我的团队以信号的形式快速比较大量测试数据。我设想以类似于 Audacity 的格式进行高度模块化、交互式的绘图。我正在 PyQt5 中构建 GUI,目前正在尝试决定使用什么进行绘图;我计划使用 matplotlib,但对于预期用途来说它会非常笨重。 Plotly and/or Dash 似乎更有前途;然而,它们只在浏览器中显示交互图,所以我需要使用嵌入在 GUI 中的某种浏览器显示。因此,QWebEngineView。
我的 GUI 本身将在我开发的 QTabWidget 中的选项卡中放置图表,其他选项卡填充有占位符 matplotlib 图,我想替换它们,因为它们缺乏简单的交互性。我能够在浏览器中成功显示网页 (google.com)。
在 PyQt5 GUI 中的 QTabWidget 中的 QWebEngineView 对象中成功显示网页
然而,当我将它指向我的 Dash plot 的地址时(出于开发目的,我在另一个内核中的单独程序 运行 中创建了该地址),它给出了一个错误:This site can't provide安全连接:
虚线图未显示
On the GUI's Kernel, the error is "[29477:29512:0716/121826.555372:ERROR:ssl_client_socket_impl.cc(1050)] handshake failed; returned -1, SSL error code 1, net_error -107".
In the kernel running the dash plot, the message is:
127.0.0.1 - - [16/Jul/2019 12:18:26] code 400, message Bad request version ('**À+À/À,À0̨̩À\x13À\x14\x00\x9c\x00\x9d\x00/\x005\x00')
127.0.0.1 - - [16/Jul/2019 12:18:26] "µ±ª~ÜÎÌDñB¤¦jËfM½;*÷hå¸GÛ¼i©Tè**À+À/À,À0̨̩ÀÀ/5" HTTPStatus.BAD_REQUEST -
这仅在 QTabsWidget 中。破折号图在单独的独立应用程序中显示良好(下面提供了作为占位符破折号图的工作代码)。
在简单的 PyQt5 GUI 中成功显示虚线图
我用谷歌搜索了这个错误,但没有找到任何相关信息。我不明白为什么这在第一个 url 上运行良好,但是当我将它指向我的 Dash 图时失败了,特别是考虑到我能够在我的精简原型中的 QWebEngineView 中查看破折号图代码。
虚线图工作代码:
import sys
import threading
from PyQt5 import QtWidgets
import dash
import dash_core_components as dcc
import dash_html_components as html
def run_dash(data, layout):
app = dash.Dash()
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Graph(
id='example-graph',
figure={
'data': data,
'layout': layout
})
])
app.run_server(debug=False)
class MainWindow(QtWidgets.QMainWindow):
pass
if __name__ == '__main__':
data = [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
layout = {
'title': 'Dash Data Visualization'
}
threading.Thread(target=run_dash, args=(data, layout), daemon=True).start()
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
根据运行这段代码,内核提供绘图地址。在我的机器上,它是 http://127.0.0.1:8050.
原型 GUI 嵌入代码:
import sys
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
web = QWebEngineView()
#web.load(QUrl("https://www.google.com"))
web.load(QUrl("http://127.0.0.1:8050"))
web.show()
sys.exit(app.exec ())
来自我实际 PyQt5 GUI 的代码片段:
web = QWebEngineView()
# web.load(QUrl("https://www.google.com")) web.load(QUrl("https://127.0.0.1:8050/"))
web.show()
self.ui.TabsContainer.addTab(web, "QWebEngineView Object")
# TabsContainer is a QTabsWidget
如何解决阻止我在 GUI 中嵌入绘图的错误?
编辑:我认为这可能与 QTabWidget 有关,所以我编写了以下简单代码来测试该想法,并且我的 Dash 图显示良好。然而,它并没有显示在我需要它的主多线程 GUI 中,尽管它是以相同的方式构造的。
import sys
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class CustomMainWindow(QMainWindow): # MainWindow is a subclass of QMainWindow
def __init__(self, *args, **kwargs):
super(CustomMainWindow, self).__init__(*args, **kwargs)
# a = 1
self.setWindowTitle("Window Title")
label = QLabel("Label")
label.setAlignment(Qt.AlignCenter)
#
layout = QVBoxLayout()
# layout.addWidget(Color('red'))
# layout.addWidget(Color('green'))
layout.addWidget(Color('blue'))
TW = QTabWidget()
web1 = QWebEngineView()
web1.load(QUrl("http://www.google.com"))
#web1.load(QUrl("http://127.0.0.1:8050"))
web2 = QWebEngineView()
web2.load(QUrl("http://127.0.0.1:8050"))
TW.addTab(web1, 'web1')
TW.addTab(web2, 'web2')
layout.addWidget(TW)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
class Color(QWidget):
def __init__(self, color, *args, **kwargs):
super(Color, self).__init__(*args, **kwargs)
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
app = QApplication(sys.argv)
CMWindow = CustomMainWindow() # Instead of using QMainWindow, we now use our custom window subclassed from QMainWindow
CMWindow.show()
sys.exit(app.exec ())
嗯,原来答案很简单:
在我发布的工作示例中,我加载了 QUrl("http://127.0.0.1:8050")。在不起作用的代码中,我使用了 https:// 。显然,Dash 图不使用 https。