• 580阅读
  • 0回复

Qt音视频开发33-vlc和mpv打开后鼠标打圈圈问题的解决 [复制链接]

上一主题 下一主题
离线liudianwu
 

只看楼主 倒序阅读 楼主  发表于: 2023-04-02

## 一、前言
如果采用的vlc句柄模式,如果鼠标停留在句柄控件中会发现在打开后鼠标打圈圈,mpv句柄模式是在关闭后鼠标打圈圈,这两者真是一前一后,这种给人的体验其实很不友好的,播放开始后或者播放完成后鼠标指针居然变成了繁忙,但是当你将鼠标位置从句柄控件中移到外面的时候,他又会自动恢复,所以需要有个机制主动恢复鼠标形状,一开始想的办法是模拟移动鼠标位置移来移去,当有几十个上百个通道的时候,这样移来移去看起来就是很傻的感觉,后面想了个办法用系统的api强制将鼠标指针恢复,测试下来还是有点怪怪的,后面发现Qt本身就内置了鼠标指针复位的函数先 qApp->setOverrideCursor(Qt::ArrowCursor) 后 qApp->restoreOverrideCursor(),就用它了。

思路这下子就清晰了,在播放打开和完成的信号中,执行两行代码就行,为了使用起来更简便,单独开辟了一个VideoTask线程处理这个事情,这样可以过滤频繁的触发,比如64个通道同时打开,其实只需要最后那个打开完成复位下就行,并不需要执行64次,而且线程中还可以控制延时执行,比如传入某个指令延时300ms再去执行,测试过程中也是这个情况,立即执行很可能还是不会生效,而是要延时一段时间执行才能完美生效。

## 二、效果图



## 三、体验地址
1. 国内站点:[https://gitee.com/feiyangqingyun](https://gitee.com/feiyangqingyun)
2. 国际站点:[https://github.com/feiyangqingyun](https://github.com/feiyangqingyun)
3. 个人作品:[https://blog.csdn.net/feiyangqingyun/article/details/97565652](https://blog.csdn.net/feiyangqingyun/article/details/97565652)
4. 体验地址:[https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g](https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g) 提取码:01jf 文件名:bin_video_demo/bin_linux_video。

## 四、相关代码
```cpp
void VideoTask::run()
{
    while (!stopped) {
        if (times.count() > 0) {
            mutex.lock();
            QDateTime time = times.first();
            QString type = types.first();
            QString para = paras.first();
            mutex.unlock();

            QDateTime now = QDateTime::currentDateTime();
            int offset = time.msecsTo(now);
            if (offset >= 500) {
                //qDebug() << TIMEMS << offset << type << para;
                if (type == "renameFile") {
                    VideoHelper::renameFile(para);
                } else if (type == "resetCursor") {
                    //必须在主线程执行
                    QMetaObject::invokeMethod(this, "resetCursor");
                }

                //执行完成任务后从队列中移除
                mutex.lock();
                times.removeFirst();
                types.removeFirst();
                paras.removeFirst();
                mutex.unlock();
            }
        }

        msleep(100);
    }

    stopped = false;
}

void VideoTask::resetCursor()
{
    VideoHelper::resetCursor();
}

void VideoTask::append(const QString &type, const QString &para)
{
    //复位光标只需要一次
    if (type == "resetCursor" && types.contains("resetCursor")) {
        return;
    }

    mutex.lock();
    times << QDateTime::currentDateTime();
    types << type;
    paras << para;
    mutex.unlock();
}

void VideoWidget::receivePlayStart(int time)
{
    //vlc内核句柄模式下在打开后鼠标打圈圈需要复位下
    if (widgetPara.videoMode == VideoMode_Hwnd) {
        VideoTask::Instance()->append("resetCursor", "");
    }

    //句柄模式下句柄控件要禁用绘制防止闪烁(尤其是海康大华厂家sdk内核)
    if (widgetPara.videoMode == VideoMode_Hwnd && videoPara.videoCore != VideoCore_Qtav) {
        hwndWidget->setUpdatesEnabled(false);
    }

    //执行父类处理
    AbstractVideoWidget::receivePlayStart(time);

    //设置默认声音大小和静音状态(测试发现Qt5.8以下的音频类需要延时设置才行)
    if (videoPara.videoCore == VideoCore_FFmpeg) {
        this->setMuted(widgetPara.soundMuted);
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
        this->revolume();
#else
        QTimer::singleShot(200, this, SLOT(revolume()));
#endif
    } else {
        this->revolume();
    }
}

void VideoWidget::receivePlayFinsh()
{
    //mpv内核句柄模式下在关闭后鼠标打圈圈需要复位下
    if (widgetPara.videoMode == VideoMode_Hwnd) {
        VideoTask::Instance()->append("resetCursor", "");
    }

    //句柄模式下句柄控件要禁用绘制防止闪烁(尤其是海康大华厂家sdk内核)
    if (widgetPara.videoMode == VideoMode_Hwnd && videoPara.videoCore != VideoCore_Qtav) {
        hwndWidget->setUpdatesEnabled(true);
    }

    //执行父类处理
    AbstractVideoWidget::receivePlayFinsh();
}
```

4条评分好评度+1贡献值+1金钱+10威望+1
20091001753 好评度 +1 - 2023-04-02
20091001753 贡献值 +1 - 2023-04-02
20091001753 威望 +1 - 2023-04-02
20091001753 金钱 +10 - 2023-04-02
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个