问题:
最近写了个项目,需要播放视频并在视频上做标记框去完成一些功能
因为视频播放使用了VLC-qt
的库,封装好的窗口控件
没办法直接在该视频窗口上绘图(也许可以?)
出于不想动别人写好的库的想法,想着在视频窗口上加一个透明蒙版-即一个透明窗口,在透明窗口上进行绘图操作
实现:
这个是业务窗口逻辑
void Dialog::on_select_videowindow_clicked()
{
//获取本窗口中视频窗口的位置,并转换为相对屏幕坐标
QPoint p = ui->video->mapToGlobal(QPoint(0, 0));
QSize size = ui->video->size();
//当没创建新创口界面时,new一个出来
if(m_screen == NULL)
{
m_screen = new Screen(0,p.x(),p.y(),size.width(),size.height());
}
else
{
//设置回初始状态
m_screen->init(true);
}
m_screen->show();
}
这个是透明蒙版的构造函数
Screen::Screen(QWidget *parent, int x, int y, int w, int h)
: QWidget(parent),
m_widthInfoRect(QRectF(0, 0, 0, 0)),
m_control(NULL)
{
setWindowFlags(Qt::FramelessWindowHint);//设置无标题栏
setMouseTracking(true);//捕获鼠标事件
setAttribute(Qt::WA_QuitOnClose,false);//设置本窗口不关联程序退出
setAttribute(Qt::WA_TransparentForMouseEvents, false);//设置鼠标不穿透
setAttribute(Qt::WA_TranslucentBackground, true);//设置窗口透明背景
setWindowFlag(Qt::WindowStaysOnTopHint);//设置本窗口处在顶层
//初始化本窗口参数
init(true);
}
分析:
如上,获取了视频窗口的位置及大小,并将透明窗口覆盖在video窗口上
然后重写了Screen的部分鼠标事件及绘图事件,实现标记功能
但实际操作发现,当鼠标点击透明窗口时无法触发该透明窗口的鼠标事件,即鼠标穿透了,点击到了视频窗口上。
明明已经设置了WA_TransparentForMouseEvents
属性为false,但鼠标依然穿透了。
即setAttribute(Qt::WA_TransparentForMouseEvents, false)
未生效
重新实现:
经过一段时间的研究,将代码修改后
重写paintEvent
事件解决了这个问题
如下:
Screen::Screen(QWidget *parent, int x, int y, int w, int h)
: QWidget(parent),
m_widthInfoRect(QRectF(0, 0, 0, 0)),
m_control(NULL)
{
setWindowFlags(Qt::FramelessWindowHint);//设置无标题栏
setMouseTracking(true);//捕获鼠标事件
m_pixmap = QPixmap(w,h);
//全局路径的初始化,一个全屏闭合回路
m_globalPath.lineTo(m_pixmap.width(), 0);
m_globalPath.lineTo(m_pixmap.width(), m_pixmap.height());
m_globalPath.lineTo(0, m_pixmap.height());
m_globalPath.lineTo(0, 0);
setAttribute(Qt::WA_QuitOnClose,false);//设置本窗口不关联程序退出
// setAttribute(Qt::WA_TransparentForMouseEvents, false);//设置鼠标不穿透
setAttribute(Qt::WA_TranslucentBackground, true);//设置窗口透明背景
setWindowFlag(Qt::WindowStaysOnTopHint);//设置本窗口处在顶层
//初始化本窗口参数
init(true);
}
void Screen::paintEvent(QPaintEvent *e)
{
//解决鼠标穿透问题
Q_UNUSED(e);
QPainter paint(this);
paint.setPen(Qt::transparent);
paint.setBrush(QColor(0, 0, 0, 1));
//关键是这一步 绘制一个全局的路径
paint.drawPath(m_globalPath);
//其他绘图事件
}
可以看到透明窗口上再绘制一个透明全屏幕路径后完美的解决了这个问题
发现设不设置Qt::WA_TransparentForMouseEvents
这个属性好像没有什么影响,也许默认就是false。
效果如下:
结论:
猜测:就是因为当前窗口上什么都没有只有一个透明背景导致鼠标穿透了,再窗口上再绘制透明图片(即让窗口上有东西)即可解决这个问题。文章来源:https://www.toymoban.com/news/detail-764294.html
但具体底层机制不明,还得深入学习下。
不过就目前来讲,应该够用了。文章来源地址https://www.toymoban.com/news/detail-764294.html
到了这里,关于Qt透明窗口鼠标穿透问题及解决办法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!