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);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM