文章目录
需求
在主窗口中, 左边显示树形结构, 元素是不同类型的节点, 要求根据节点类型不同在主窗口右侧显示不同的控件内容
实现
这个功能在MFC中实现不是很方面, 但是在QT中比较简单
1. 在主界面中添加一个treeWidget
把treeWidget
放窗体showinfo
中, 如图:
注意: 这里用一个Spacers
顶着treeWidget
, 有三个作用:
- 初始时树形控件的高度是铺满的;
- 如果这个窗口还要嵌入到别的窗口, 假如没有把
showinfo
窗体提前做布局, 那么在加入右侧的布局后, 即时用layout
把左右部分布局, 拖动窗口边框时, 左右部分不会同步改变大小, 所以需要在设计ui时把showinfo
窗体提前做布局; - 做了布局以后, 如果没有
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);
}
}
右侧窗体如图:
3. 效果
- 打开主窗体, 加载
showinfo
- 点击
shouinfo
的树形控件
4. 改进
固定右侧布局的高度
现在上下拖动改变窗体的时候, 右侧布局中每行间隔变很大, 可以设定最大最小高度, 加一个layout
和Spacer
顶着它, 代码如下:
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);
}
}
效果:
多个右侧布局的切换
比如右侧的编码器
和解码器
的右侧布局不同, 并且要切换显示
在右侧布局中加入他们并隐藏, 这段代码在主窗体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();
}
}
运行效果如下:
点击编码器:
切换到解码器:
切换并不会影响控件内的内容, 所以可以给控件映射sqlmodle
, 进行数据库操作
使用UI文件
因为没有找到嵌入对话框的办法(MFC的做法), 所以利用布局的addWidget
加入了分块的Widget
Widget的设计文件是ui文件, 需要关联一个class才能使用
关联的方式有两种
第一种非常简单, 添加新文件时, 选择Qt设计师界面类
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019081610542340.png)
界面模板选择`Widget`
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190816105449137.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190816105507158.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Jsd2lubmVy,size_16,color_FFFFFF,t_70)
输入类名和界面文件名下一步, 完成
第二种方法是如果只有ui文件, 需要一个class关联
1. 项目中添加该ui文件, **编译项目**
2. 成功编译后, 在构建目录下生成`ui_ui文件名.h`
3. 新建一个c++类, 父类选择`QtWidget`
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190816105857633.png)
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;
}