• 1983阅读
  • 2回复

Qt开源作品42-视频监控布局 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 2021-11-29
## 一、前言
自从做监控系统以来,就一直有打算将这个功能独立出来一个类,这样的话很多系统用到此类布局切换,通用这个类就行,而且后期此布局会增加其他异形布局,甚至按照16:9之类的比例生成布局,之前此功能直接写在功能界面UI类中,不方便拓展,好多个系统用到此功能,一旦增加了64布局、128通道布局等,都需要做对应更改,烦不胜烦,所以务必将此功能彻底剥离出来,为后面的256通道、异形布局、自定义布局打基础。

通道切换在视频监控系统中是最基础的必备功能,一般都会提供1通道、4通道、6通道、8通道、9通道、16通道这几个通道切换,可能做得比较好的还会提供24通道、32通道、64通道的,这个可能对电脑的配置就有一定要求了,一般来说,超过9个通道实时显示视频流,基本上会采用子码流来显示,如果都采用主码流,电脑压力非常巨大,CPU占用很高,内存也高,不过现在的电脑配置越来越高,基本上四千多块钱的台式机,配置已经非常好了,显示个16个通道的实时视频毫无压力。

Qt中的布局非常好用,尤其是QGridLayout表格布局,可以指定行列放置控件,而且还可以设置每个控件占用几行几列,这样就可以完美的实现各种通道布局了。比如6通道,可以设置通道1占用两行两列,其他通道各站一行一列即可,当切换布局的时候,其他隐藏即可。

## 二、主要功能
1. 将所有通道切换处理全部集中到一个类。
2. 通用整数倍数布局切换函数,可方便拓展到100、255通道等。
3. 通用异形布局切换函数,可以参考进行自定义异形布局。
4. 通道布局切换发出信号通知。
5. 可控每种布局切换菜单是否启用。
6. 支持自定义子菜单布局内容。
7. 支持设置对应的菜单标识比如默认的通道字样改成设备。

## 三、效果图




## 四、开源主页
- **以上作品完整源码下载都在开源主页,会持续不断更新作品数量和质量,欢迎各位关注。**
- **本开源项目已经成功升级到V2.0版本,分门别类,图文并茂,保你爽到爆。**
- **Qt开源武林秘籍开发经验,看完学完,20K起薪,没有找我!**

1. 国内站点:[https://gitee.com/feiyangqingyun/QWidgetDemo](https://gitee.com/feiyangqingyun/QWidgetDemo)
2. 国际站点:[https://github.com/feiyangqingyun/QWidgetDemo](https://github.com/feiyangqingyun/QWidgetDemo)
3. 开源秘籍:[https://gitee.com/feiyangqingyun/qtkaifajingyan](https://gitee.com/feiyangqingyun/qtkaifajingyan)
3. 个人主页:[https://qtchina.blog.csdn.net/](https://qtchina.blog.csdn.net/)
4. 知乎主页:[https://www.zhihu.com/people/feiyangqingyun/](https://www.zhihu.com/people/feiyangqingyun/)

## 五、核心代码
```cpp
void VideoBox::change_video_normal(int index, int flag)
{
    //首先隐藏所有通道
    hide_video_all();
    int count = 0;
    int row = 0;
    int column = 0;

    //行列数一致的比如 2*2 3*4 4*4 5*5 等可以直接套用通用的公式
    //按照这个函数还可以非常容易的拓展出 10*10 16*16=256 通道界面
    for (int i = 0; i < videoCount; i++) {
        if (i >= index) {
            //添加到对应布局并设置可见
            gridLayout->addWidget(widgets.at(i), row, column);
            widgets.at(i)->setVisible(true);

            count++;
            column++;
            if (column == flag) {
                row++;
                column = 0;
            }
        }

        if (count == (flag * flag)) {
            break;
        }
    }
}

void VideoBox::change_video_custom(int index, int type)
{
    //从开始索引开始往后衍生多少个通道
    QList<int> indexs;
    for (int i = index; i < (index + type); ++i) {
        indexs << i;
    }

    if (type == 6) {
        change_video_6(indexs);
    } else if (type == 8) {
        change_video_8(indexs);
    } else if (type == 13) {
        change_video_13(indexs);
    }
}

void VideoBox::change_video_6(const QList<int> &indexs)
{
    //过滤防止索引越界
    if (indexs.count() < 6) {
        return;
    }

    //首先隐藏所有通道
    hide_video_all();
    //挨个重新添加到布局
    gridLayout->addWidget(widgets.at(indexs.at(0)), 0, 0, 2, 2);
    gridLayout->addWidget(widgets.at(indexs.at(1)), 0, 2, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(2)), 1, 2, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(3)), 2, 2, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(4)), 2, 1, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(5)), 2, 0, 1, 1);
    //设置通道控件可见
    for (int i = indexs.first(); i <= indexs.last(); i++) {
        widgets.at(i)->setVisible(true);
    }
}

void VideoBox::change_video_8(const QList<int> &indexs)
{
    //过滤防止索引越界
    if (indexs.count() < 8) {
        return;
    }

    //首先隐藏所有通道
    hide_video_all();
    //挨个重新添加到布局
    gridLayout->addWidget(widgets.at(indexs.at(0)), 0, 0, 3, 3);
    gridLayout->addWidget(widgets.at(indexs.at(1)), 0, 3, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(2)), 1, 3, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(3)), 2, 3, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(4)), 3, 3, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(5)), 3, 2, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(6)), 3, 1, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(7)), 3, 0, 1, 1);
    //设置通道控件可见
    for (int i = indexs.first(); i <= indexs.last(); i++) {
        widgets.at(i)->setVisible(true);
    }
}

void VideoBox::change_video_13(const QList<int> &indexs)
{
    //过滤防止索引越界
    if (indexs.count() < 13) {
        return;
    }

    //首先隐藏所有通道
    hide_video_all();
    //挨个重新添加到布局
    gridLayout->addWidget(widgets.at(indexs.at(0)), 0, 0, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(1)), 0, 1, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(2)), 0, 2, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(3)), 0, 3, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(4)), 1, 0, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(5)), 2, 0, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(6)), 1, 1, 2, 2);
    gridLayout->addWidget(widgets.at(indexs.at(7)), 1, 3, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(8)), 2, 3, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(9)), 3, 0, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(10)), 3, 1, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(11)), 3, 2, 1, 1);
    gridLayout->addWidget(widgets.at(indexs.at(12)), 3, 3, 1, 1);
    //设置通道控件可见
    for (int i = indexs.first(); i <= indexs.last(); i++) {
        widgets.at(i)->setVisible(true);
    }
}

void VideoBox::change_video_1(int index)
{
    //首先隐藏所有通道
    hide_video_all();
    //添加通道到布局
    gridLayout->addWidget(widgets.at(index), 0, 0);
    //设置可见
    widgets.at(index)->setVisible(true);
}

void VideoBox::change_video_4(int index)
{
    change_video_normal(index, 2);
}

void VideoBox::change_video_6(int index)
{
    change_video_custom(index, 6);
}

void VideoBox::change_video_8(int index)
{
    change_video_custom(index, 8);
}

void VideoBox::change_video_9(int index)
{
    change_video_normal(index, 3);
}

void VideoBox::change_video_13(int index)
{
    change_video_custom(index, 13);
}

void VideoBox::change_video_16(int index)
{
    change_video_normal(index, 4);
}

void VideoBox::change_video_25(int index)
{
    change_video_normal(index, 5);
}

void VideoBox::change_video_36(int index)
{
    change_video_normal(index, 6);
}

void VideoBox::change_video_64(int index)
{
    change_video_normal(index, 8);
}
```
4条评分好评度+1贡献值+1金钱+10威望+1
20091001753 好评度 +1 - 2021-11-30
20091001753 贡献值 +1 - 2021-11-30
20091001753 威望 +1 - 2021-11-30
20091001753 金钱 +10 - 2021-11-30
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线uidab

只看该作者 1楼 发表于: 2021-11-29
国企绝对不会给你20K, 哈哈哈
有时候为了工作直接获得答案,而我却失去了思考的乐趣!


飘啊飘,何时能安居!
离线liudianwu

只看该作者 2楼 发表于: 2021-11-29
回 uidab 的帖子
uidab:国企绝对不会给你20K, 哈哈哈 (2021-11-29 09:00) 

加上其他福利和年终奖,应该可以
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个