在QtCreator中可以显示多个页面,它通过左边的按钮进行页面切换,这里就扩展核心插件的页面接口,使它可以通过插件方式添加页面,并通过左侧的按键进行页面切换。

1、页面接口

1.1、FancyPage页面类

创建 FancyPage 类型,头文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#ifndef FANCYPAGE_H
#define FANCYPAGE_H

#include <QObject>

#include "core_global.h"

#include <QPushButton>

namespace Core {

class CORE_EXPORT FancyPage : public QObject
{
Q_OBJECT
public:
explicit FancyPage(QObject *parent = nullptr);

QPushButton *pageButton();
QWidget *pageWidget();

private:
QPushButton *m_pageButton;
QWidget *m_pageWidget;

protected:
void setButtonName(const QString &text);
void setWidget(QWidget *widget);

signals:

};

}

#endif // FANCYPAGE_H

这个类用于创建其他页面,它包含一个按钮和一个Widget控件,按钮显示在主页面的左侧,用于点击是切换页面。

1.2、实例化页面

创建其他页面继承自FancyPage类,如下创建了两个页面:

  • Home页面
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef HOMEPAGE_H
#define HOMEPAGE_H

#include <coreplugin/fancypage.h>

class HomePage : public Core::FancyPage
{
public:
HomePage();
};

#endif // HOMEPAGE_H

这个页面继承FancyPage,在该类中实现Home页面的窗体控件。

  • Tool页面
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef TOOLPAGE_H
#define TOOLPAGE_H

#include <coreplugin/fancypage.h>

class ToolPage : public Core::FancyPage
{
public:
ToolPage();
};

#endif // TOOLPAGE_H

Tool页面也是一样继承FancyPage,用于创建Tool页面窗体。

2、加载页面

上面两个创建好的页面,需要添加到主界面布局中,主要通过以下方式进行加载:

  • 先在插件初始化时候把页面对象通过addObject注册到插件管理器的Object pool中,其官方参考文档说明:https://doc.qt.io/qtcreator-extending/pluginmanager.html
  • 然后在Coreplugin插件的extensioninitized中通过allObjects获取所有的object对象并转换为fancyPage,再获取其按钮和Widget控件添加到主界面的layout中;
2.1、创建页面添加到插件管理器

这里直接在Coreplugin的初始化时候添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
bool CorePlugin::initialize(const QStringList &, QString *)
{

......

//home page load
ExtensionSystem::PluginManager::addObject(new HomePage());

//tool page load
ExtensionSystem::PluginManager::addObject(new ToolPage());

return true;
}
2.2、在主界面加载

(1) 先在主界面添加布局管理器用于整个界面的布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bool CorePlugin::initialize(const QStringList &, QString *)
{

......

//add page layout
QWidget *mainWidget = new QWidget(mwin);
QHBoxLayout *mainLayout = new QHBoxLayout(mainWidget);
mainWidget->setLayout(mainLayout);
m_pageButtons = new QButtonGroup(mainWidget);
m_pageStacks = new QStackedWidget(mainWidget);
m_buttonLayout = new QVBoxLayout(mainWidget);
m_buttonLayout->setContentsMargins(0,0,0,0);
m_buttonLayout->setSpacing(0);

mainLayout->addLayout(m_buttonLayout);
mainLayout->addWidget(m_pageStacks);
mainLayout->setStretch(0,2);
mainLayout->setStretch(1,8);

mwin->setCentralWidget(mainWidget);
mwin->setMinimumSize(800,600);

m_mainWindow.reset(mwin);

......
}

上述布局是把所有页面切换按键放置在左侧一列,所有的页面放置在Stack控件中布局在右侧,这样在左侧按钮按下是显示不同页面效果。 (2) 加载所有的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void CorePlugin::extensionsInitialized()
{
QVector<QObject*> pagesObject = ExtensionSystem::PluginManager::allObjects();

QPushButton *homeBtn = nullptr;

for(QObject* objPage:pagesObject){
FancyPage *page = qobject_cast<FancyPage*>(objPage);

if(!page->pageWidget()){
continue;
}

qDebug()<<" pages button add:"<<page->pageButton()->text();

if(page->pageButton()->objectName() == "Home"){
homeBtn = page->pageButton();
}

m_pageButtons->addButton(page->pageButton());
m_buttonLayout->addWidget(page->pageButton());
m_pageStacks->addWidget(page->pageWidget());

connect(page->pageButton(),&QPushButton::clicked,[=](){
m_pageStacks->setCurrentWidget(page->pageWidget());
page->pageButton()->setChecked(true);
});

//remove from plugin pool
connect(this, &IPlugin::destroyed, this, [=]{
ExtensionSystem::PluginManager::removeObject(objPage);
});
}

//init page
homeBtn->setChecked(true);

m_buttonLayout->addStretch();

}

以上是利用Qt插件框架系统的机制,可以从plugin pool中获取所有的之前通过addObject注册的Object对象,转换为实际的页面类型FancyPage后即可获取到对象的按键和Widget控件。

2.3、最后效果如下