NanoGUI使用
为什么用
NanoGUI是一个支持OpenGL绘制的gui 库,也提供python的绑定(由pybind11实现)
优点
- 支持Mac、Windows和Linux,能够在windows平台上提供OpenGL3.x支持。
- 体积小
- 支持高清屏
- 使用lambda回调函数,逻辑清晰
缺点
- 维护不及时
- 功能少
- 缺少移动版本
总体来说,对于一般应用已经足够。
编译
从github下载:
git clone --recursive https://github.com/wjakob/nanogui.git
Mac/Linux上使用CMake构建,在Windows上生成VC solution后编译。注意windows上仅支持win64 build。vsiual studio 2015需要升级update 2 或update3(见NanoGUI::issures 201)。
C++实例
使用nanogui界面时刻直接从nanogui::screen 继承:
class App : public nanogui::Screen {
public:
App() : nanogui::Screen(Eigen::Vector2i(1024, 768), "NanoGUI Test") {
//初始化界面中第一个或多个菜单窗口
}
virtual void draw(NVGcontext *ctx) {
//更新界面
//...
Screen::draw(ctx);
}
virtual void drawContents() {
//使用OpenGL绘制窗口内容
}
virtual void Screen::drawAll() {
glClearColor(mBackground[0], mBackground[1], mBackground[2], 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
drawContents();
drawWidgets();
glfwSwapBuffers(mGLFWWindow);
}
virtual bool keyboardEvent(int key, int scancode, int action, int modifiers);
...
}
int main(int /* argc */, char ** /* argv */) {
try {
nanogui::init();
/* scoped variables */ {
nanogui::ref<App> app = new App();
app->drawAll();
app->setVisible(true);
nanogui::mainloop();
}
nanogui::shutdown();
} catch (const std::runtime_error &e) {
//...
return -1;
}
也可将其变为实例实现在view类中。
class myViewer{
public:
nanogui::Screen* screen;
void draw(){
ngui->refresh();
screen->drawWidgets();
...
}
}
初始化菜单和窗口上的控件时,需要为其清晰的指定父窗口指针和布局(Layout)。也定义lambda函数作为button等对象的回调函数。
Window *window = new Window(this, "Button demo");
window->setPosition(Vector2i(15, 15));
window->setLayout(new GroupLayout());
/* No need to store a pointer, the data structure will be automatically
freed when the parent window is deleted */
new Label(window, "Push buttons", "sans-bold");
Button *b = new Button(window, "Plain button");
b->setCallback([] { cout << "pushed!" << endl; });
b->setTooltip("short tooltip");
也可以为对象自定义回调函数,然后将其加入到系统循环的refresh()中。
std::vector<std::function<void()>> mRefreshCallbacks;
void refresh() {
for (auto const &callback : mRefreshCallbacks)
callback();
}
加入UI对象
template <typename Type> detail::FormWidget<Type> *
addVariable(const std::string &label, const std::function<void(Type)> &setter, const std::function<Type()> &getter, bool editable = true) {
Label *labelW = new Label(mWindow, label, mLabelFontName, mLabelFontSize);
//使用专用模板将数值类型转换为对应的UI对象
auto widget = new detail::FormWidget<Type>(mWindow);
//getter,setter函数加入callbacks集合
auto refresh = [widget, getter] {
Type value = getter(), current = widget->value();
if (value != current)
widget->setValue(value);
};
refresh();
widget->setCallback(setter);
widget->setEditable(editable);
widget->setFontSize(mWidgetFontSize);
Vector2i fs = widget->fixedSize();
widget->setFixedSize(Vector2i(fs.x() != 0 ? fs.x() : mFixedSize.x(),
fs.y() != 0 ? fs.y() : mFixedSize.y()));
mRefreshCallbacks.push_back(refresh);
}
Python实例
python中直接将生成的lib文件和pyd文件放到.py文件的同一目录(或Python搜索路径),实现参考实例的中的Python代码。
关于作者
NanoGUI的作者是Wenzel Jakob,洛桑联邦理工学院(EPFL)助理教授,他的研究兴趣是真实感渲染。