You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测QWebEngineView中Discord组件的打开与关闭状态?

解决WidgetBot组件关闭状态下阻挡点击的问题

核心问题在于QWebEngineView会占据分配的整个布局空间,即便WidgetBot组件处于关闭状态,也会拦截鼠标事件。要解决这个问题,需要监听WidgetBot组件的开闭状态,再动态调整QWebEngineView的尺寸或鼠标穿透属性。

方法:利用WidgetBot的JavaScript API与Qt交互

WidgetBot的Crate组件提供了open和close原生事件,我们可以在网页中监听这些事件,通过Qt的QWebChannel将状态传递到Qt端,进而调整组件行为。

步骤1:创建状态通知类

定义一个Qt对象作为JS与Qt的交互桥梁,用于接收Web端传来的状态:

#include <QObject>

class WidgetBotStateNotifier : public QObject
{
    Q_OBJECT
public slots:
    // 接收Web端的状态变更
    void onStateChanged(bool isOpen) {
        emit stateChanged(isOpen);
    }
signals:
    // 向Qt内部发送状态变化信号
    void stateChanged(bool isOpen);
};

步骤2:修改DiscordWidget实现

更新DiscordWidget的构造函数,配置QWebChannel并修改加载的HTML内容,添加事件监听逻辑:

//discordwidget.h
#include <QtWebEngineWidgets>
#include <QWebChannel>
#include "widgetbotstatenotifier.h"

class DiscordWidget : public QWebEngineView 
{
    Q_OBJECT

public:
    DiscordWidget(QWidget* parent = 0) : QWebEngineView(parent)
    {    
        this->page()->setBackgroundColor(Qt::transparent);   

        // 创建状态通知器并绑定处理逻辑
        WidgetBotStateNotifier* notifier = new WidgetBotStateNotifier(this);
        connect(notifier, &WidgetBotStateNotifier::stateChanged, this, [this](bool isOpen) {
            // 关闭时允许鼠标穿透到下方组件,打开时恢复拦截
            this->setAttribute(Qt::WA_TransparentForMouseEvents, !isOpen);
            
            // 动态调整组件最大尺寸
            if (isOpen) {
                this->setMaximumSize(400, 600); // 组件展开后的尺寸
            } else {
                this->setMaximumSize(60, 60); // 组件关闭后的按钮尺寸
            }
            
            // 更新布局,让网格布局重新计算空间分配
            this->updateGeometry();
            if (this->parentWidget() && this->parentWidget()->layout()) {
                this->parentWidget()->layout()->update();
            }
        });

        // 配置QWebChannel,注册交互对象
        QWebChannel* channel = new QWebChannel(this);
        channel->registerObject("widgetBotNotifier", notifier);
        this->page()->setWebChannel(channel);

        // 加载带事件监听的HTML内容
        this->page()->setHtml(R"(    
            <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
            <script src='https://cdn.jsdelivr.net/npm/@widgetbot/crate@3' async defer></script>
            <script>
                document.addEventListener('DOMContentLoaded', () => {
                    const crate = new Crate({
                        server: '', // 替换为你的Discord服务器ID
                        channel: '' // 替换为你的Discord频道ID
                    });
                    
                    // 初始化QWebChannel并绑定WidgetBot的开闭事件
                    new QWebChannel(qt.webChannelTransport, function(channel) {
                        const notifier = channel.objects.widgetBotNotifier;
                        crate.on('open', () => notifier.onStateChanged(true));
                        crate.on('close', () => notifier.onStateChanged(false));
                    });
                });
            </script>    
        )");
    } 
};

补充说明

  1. 鼠标穿透属性:Qt::WA_TransparentForMouseEvents是解决阻挡问题的关键,它能让关闭状态的QWebEngineView忽略所有鼠标事件,点击直接传递到下方组件。
  2. 尺寸调整:配合最大尺寸设置,可让组件在关闭时仅占据极小空间,避免浪费布局区域。
  3. 替代方案:若不想使用QWebChannel,也可在JS中通过console.log输出状态,然后Qt端重写QWebEnginePage::javaScriptConsoleMessage方法捕获日志并解析状态,但QWebChannel是更规范的交互方式。

内容的提问来源于stack exchange,提问作者Cesar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:06:14