WebEngine ウィジェット シンプルブラウザの例

Qt WebEngine ウィジェットをベースにしたシンプルなブラウザです。

使用する方法を示します。 Qt WebEngine C++ classesを使用して、次の要素を含む小さなウェブブラウザアプリケーションを開発する方法を示します:

  • 保存されたページを開き、ウィンドウとタブを管理するためのメニューバー。
  • URL を入力し、ウェブページの閲覧履歴を前後に移動するためのナビゲーションバー。
  • タブ内にウェブコンテンツを表示するためのマルチタブエリア。
  • ホバーされたリンクを表示するステータスバー
  • シンプルなダウンロードマネージャー

ウェブコンテンツは、新しいタブまたは別のウィンドウで開くことができます。ウェブページへのアクセスにHTTP認証とプロキシ認証を使用できます。

例の実行

からサンプルを実行するには Qt Creatorからサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、「例の構築と実行」を参照してください。

クラス階層

まず、これから実装する主なクラスの図を描くことから始めます:

  • Browser はアプリケーションのウィンドウを管理するクラスです。
  • BrowserWindow は 、メニュー、ナビゲーション・バー、 、ステータス・バーを示します。QMainWindow TabWidget
  • TabWidget は で、1 つまたは複数のブラウザー・タブを含みます。QTabWidget
  • WebView は で、 のビューを提供し、 のタブとして追加されます。QWebEngineView WebPage TabWidget
  • WebPage は で、ウェブサイトのコンテンツを表します。QWebEnginePage

さらに、いくつかの補助クラスを実装します:

  • WebPopupWindow は、ポップアップ・ウィンドウを表示するための です。QWidget
  • DownloadManagerWidget はダウンロードリストを実装する です。QWidget

ブラウザのメインウィンドウの作成

この例では、Browser オブジェクトが所有する複数のメインウィンドウをサポートしています。このクラスは、DownloadManagerWidget も所有し、ブックマークや履歴マネージャなどのさらなる機能にも使用できます。

main.cpp で、最初のBrowserWindow インスタンスを作成し、Browser オブジェクトに追加します。コマンドラインに引数が渡されなければ、Qtホームページを開きます:

int main(int argc, char **argv)
{
    QCoreApplication::setOrganizationName("QtExamples");

    QApplication app(argc, argv);
    app.setWindowIcon(QIcon(u":AppLogoColor.png"_s));
    QLoggingCategory::setFilterRules(u"qt.webenginecontext.debug=true"_s);

    QWebEngineProfile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
    QWebEngineProfile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true);
    QWebEngineProfile::defaultProfile()->settings()->setAttribute(
            QWebEngineSettings::ScreenCaptureEnabled, true);

    QUrl url = commandLineUrlArgument();

    Browser browser;
    BrowserWindow *window = browser.createHiddenWindow();
    window->tabWidget()->setUrl(url);
    window->show();
    return app.exec();
}

ウィンドウをOpenGLレンダリングに切り替えたときのちらつきを抑えるために、最初のブラウザ・タブが追加された後にshowを呼び出します。

タブの作成

BrowserWindow コンストラクタは、必要なユーザーインターフェース関連オブジェクトをすべて初期化します。BrowserWindowcentralWidget にはTabWidget のインスタンスが含まれます。TabWidget には、1つまたは複数のWebView インスタンスがタブとして含まれ、現在選択されているものにシグナルとスロットを委譲します:

class TabWidget : public QTabWidget
{
    ...
signals:
    // current tab/page signals
    void linkHovered(const QString &link);
    void loadProgress(int progress);
    void titleChanged(const QString &title);
    void urlChanged(const QUrl &url);
    void favIconChanged(const QIcon &icon);
    void webActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled);
    void devToolsRequested(QWebEnginePage *source);
    void findTextFinished(const QWebEngineFindTextResult &result);

public slots:
    // current tab/page slots
    void setUrl(const QUrl &url);
    void triggerWebPageAction(QWebEnginePage::WebAction action);
    ...
};

各タブはWebView のインスタンスを含む:

WebView *TabWidget::createTab()
{
    WebView *webView = createBackgroundTab();
    setCurrentWidget(webView);
    return webView;
}

WebView *TabWidget::createBackgroundTab()
{
    WebView *webView = new WebView;
    WebPage *webPage = new WebPage(m_profile, webView);
    webView->setPage(webPage);
    setupView(webView);
    int index = addTab(webView, tr("(Untitled)"));
    setTabIcon(index, webView->favIcon());
    // Workaround for QTBUG-61770
    webView->resize(currentWidget()->size());
    webView->show();
    return webView;
}

TabWidget::setupView() では、TabWidget が常に現在選択されているWebView のシグナルを転送するようにしています:

void TabWidget::setupView(WebView *webView)
{
    QWebEnginePage *webPage = webView->page();

    connect(webView, &QWebEngineView::titleChanged, [this, webView](const QString &title) {
        int index = indexOf(webView);
        if (index != -1) {
            setTabText(index, title);
            setTabToolTip(index, title);
        }
        if (currentIndex() == index)
            emit titleChanged(title);
    });
    connect(webView, &QWebEngineView::urlChanged, [this, webView](const QUrl &url) {
        int index = indexOf(webView);
        if (index != -1)
            tabBar()->setTabData(index, url);
        if (currentIndex() == index)
            emit urlChanged(url);
    });
    connect(webView, &QWebEngineView::loadProgress, [this, webView](int progress) {
        if (currentIndex() == indexOf(webView))
            emit loadProgress(progress);
    });
    connect(webPage, &QWebEnginePage::linkHovered, [this, webView](const QString &url) {
        if (currentIndex() == indexOf(webView))
            emit linkHovered(url);
    });
    connect(webView, &WebView::favIconChanged, [this, webView](const QIcon &icon) {
        int index = indexOf(webView);
        if (index != -1)
            setTabIcon(index, icon);
        if (currentIndex() == index)
            emit favIconChanged(icon);
    });
    connect(webView, &WebView::webActionEnabledChanged, [this, webView](QWebEnginePage::WebAction action, bool enabled) {
        if (currentIndex() ==  indexOf(webView))
            emit webActionEnabledChanged(action,enabled);
    });
    connect(webPage, &QWebEnginePage::windowCloseRequested, [this, webView]() {
        int index = indexOf(webView);
        if (webView->page()->inspectedPage())
            window()->close();
        else if (index >= 0)
            closeTab(index);
    });
    connect(webView, &WebView::devToolsRequested, this, &TabWidget::devToolsRequested);
    connect(webPage, &QWebEnginePage::findTextFinished, [this, webView](const QWebEngineFindTextResult &result) {
        if (currentIndex() == indexOf(webView))
            emit findTextFinished(result);
    });
}

タブを閉じる

ユーザーがタブを閉じると、まず対応するWebViewRequestClose Web アクションをトリガーします:

    connect(tabBar, &QTabBar::tabCloseRequested, [this](int index) {
        if (WebView *view = webView(index))
            view->page()->triggerAction(QWebEnginePage::WebAction::RequestClose);
    });

これにより、JavaScriptbeforeunload のイベントリスナーが起動し、ページを閉じるかどうかを確認するダイアログが表示されます。この場合、ユーザーは閉じる要求を拒否し、タブを開いたままにすることができます。そうでなければ、windowCloseRequested シグナルが発せられ、タブを閉じます:

    connect(webPage, &QWebEnginePage::windowCloseRequested, [this, webView]() {
        int index = indexOf(webView);
        if (webView->page()->inspectedPage())
            window()->close();
        else if (index >= 0)
            closeTab(index);
    });

WebView 機能の実装

WebViewQWebEngineView から派生したもので、以下の機能をサポートしています:

  • renderProcess が終了した場合のエラーメッセージの表示
  • createWindow リクエストの処理
  • コンテキストメニューへのカスタムメニュー項目の追加

まず、必要なメソッドとシグナルを持つWebView を作成します:

class WebView : public QWebEngineView
{
    Q_OBJECT

public:
    explicit WebView(QWidget *parent = nullptr);
    ...
protected:
    void contextMenuEvent(QContextMenuEvent *event) override;
    QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) override;

signals:
    void webActionEnabledChanged(QWebEnginePage::WebAction webAction, bool enabled);
    ...
};
エラーメッセージの表示

レンダー処理が終了した場合は、エラーコードとともにQMessageBox を表示し、ページを再読み込みします:

WebView::WebView(QWidget *parent)
    : QWebEngineView(parent)
{
    ...
    connect(this, &QWebEngineView::renderProcessTerminated,
            [this](QWebEnginePage::RenderProcessTerminationStatus termStatus, int statusCode) {
        QString status;
        switch (termStatus) {
        case QWebEnginePage::NormalTerminationStatus:
            status = tr("Render process normal exit");
            break;
        case QWebEnginePage::AbnormalTerminationStatus:
            status = tr("Render process abnormal exit");
            break;
        case QWebEnginePage::CrashedTerminationStatus:
            status = tr("Render process crashed");
            break;
        case QWebEnginePage::KilledTerminationStatus:
            status = tr("Render process killed");
            break;
        }
        QMessageBox::StandardButton btn = QMessageBox::question(window(), status,
                                                   tr("Render process exited with code: %1\n"
                                                      "Do you want to reload the page ?").arg(statusCode));
        if (btn == QMessageBox::Yes)
            QTimer::singleShot(0, this, &WebView::reload);
    });
}
WebWindows の管理

QWebEnginePage::WebWindowTypeたとえば、JavaScript プログラムが新しいウィンドウやダイアログでドキュメントを開くように要求した場合などです。この場合はQWebView::createWindow() をオーバーライドします:

QWebEngineView *WebView::createWindow(QWebEnginePage::WebWindowType type)
{
    BrowserWindow *mainWindow = qobject_cast<BrowserWindow*>(window());
    if (!mainWindow)
        return nullptr;

    switch (type) {
    case QWebEnginePage::WebBrowserTab: {
        return mainWindow->tabWidget()->createTab();
    }

QWebEnginePage::WebDialog の場合、WebPopupWindow クラスのインスタンスを作成します:

class WebPopupWindow : public QWidget
{
    Q_OBJECT

public:
    explicit WebPopupWindow(QWebEngineProfile *profile);
    WebView *view() const;

private slots:
    void handleGeometryChangeRequested(const QRect &newGeometry);

private:
    QLineEdit *m_urlLineEdit;
    QAction *m_favAction;
    WebView *m_view;
};
コンテキストメニュー項目の追加

コンテキストメニューにメニュー項目を追加して、ユーザが右クリックでインスペクタを新しいウィンドウで開けるようにします。QWebEngineView::contextMenuEvent をオーバーライドし、QWebEnginePage::createStandardContextMenu を使用して、QWebEnginePage::WebAction アクションのデフォルトリストを持つデフォルトのQMenu を作成します。

QWebEnginePage::InspectElement アクションのデフォルト名はInspect です。わかりやすくするため、インスペクタがまだ存在しない場合はOpen Inspector In New Window に、すでに作成されている場合はInspect Element に名前を変更します。

また、QWebEnginePage::ViewSource アクションがメニューにあるかどうかもチェックする。もしなければ、セパレーターも追加しなければならないからだ。

void WebView::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu *menu = createStandardContextMenu();
    const QList<QAction *> actions = menu->actions();
    auto inspectElement = std::find(actions.cbegin(), actions.cend(), page()->action(QWebEnginePage::InspectElement));
    if (inspectElement == actions.cend()) {
        auto viewSource = std::find(actions.cbegin(), actions.cend(), page()->action(QWebEnginePage::ViewSource));
        if (viewSource == actions.cend())
            menu->addSeparator();

        QAction *action = menu->addAction("Open inspector in new window");
        connect(action, &QAction::triggered, [this]() { emit devToolsRequested(page()); });
    } else {
        (*inspectElement)->setText(tr("Inspect element"));
    }

    // add conext menu for image policy
    QMenu *editImageAnimation = new QMenu(tr("Image animation policy"));

    m_imageAnimationGroup = new QActionGroup(editImageAnimation);
    m_imageAnimationGroup->setExclusive(true);

    QAction *disableImageAnimation =
            editImageAnimation->addAction(tr("Disable all image animation"));
    disableImageAnimation->setCheckable(true);
    m_imageAnimationGroup->addAction(disableImageAnimation);
    connect(disableImageAnimation, &QAction::triggered, [this]() {
        handleImageAnimationPolicyChange(QWebEngineSettings::ImageAnimationPolicy::Disallow);
    });
    QAction *allowImageAnimationOnce =
            editImageAnimation->addAction(tr("Allow animated images, but only once"));
    allowImageAnimationOnce->setCheckable(true);
    m_imageAnimationGroup->addAction(allowImageAnimationOnce);
    connect(allowImageAnimationOnce, &QAction::triggered,
            [this]() { handleImageAnimationPolicyChange(QWebEngineSettings::ImageAnimationPolicy::AnimateOnce); });
    QAction *allowImageAnimation = editImageAnimation->addAction(tr("Allow all animated images"));
    allowImageAnimation->setCheckable(true);
    m_imageAnimationGroup->addAction(allowImageAnimation);
    connect(allowImageAnimation, &QAction::triggered, [this]() {
        handleImageAnimationPolicyChange(QWebEngineSettings::ImageAnimationPolicy::Allow);
    });

    switch (page()->settings()->imageAnimationPolicy()) {
    case QWebEngineSettings::ImageAnimationPolicy::Allow:
        allowImageAnimation->setChecked(true);
        break;
    case QWebEngineSettings::ImageAnimationPolicy::AnimateOnce:
        allowImageAnimationOnce->setChecked(true);
        break;
    case QWebEngineSettings::ImageAnimationPolicy::Disallow:
        disableImageAnimation->setChecked(true);
        break;
    default:
        allowImageAnimation->setChecked(true);
        break;
    }

    menu->addMenu(editImageAnimation);
    menu->popup(event->globalPos());
}

WebPageとWebView機能の実装

QWebEnginePage のサブクラスとしてWebPage を実装し、QWebEngineView のサブクラスとしてWebView を実装して、HTTP、プロキシ認証、およびウェブページへのアクセス時の SSL 証明書エラーの無視を有効にします:

class WebPage : public QWebEnginePage
{
    Q_OBJECT

public:
    explicit WebPage(QWebEngineProfile *profile, QObject *parent = nullptr);

signals:
    void createCertificateErrorDialog(QWebEngineCertificateError error);

private slots:
    void handleCertificateError(QWebEngineCertificateError error);
    void handleSelectClientCertificate(QWebEngineClientCertificateSelection clientCertSelection);
    void handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request);
};

class WebView : public QWebEngineView
{
    Q_OBJECT

public:
    explicit WebView(QWidget *parent = nullptr);
    ~WebView();
    void setPage(WebPage *page);

    int loadProgress() const;
    bool isWebActionEnabled(QWebEnginePage::WebAction webAction) const;
    QIcon favIcon() const;

protected:
    void contextMenuEvent(QContextMenuEvent *event) override;
    QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) override;

signals:
    void webActionEnabledChanged(QWebEnginePage::WebAction webAction, bool enabled);
    void favIconChanged(const QIcon &icon);
    void devToolsRequested(QWebEnginePage *source);
private slots:
    void handleCertificateError(QWebEngineCertificateError error);
    void handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth);
    void handlePermissionRequested(QWebEnginePermission permission);
    void handleProxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth,
                                           const QString &proxyHost);
    void handleRegisterProtocolHandlerRequested(QWebEngineRegisterProtocolHandlerRequest request);
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
    void handleFileSystemAccessRequested(QWebEngineFileSystemAccessRequest request);
    void handleWebAuthUxRequested(QWebEngineWebAuthUxRequest *request);
#endif
    void handleImageAnimationPolicyChange(QWebEngineSettings::ImageAnimationPolicy policy);

private:
    void createWebActionTrigger(QWebEnginePage *page, QWebEnginePage::WebAction);
    void onStateChanged(QWebEngineWebAuthUxRequest::WebAuthUxState state);

private:
    int m_loadProgress = 100;
    WebAuthDialog *m_authDialog = nullptr;
    QActionGroup *m_imageAnimationGroup = nullptr;
};

上記のすべての場合において、適切なダイアログをユーザーに表示します。認証の場合、QAuthenticator オブジェクトに正しいクレデンシャル値を設定する必要があります:

void WebView::handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth)
{
    QDialog dialog(window());
    dialog.setModal(true);
    dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);

    Ui::PasswordDialog passwordDialog;
    passwordDialog.setupUi(&dialog);

    passwordDialog.m_iconLabel->setText(QString());
    QIcon icon(window()->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, window()));
    passwordDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32));

    QString introMessage(tr("Enter username and password for \"%1\" at %2")
                                 .arg(auth->realm(),
                                      requestUrl.toString().toHtmlEscaped()));
    passwordDialog.m_infoLabel->setText(introMessage);
    passwordDialog.m_infoLabel->setWordWrap(true);

    if (dialog.exec() == QDialog::Accepted) {
        auth->setUser(passwordDialog.m_userNameLineEdit->text());
        auth->setPassword(passwordDialog.m_passwordLineEdit->text());
    } else {
        // Set authenticator null if dialog is cancelled
        *auth = QAuthenticator();
    }
}

handleProxyAuthenticationRequired シグナル・ハンドラは、HTTPプロキシの認証とまったく同じ手順を実装しています。

SSLエラーが発生した場合、メインフレームから発生したのか、ページ内のリソースから発生したのかを確認します。リソースのエラーは自動的に証明書拒否をトリガーします。それ以外のケースでは、ユーザが証明書を許可または拒否できるダイアログを表示します。

void WebPage::handleCertificateError(QWebEngineCertificateError error)
{
    // Automatically block certificate errors from page resources without prompting the user.
    // This mirrors the behavior found in other major browsers.
    if (!error.isMainFrame()) {
        error.rejectCertificate();
        return;
    }

    error.defer();
    QTimer::singleShot(0, this,
                       [this, error]() mutable { emit createCertificateErrorDialog(error); });
}

ウェブ・ページを開く

このセクションでは、新しいページを開くワークフローについて説明します。ユーザーがナビゲーション・バーに URL を入力し、Enter を押すと、QLineEdit::returnPressed シグナルが発信され、新しい URL がTabWidget::setUrl に引き渡される:

BrowserWindow::BrowserWindow(Browser *browser, QWebEngineProfile *profile, bool forDevTools)
{
    ...
        connect(m_urlLineEdit, &QLineEdit::returnPressed, [this]() {
            m_tabWidget->setUrl(QUrl::fromUserInput(m_urlLineEdit->text()));
        });
    ...
}

呼び出しは現在選択されているタブに転送される:

void TabWidget::setUrl(const QUrl &url)
{
    if (WebView *view = currentWebView()) {
        view->setUrl(url);
        view->setFocus();
    }
}

WebViewsetUrl() メソッドは、url を関連するWebPage に転送するだけで、 はバックグラウンドでページのコンテンツのダウンロードを開始する。

プライベートブラウジングの実装

プライベートブラウジングインコグニートモード、または記録外モードは、多くのブラウザの機能で、クッキー、HTTP キャッシュ、または閲覧履歴のような、通常は永続的なデータがメモリ上にのみ保持され、ディスク上には痕跡を残しません。この例では、ウィンドウ・レベルでプライベート・ブラウジングを実装します。あるいは、タブレベルでプライベートブラウジングを実装し、ウィンドウ内のいくつかのタブを通常モードに、他のタブをプライベートモードにすることもできます。

Qt WebEngine を使えば、プライベートブラウジングの実装はとても簡単だ。QWebEngineProfile 、デフォルトのプロファイルの代わりにQWebEnginePage 。この例では、この新しいプロファイルはBrowser オブジェクトによって所有されています:

class Browser
{
public:
    ...
    BrowserWindow *createHiddenWindow(bool offTheRecord = false);
    BrowserWindow *createWindow(bool offTheRecord = false);
private:
    ...
    QScopedPointer<QWebEngineProfile> m_profile;
};

プライベートブラウジングに必要なプロファイルは、その最初のウィンドウとともに作成されます。QWebEngineProfile のデフォルトのコンストラクタは、すでにそれをオフレコ・モードにしています。

BrowserWindow *Browser::createHiddenWindow(bool offTheRecord)
{
    if (!offTheRecord && !m_profile) {
        const QString name = u"simplebrowser."_s + QLatin1StringView(qWebEngineChromiumVersion());
        m_profile.reset(new QWebEngineProfile(name));
    ...

あとは適切なプロファイルを適切なQWebEnginePage オブジェクトに渡すだけです。Browser オブジェクトは、グローバル・デフォルト・プロファイル(QWebEngineProfile::defaultProfile を参照)か、共有のオフ・ザ・レコード・プロファイル・インスタンスのいずれかを、新しいBrowserWindow に渡します:

    ...
        QObject::connect(m_profile.get(), &QWebEngineProfile::downloadRequested,
                         &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested);
    }
    auto profile = !offTheRecord ? m_profile.get() : QWebEngineProfile::defaultProfile();
    auto mainWindow = new BrowserWindow(this, profile, false);
    return mainWindow;
}

BrowserWindowTabWidget オブジェクトは、ウィンドウに含まれるすべてのQWebEnginePage オブジェクトがこのプロファイルを使用するようにします。

ダウンロードの管理

ダウンロードはQWebEngineProfile に関連付けられます。ウェブページでダウンロードがトリガーされるたびに、QWebEngineProfile::downloadRequested シグナルがQWebEngineDownloadRequest とともに発信され、この例ではDownloadManagerWidget::downloadRequested に転送されます:

Browser::Browser()
{
    // Quit application if the download manager window is the only remaining window
    m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false);

    QObject::connect(
        QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested,
        &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested);
}

このメソッドは、ユーザーにファイル名の入力を促し(あらかじめ入力された候補が表示される)、ダウンロードを開始する(ユーザーがSave As ダイアログをキャンセルしない限り):

void DownloadManagerWidget::downloadRequested(QWebEngineDownloadRequest *download)
{
    Q_ASSERT(download && download->state() == QWebEngineDownloadRequest::DownloadRequested);

    QString path = QFileDialog::getSaveFileName(this, tr("Save as"), QDir(download->downloadDirectory()).filePath(download->downloadFileName()));
    if (path.isEmpty())
        return;

    download->setDownloadDirectory(QFileInfo(path).path());
    download->setDownloadFileName(QFileInfo(path).fileName());
    download->accept();
    add(new DownloadWidget(download));

    show();
}

QWebEngineDownloadRequest オブジェクトは定期的にreceivedBytesChanged シグナルを発信し、潜在的なオブザーバーにダウンロードの進行状況を通知し、ダウンロードが終了したときやエラーが発生したときにstateChanged シグナルを発信します。これらのシグナルの処理方法の例については、downloadmanagerwidget.cpp を参照してください。

WebAuth/FIDO UXリクエストの管理

WebAuth UXリクエストはQWebEnginePage 。認証機関がユーザーとの対話を要求するたびに、QWebEnginePage で UX リクエストがトリガーされ、QWebEngineWebAuthUxRequestQWebEnginePage::webAuthUxRequested シグナルが発行されます。この例では、WebView::handleAuthenticatorRequired に転送されます:

    connect(page, &QWebEnginePage::webAuthUxRequested, this, &WebView::handleWebAuthUxRequested);

このメソッドは WebAuth UX ダイアログを生成し、UX リクエストフローを開始する。

void WebView::handleWebAuthUxRequested(QWebEngineWebAuthUxRequest *request)
{
    if (m_authDialog)
        delete m_authDialog;

    m_authDialog = new WebAuthDialog(request, window());
    m_authDialog->setModal(false);
    m_authDialog->setWindowFlags(m_authDialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);

    connect(request, &QWebEngineWebAuthUxRequest::stateChanged, this, &WebView::onStateChanged);
    m_authDialog->show();
}

QWebEngineWebAuthUxRequest オブジェクトはstateChanged シグナルを定期的に発信し、潜在的なオブザーバに現在の WebAuth UX の状態を通知します。オブザーバはそれに応じて WebAuth ダイアログを更新する。これらのシグナルの処理方法の例については、webview.cppwebauthdialog.cpp を参照してください。

macOS の署名要件

macOS上でSimple Browserを動作させるときに、Webサイトが位置情報、カメラ、マイクにアクセスできるようにするには、アプリケーションに署名する必要があります。これはビルド時に自動的に行われますが、ビルド環境に有効な署名IDを設定する必要があります。

ファイルと属性

この例ではTango Icon Libraryのアイコンを使用しています:

Tangoアイコンライブラリパブリックドメイン

サンプルプロジェクト @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.