文章目錄
需求
在主窗口中, 左邊顯示樹形結構, 元素是不同類型的節點, 要求根據節點類型不同在主窗口右側顯示不同的控件內容
實現
這個功能在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;
}