文章目录

  • 需求
  • 实现
  • 1. 在主界面中添加一个`treeWidget`
  • 2. 响应树形控件点击事件, 添加右侧布局
  • 3. 效果
  • 4. 改进
  • 固定右侧布局的高度
  • 多个右侧布局的切换
  • 使用UI文件
  • 第一种非常简单, 添加新文件时, 选择`Qt设计师界面类`
  • 第二种方法是如果只有ui文件, 需要一个class关联


需求

在主窗口中, 左边显示树形结构, 元素是不同类型的节点, 要求根据节点类型不同在主窗口右侧显示不同的控件内容

实现

这个功能在MFC中实现不是很方面, 但是在QT中比较简单

1. 在主界面中添加一个treeWidget

treeWidget放窗体showinfo中, 如图:

opencv窗体嵌入qt窗体 qt嵌入其他窗口_Qt


注意: 这里用一个Spacers顶着treeWidget, 有三个作用:

  1. 初始时树形控件的高度是铺满的;
  2. 如果这个窗口还要嵌入到别的窗口, 假如没有把showinfo窗体提前做布局, 那么在加入右侧的布局后, 即时用layout把左右部分布局, 拖动窗口边框时, 左右部分不会同步改变大小, 所以需要在设计ui时把showinfo窗体提前做布局;
  3. 做了布局以后, 如果没有Spacer顶着, 树形控件会充满窗体, 默认添加右侧布局后会看不到, 还需要代码中手动调整位置

2. 响应树形控件点击事件, 添加右侧布局

注意: 右侧布局的构造函数中hide(), 否则界面一加载就显示, 不满足需求
代码:

void OrgShowAllDeviceDlg::on_treeAllDevices_itemClicked(QTreeWidgetItem *item, int column)
{
    if (item->text(column) == "编码器")
    {
        _mgrEncoder->move(ui->treeAllDevices->width(), 0);
        _mgrEncoder->show();
        QLayout *layout = this->layout();
        layout->removeItem(ui->horizontalSpacer);
//        QHBoxLayout *layout = new QHBoxLayout(this);
//        layout->addWidget(ui->treeAllDevices);
        layout->addWidget(_mgrEncoder);
        setLayout(layout);
    }
}

右侧窗体如图:

opencv窗体嵌入qt窗体 qt嵌入其他窗口_树形控件_02

3. 效果

  • 打开主窗体, 加载showinfo
  • opencv窗体嵌入qt窗体 qt嵌入其他窗口_opencv窗体嵌入qt窗体_03


  • 点击shouinfo的树形控件

4. 改进

固定右侧布局的高度

现在上下拖动改变窗体的时候, 右侧布局中每行间隔变很大, 可以设定最大最小高度, 加一个layoutSpacer顶着它, 代码如下:

void OrgShowAllDeviceDlg::on_treeAllDevices_itemClicked(QTreeWidgetItem *item, int column)
{
    if (item->text(column) == "编码器")
    {
        _mgrEncoder->move(ui->treeAllDevices->width(), 0);
        _mgrEncoder->show();
        QVBoxLayout *vlayout = new QVBoxLayout(this);
        vlayout->addWidget(_mgrEncoder);
        vlayout->addStretch(1);
        QHBoxLayout *layout = (QHBoxLayout*)(this->layout());
        layout->removeItem(ui->horizontalSpacer);
        layout->addLayout(vlayout);
        setLayout(layout);
    }
}

效果:

opencv窗体嵌入qt窗体 qt嵌入其他窗口_树形控件_04

多个右侧布局的切换

比如右侧的编码器解码器的右侧布局不同, 并且要切换显示
在右侧布局中加入他们并隐藏, 这段代码在主窗体showinfo的构造函数中实现:

OrgShowAllDeviceDlg::OrgShowAllDeviceDlg(QWidget *parent) : QWidget(parent), ui(new Ui::ShowAllDevices)
{
    ui->setupUi(this);
	_mgrEncoder = new ManageEncoderDlg(this);//编码器
    _mgrEncoder->move(ui->treeAllDevices->width(), 0);
    _mgrDecoder = new ManageDecoderDlg(this);//解码器
    _mgrDecoder ->move(ui->treeAllDevices->width(), 0);

    QVBoxLayout *vlayout = new QVBoxLayout(this);
    vlayout->addWidget(_mgrEncoder);
    vlayout->addWidget(_mgrDecoder );
    vlayout->addStretch(1);
    QHBoxLayout *layout = (QHBoxLayout*)(this->layout());
    layout->removeItem(ui->horizontalSpacer);
    layout->addLayout(vlayout);
    setLayout(layout);
}

此时, 树形控件的点击代码简化如下:

void OrgShowAllDeviceDlg::on_treeAllDevices_itemClicked(QTreeWidgetItem *item, int column)
{
    if (item->text(column) == "编码器")
    {
        _mgrEncoder->show();
        _mgrDecoder ->hide();

    }
    if (item->text(column) == "解码器")
    {
        _mgrEncoder->hide();
        _mgrDecoder ->show();
    }
}

运行效果如下:

点击编码器:

opencv窗体嵌入qt窗体 qt嵌入其他窗口_嵌入窗口_05


切换到解码器:

opencv窗体嵌入qt窗体 qt嵌入其他窗口_嵌入窗口_06


切换并不会影响控件内的内容, 所以可以给控件映射sqlmodle, 进行数据库操作

使用UI文件

因为没有找到嵌入对话框的办法(MFC的做法), 所以利用布局的addWidget加入了分块的Widget
Widget的设计文件是ui文件, 需要关联一个class才能使用
关联的方式有两种

第一种非常简单, 添加新文件时, 选择Qt设计师界面类

![在这里插入图片描述]()
界面模板选择`Widget`
![在这里插入图片描述]()
![在这里插入图片描述]()
输入类名和界面文件名下一步, 完成

第二种方法是如果只有ui文件, 需要一个class关联

1. 项目中添加该ui文件, **编译项目**
2. 成功编译后, 在构建目录下生成`ui_ui文件名.h`
3.  新建一个c++类, 父类选择`QtWidget`
 ![在这里插入图片描述]()
 4. 参照Qt默认的代码生成
 	1. 在`.h`中增加:
namespace Ui {
class ui文件名;
}
增加:
private:
   Ui::OrgMainWindow *ui;
2. 在.cpp中增加:
OrgMainWindow::OrgMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ui文件名)
{
    ui->setupUi(this);

    _showAllDeviceDlg = new OrgShowAllDeviceDlg(this);
    on_actShowAllDevice_triggered();
}

OrgMainWindow::~OrgMainWindow()
{
    delete ui;
}