• Qt编写安防视频监控系统24-自定义悬浮条


    一、前言

    自定义悬浮条功能集成在通用视频控件中,就是提供一个顶部的悬浮条,放一排功能按钮,有抓拍、录像、云台控制、关闭等,相当于可以直接单击对应的按钮针对该通道的视频进行操作,悬浮条的含义就是鼠标移入的时候显示出来,移除的时候自动隐藏,只在需要的时候显示出来,为视频画面尽可能多的流出空间显示,自定义悬浮条默认在顶部,也可以自行改成上下左右四个位置显示,视频控件拉伸大小的时候自动填充,有些厂家做的悬浮条是固定的,估计是因为技术上不过关才选择做成这样的,大部分会做成悬浮半透明,悬浮半透明相对来说难度大一些,通用的视频控件悬浮条部分,通过设置按钮文本集合来自动生成按钮,按钮单击自动发送对应按钮单击的信号出去,至于该按钮应该触发执行何种操作动作,这个由具体的厂家程序员去实现,毕竟每个用户要求的悬浮条功能都不一样。

    视频控件开源地址:https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo
    文件名称:videowidget

    体验地址:https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe
    文件名称:bin_video_system.zip

    二、功能特点

    1. 支持16画面切换,全屏切换等,包括1+4+6+8+9+13+16画面切换。
    2. 支持alt+enter全屏,esc退出全屏。
    3. 自定义信息框+错误框+询问框+右下角提示框。
    4. 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
    5. 云台仪表盘鼠标移上去高亮,八个方位精准识别。
    6. 底部画面工具栏(画面分割切换+截图声音等设置)移上去高亮。
    7. 可在配置文件更改左上角logo+中文软件名称+英文软件名称。
    8. 封装了百度地图,三维切换,设备点位,鼠标按下获取经纬度等。
    9. 堆栈窗体,每个窗体都是个单独的qwidget,方便编写自己的代码。
    10. 顶部鼠标右键菜单,可动态控制时间CPU+左上角面板+左下角面板+右上角面板+右下角面板的显示和隐藏,支持恢复默认布局。
    11. 工具栏可以放置多个小图标和关闭图标。
    12. 左侧右侧可拖动拉伸,并自动记忆宽高位置,重启后恢复。
    13. 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。
    14. 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
    15. 视频画面窗体支持拖曳交换,瞬间响应。
    16. 双击节点+拖曳节点+拖曳窗体交换位置,均自动更新url.txt。
    17. 支持从url.txt中加载16通道视频播放,自动记忆最后通道对应的视频,软件启动后自动打开播放。
    18. 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
    19. 集成百度地图,可以添加设备对应位置,自动生成地图,支持缩放和三维地图,提供地图风格选择,共12种风格。
    20. 视频拖动到通道窗体外自动删除视频。
    21. 鼠标右键可删除当前+所有视频,截图当前+所有视频。
    22. 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
    23. 在pro文件中可以自由开启是否加载地图。
    24. 视频播放可选四种内核自由切换,vlc+ffmpeg+easyplayer+海康sdk,均可在pro中设置。
    25. 可设置1+4+9+16画面轮询,可设置轮询间隔以及轮询码流类型等,直接在主界面底部工具栏右侧单击启动轮询按钮即可,再次单击停止轮询。
    26. 默认超过10秒钟未操作自动隐藏鼠标指针。
    27. 支持onvif搜素设备,支持任意onvif摄像机,包括但不限于海康大华宇视天地伟业华为等,支持onvif云台控制。
    28. 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,支持linux系统。

    三、效果图

    四、核心代码

    VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent)
    {
        //设置强焦点
        setFocusPolicy(Qt::StrongFocus);
        //设置支持拖放
        setAcceptDrops(true);
    
        timerCheck = new QTimer(this);
        timerCheck->setInterval(10 * 1000);
        connect(timerCheck, SIGNAL(timeout()), this, SLOT(checkVideo()));
    
        image = QImage();
    
        //顶部工具栏,默认隐藏,鼠标移入显示移除隐藏
        flowPanel = new QWidget(this);
        flowPanel->setObjectName("flowPanel");
        flowPanel->setVisible(false);
    
        //用布局顶住,左侧弹簧
        QHBoxLayout *layout = new QHBoxLayout;
        layout->setSpacing(2);
        layout->setMargin(0);
        layout->addStretch();
        flowPanel->setLayout(layout);
    
        //按钮集合名称,如果需要新增按钮则在这里增加即可
        QList<QString> btns;
        btns << "btnFlowVideo" << "btnFlowSnap" << "btnFlowSound" << "btnFlowAlarm" << "btnFlowClose";
    
        //有多种办法来设置图片,qt内置的图标+自定义的图标+图形字体
        //既可以设置图标形式,也可以直接图形字体设置文本
    #if 0
        QList<QIcon> icons;
        icons << QApplication::style()->standardIcon(QStyle::SP_ComputerIcon);
        icons << QApplication::style()->standardIcon(QStyle::SP_FileIcon);
        icons << QApplication::style()->standardIcon(QStyle::SP_DirIcon);
        icons << QApplication::style()->standardIcon(QStyle::SP_DialogOkButton);
        icons << QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton);
    #else
        QList<QChar> chars;
        chars << 0xe68d << 0xe672 << 0xe674 << 0xea36 << 0xe74c;
    
        //判断图形字体是否存在,不存在则加入
        QFont iconFont;
        QFontDatabase fontDb;
        if (!fontDb.families().contains("iconfont")) {
            int fontId = fontDb.addApplicationFont(":/image/iconfont.ttf");
            QStringList fontName = fontDb.applicationFontFamilies(fontId);
            if (fontName.count() == 0) {
                qDebug() << "load iconfont.ttf error";
            }
        }
    
        if (fontDb.families().contains("iconfont")) {
            iconFont = QFont("iconfont");
            iconFont.setPixelSize(17);
    #if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
            iconFont.setHintingPreference(QFont::PreferNoHinting);
    #endif
        }
    #endif
    
        //循环添加顶部按钮
        for (int i = 0; i < btns.count(); i++) {
            QPushButton *btn = new QPushButton;
            //绑定按钮单击事件,用来发出信号通知
            connect(btn, SIGNAL(clicked(bool)), this, SLOT(btnClicked()));
            //设置标识,用来区别按钮
            btn->setObjectName(btns.at(i));
            //设置固定宽度
            btn->setFixedWidth(20);
            //设置拉伸策略使得填充
            btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
            //设置焦点策略为无焦点,避免单击后焦点跑到按钮上
            btn->setFocusPolicy(Qt::NoFocus);
    
    #if 0
            //设置图标大小和图标
            btn->setIconSize(QSize(16, 16));
            btn->setIcon(icons.at(i));
    #else
            btn->setFont(iconFont);
            btn->setText(chars.at(i));
    #endif
    
            //将按钮加到布局中
            layout->addWidget(btn);
        }
    
        copyImage = false;
        checkLive = true;
        drawImage = true;
        fillImage = true;
    
        flowEnable = false;
        flowBgColor = "#000000";
        flowPressColor = "#5EC7D9";
    
        timeout = 20;
        borderWidth = 5;
        borderColor = "#000000";
        focusColor = "#22A3A9";
        bgText = "实时视频";
        bgImage = QImage();
    
        osd1Visible = false;
        osd1FontSize = 12;
        osd1Text = "时间";
        osd1Color = "#FF0000";
        osd1Image = QImage();
        osd1Format = OSDFormat_DateTime;
        osd1Position = OSDPosition_Right_Top;
    
        osd2Visible = false;
        osd2FontSize = 12;
        osd2Text = "通道名称";
        osd2Color = "#FF0000";
        osd2Image = QImage();
        osd2Format = OSDFormat_Text;
        osd2Position = OSDPosition_Left_Bottom;
    
        this->initFlowStyle();
    }
    
    VideoWidget::~VideoWidget()
    {
        if (timerCheck->isActive()) {
            timerCheck->stop();
        }
    
        close();
    }
    
    void VideoWidget::resizeEvent(QResizeEvent *)
    {
        //重新设置顶部工具栏的位置和宽高,可以自行设置顶部显示或者底部显示
        int height = 20;
        flowPanel->setGeometry(borderWidth, borderWidth, this->width() - (borderWidth * 2), height);
        //flowPanel->setGeometry(borderWidth, this->height() - height - borderWidth, this->width() - (borderWidth * 2), height);
    }
    
    void VideoWidget::enterEvent(QEvent *)
    {
        //这里还可以增加一个判断,是否获取了焦点的才需要显示
        //if (this->hasFocus()) {}
        if (flowEnable) {
            flowPanel->setVisible(true);
        }
    }
    
    void VideoWidget::leaveEvent(QEvent *)
    {
        if (flowEnable) {
            flowPanel->setVisible(false);
        }
    }
    
  • 相关阅读:
    统计学六:逻辑回归
    数据分析五:因子分析
    统计学四:聚类分析
    统计学三:线性回归
    统计学二:假设检验与参数估计
    统计学一:描述统计
    数据分析十:高价值用户识别
    数据分析九:互联网征信中的信用评分模型(用户APP使用行为分析)
    数据分析八:互联网征信中的信用评分模型(刷卡行为分析)
    数据分析七:数据治理
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/12159924.html
Copyright © 2020-2023  润新知