Как открыть веб окно по кнопке в pyqt?

Хочу открыть web окно с изображением графика plotly по кнопке. Пытаюсь открыть, но либо web окно открывается на долю секунды, либо всё закрывается без ошибки.

import plotly.offline as po
import plotly.graph_objs as go
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWebEngineWidgets import QWebEngineView
import sys


def start_web(fig):
    raw_html = '<html><head><meta charset="utf-8" />'
    raw_html += '<script src="https://cdn.plot.ly/plotly-latest.min.js"></script></head>'
    raw_html += '<body>'
    raw_html += po.plot(fig, include_plotlyjs=False, output_type='div')
    raw_html += '</body></html>'

    fig_view = QWebEngineView()

    screen = app.primaryScreen()
    size = screen.size()

    fig_view.resize(size.width() / 2, size.height() / 2)
    fig_view.setHtml(raw_html)
    fig_view.show()
    fig_view.raise_()
    return fig_view

def on_clicked():
    fig = go.Figure(data=[{'type': 'scattergl', 'y': [2, 1, 3, 1, 10]}])
    fig_view = start_web(fig)


app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QWidget()
window.setWindowTitle("График температуры")
screen = app.primaryScreen()
size = screen.size()
window.resize(size.width() / 4, size.height() / 4)

text_com_ports = QtWidgets.QLabel("Com-порт", window)
text_addr_slave = QtWidgets.QLabel("Адресс устройства", window)
text_addr_regs = QtWidgets.QLabel("Регистр", window)

btn_connect = QtWidgets.QPushButton("Подключиться", window)
btn_connect.resize(280, 60)
btn_trend = QtWidgets.QPushButton("Открыть график", window)
text_com_ports.setGeometry(10, 10, 100, 100)

com_ports = QtWidgets.QComboBox(window)
com_ports.move(250, 10)
for i in range(0, 21):
com_ports.addItem(str(i))

addr_slave = QtWidgets.QSpinBox(window)
addr_regs = QtWidgets.QSpinBox(window)
addr_slave.move(350, 10)
addr_slave.setMaximum(256)
addr_regs.move(500, 10)
addr_regs.setMaximum(256)

grid = QtWidgets.QGridLayout(window)
grid.addWidget(text_com_ports, 0, 0)
grid.addWidget(com_ports, 0, 1)
grid.addWidget(text_addr_slave, 1, 0)
grid.addWidget(addr_slave, 1, 1)
grid.addWidget(text_addr_regs, 2, 0)
grid.addWidget(addr_regs, 2, 1)
grid.addWidget(btn_connect, 3, 0)
grid.addWidget(btn_trend, 3, 1)
btn_trend.clicked.connect(on_clicked)
window.show()
sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Получается, что fig_view это локальная переменная, которая удаляется сборщиком мусора.

Попробуйте так:

import sys
import plotly.offline as po
import plotly.graph_objs as go
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWebEngineWidgets import QWebEngineView


class Widget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle("График температуры")
        screen = app.primaryScreen()
        size = screen.size()
        self.resize(size.width() / 4, size.height() / 4)
        self.browser = None

        text_com_ports = QtWidgets.QLabel("Com-порт")
        text_addr_slave = QtWidgets.QLabel("Адресс устройства")
        text_addr_regs = QtWidgets.QLabel("Регистр")
        
        btn_connect = QtWidgets.QPushButton("Подключиться")
        btn_trend = QtWidgets.QPushButton("Открыть график")
        btn_trend.clicked.connect(self.on_clicked)

        com_ports = QtWidgets.QComboBox()
        com_ports.addItems([ str(i) for i in range(21)])
        
        addr_slave = QtWidgets.QSpinBox(maximum=256)
        addr_regs = QtWidgets.QSpinBox(maximum=256)
        
        grid = QtWidgets.QGridLayout(self)
        grid.addWidget(text_com_ports, 0, 0)
        grid.addWidget(com_ports, 0, 1)
        grid.addWidget(text_addr_slave, 1, 0)
        grid.addWidget(addr_slave, 1, 1)
        grid.addWidget(text_addr_regs, 2, 0)
        grid.addWidget(addr_regs, 2, 1)
        grid.addWidget(btn_connect, 3, 0)
        grid.addWidget(btn_trend, 3, 1)

    @QtCore.pyqtSlot()
    def start_web(self, fig):
        raw_html = '<html><head><meta charset="utf-8" />'
        raw_html += '<script src="https://cdn.plot.ly/plotly-latest.min.js"></script></head>'
        raw_html += '<body>'
        raw_html += po.plot(fig, include_plotlyjs=False, output_type='div')
        raw_html += '</body></html>'
        return raw_html

    @QtCore.pyqtSlot()
    def on_clicked(self):
        self.browser = QWebEngineView()
        
        fig = go.Figure(data=[{'type': 'scattergl', 'y': [2, 1, 3, 1, 10]}])
        fig_view = self.start_web(fig)

        self.browser.setHtml(fig_view)
        self.browser.show()
        
    def closeEvent(self, event):
        if self.browser:
            self.browser.hide()
    

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    view = Widget()
    view.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка