如何使用 HTML 按钮关闭应用程序

Posted

技术标签:

【中文标题】如何使用 HTML 按钮关闭应用程序【英文标题】:How To Close Application Using HTML Button 【发布时间】:2021-09-27 20:19:58 【问题描述】:

在我的 PyQt5 浏览器窗口中,我已经加载了 htmljavascript。我在 HTML 中包含了一个按钮,它应该使用 vanilla JavaScript 关闭 Python 应用程序。这是我创建窗口并加载 HTML 文件的 Python 代码:

import sys
import os
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.browser = QWebEngineView()
        config_name = 'data_files/init.html'
        if getattr(sys, 'frozen', False):
            application_path = os.path.dirname(sys.executable)
        elif __file__:
            application_path = os.path.dirname(__file__)
        config_path = os.path.join(application_path, config_name)
        self.browser.load(QUrl().fromLocalFile(config_path))
        self.setCentralWidget(self.browser)
        self.showMaximized()


app = QApplication(sys.argv)
QApplication.setApplicationName('v0.1')
window = MainWindow()
app.exec_()

在我的 HTML 中,我有这个:

<button onclick="exitApplication()">Exit</button>

<script>
    function exitApplication() 
        // How can I tell Python to call self.close() ??
    
</script>

正如我所说,我想使用 HTML 中的按钮关闭应用程序。我查看了各种来源,但我从来没有找到任何可以帮助我或让我感到困惑的东西。

调用exitApplication()-Function时如何关闭应用程序?

【问题讨论】:

【参考方案1】:

首先要知道,关闭窗口和退出应用程序是不一样的,如果你只有一个窗口并且属性quitOnLastWindowClosed为True,那么它们是等价的,但一般情况下是不一样的。

QtWebChannel:

import sys
import os
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QCoreApplication, QObject, QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebChannel import QWebChannel

application_path = (
    os.path.dirname(sys.executable)
    if getattr(sys, "frozen", False)
    else os.path.dirname(__file__)
)


class Bridge(QObject):
    request_closed = pyqtSignal()

    @pyqtSlot()
    def quit(self):
        QCoreApplication.quit()

    @pyqtSlot()
    def close(self):
        self.request_closed.emit()


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.browser = QWebEngineView()

        self.bridge = Bridge()

        self.bridge.request_closed.connect(self.close)

        self.channel = QWebChannel()
        self.channel.registerObject("bridge", self.bridge)
        self.browser.page().setWebChannel(self.channel)

        config_name = "data_files/init.html"
        config_path = os.path.join(application_path, config_name)
        self.browser.load(QUrl.fromLocalFile(config_path))
        self.setCentralWidget(self.browser)
        self.showMaximized()


if __name__ == "__main__":

    app = QApplication(sys.argv)
    QApplication.setApplicationName("v0.1")
    window = MainWindow()
    app.exec_()
<!DOCTYPE html>
<html>
  <head>
    <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
  </head>
  <body>
    <button onclick="exitApplication()">Exit</button>

    <script>
      var bridge = null;
      function exitApplication() 
        bridge.quit();
        // bridge.close();
      
      if (typeof QWebChannel !== "undefined") 
        new QWebChannel(qt.webChannelTransport, function (channel) 
          bridge = channel.objects.bridge;
        );
      
    </script>
  </body>
</html>

QWebEngineUrlSchemeHandler:

import sys
import os
from PyQt5.QtCore import QCoreApplication, QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebEngineCore import (
    QWebEngineUrlScheme,
    QWebEngineUrlSchemeHandler,
    QWebEngineUrlRequestJob,
)
from PyQt5.QtWebEngineWidgets import QWebEngineView


application_path = (
    os.path.dirname(sys.executable)
    if getattr(sys, "frozen", False)
    else os.path.dirname(__file__)
)


class QtSchemeHandler(QWebEngineUrlSchemeHandler):
    def requestStarted(self, job):
        if job.requestMethod() == b"POST" and job.requestUrl() == QUrl(
            "qt://commands/quit"
        ):
            QCoreApplication.quit()
            return
        job.fail(QWebEngineUrlRequestJob.RequestFailed)


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.browser = QWebEngineView()
        self.scheme_handler = QtSchemeHandler()
        self.browser.page().profile().installUrlSchemeHandler(
            b"qt", self.scheme_handler
        )

        config_name = "data_files/init.html"
        config_path = os.path.join(application_path, config_name)
        self.browser.load(QUrl.fromLocalFile(config_path))
        self.setCentralWidget(self.browser)
        self.showMaximized()


if __name__ == "__main__":

    scheme = QWebEngineUrlScheme(b"qt")
    scheme.setFlags(QWebEngineUrlScheme.CorsEnabled)
    QWebEngineUrlScheme.registerScheme(scheme)

    app = QApplication(sys.argv)
    QApplication.setApplicationName("v0.1")
    window = MainWindow()
    app.exec_()
<!DOCTYPE html>
<html>
  <body>
    <button onclick="exitApplication()">Exit</button>

    <script>
      function exitApplication() 
        const xhr = new XMLHttpRequest();
        xhr.open("POST", "qt://commands/quit", true);
        xhr.send();
      
    </script>
  </body>
</html>

【讨论】:

谢谢,我会试试这个!您能否在这里更详细地解释这部分:qrc:///qtwebchannel/qwebchannel.js我不明白,这是一些额外的库,我找不到吗?这是正确的来源吗:doc.qt.io/archives/qt-5.9/…? @Miger 你不需要做任何事情,因为该库包含在 Qt 中(qrc 是 Qt 的内部资源) 这很好,我会尽快尝试,如果检查成功,我会将其标记为已接受的答案。感谢您的帮助! 工作就像一个魅力,谢谢!

以上是关于如何使用 HTML 按钮关闭应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用未完成按钮顶部栏的按钮关闭 inAppbrowser

单击inappbrowser中启动的页面上的按钮时如何关闭phonegap inappbrowser?

HTML中如何让窗口在点击按钮关闭该窗口?

如何使用 html5/动态站点创建 URL [关闭]

当元素不是按钮且在 Selenium 中不可定位时,如何查找在网页中单击了哪个元素? (HTML,硒)[关闭]

如何在警报视图中隐藏关闭按钮和关闭操作以仅显示“打开应用程序”按钮