NanoGUI使用

为什么用

NanoGUI是一个支持OpenGL绘制的gui 库,也提供python的绑定(由pybind11实现)

  • 优点

    • 支持Mac、Windows和Linux,能够在windows平台上提供OpenGL3.x支持。
    • 体积小
    • 支持高清屏
    • 使用lambda回调函数,逻辑清晰
  • 缺点

    • 维护不及时
    • 功能少
    • 缺少移动版本

总体来说,对于一般应用已经足够。

编译

从github下载:

  1. 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 继承:

  1. class App : public nanogui::Screen {
  2. public:
  3. App() : nanogui::Screen(Eigen::Vector2i(1024, 768), "NanoGUI Test") {
  4. //初始化界面中第一个或多个菜单窗口
  5. }
  6. virtual void draw(NVGcontext *ctx) {
  7. //更新界面
  8. //...
  9. Screen::draw(ctx);
  10. }
  11. virtual void drawContents() {
  12. //使用OpenGL绘制窗口内容
  13. }
  14. virtual void Screen::drawAll() {
  15. glClearColor(mBackground[0], mBackground[1], mBackground[2], 1.0f);
  16. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  17. drawContents();
  18. drawWidgets();
  19. glfwSwapBuffers(mGLFWWindow);
  20. }
  21. virtual bool keyboardEvent(int key, int scancode, int action, int modifiers);
  22. ...
  23. }
  24. int main(int /* argc */, char ** /* argv */) {
  25. try {
  26. nanogui::init();
  27. /* scoped variables */ {
  28. nanogui::ref<App> app = new App();
  29. app->drawAll();
  30. app->setVisible(true);
  31. nanogui::mainloop();
  32. }
  33. nanogui::shutdown();
  34. } catch (const std::runtime_error &e) {
  35. //...
  36. return -1;
  37. }

也可将其变为实例实现在view类中。

  1. class myViewer{
  2. public:
  3. nanogui::Screen* screen;
  4. void draw(){
  5. ngui->refresh();
  6. screen->drawWidgets();
  7. ...
  8. }
  9. }

初始化菜单和窗口上的控件时,需要为其清晰的指定父窗口指针和布局(Layout)。也定义lambda函数作为button等对象的回调函数。

  1. Window *window = new Window(this, "Button demo");
  2. window->setPosition(Vector2i(15, 15));
  3. window->setLayout(new GroupLayout());
  4. /* No need to store a pointer, the data structure will be automatically
  5. freed when the parent window is deleted */
  6. new Label(window, "Push buttons", "sans-bold");
  7. Button *b = new Button(window, "Plain button");
  8. b->setCallback([] { cout << "pushed!" << endl; });
  9. b->setTooltip("short tooltip");

img

也可以为对象自定义回调函数,然后将其加入到系统循环的refresh()中。

  1. std::vector<std::function<void()>> mRefreshCallbacks;
  2. void refresh() {
  3. for (auto const &callback : mRefreshCallbacks)
  4. callback();
  5. }

加入UI对象

  1. template <typename Type> detail::FormWidget<Type> *
  2. addVariable(const std::string &label, const std::function<void(Type)> &setter, const std::function<Type()> &getter, bool editable = true) {
  3. Label *labelW = new Label(mWindow, label, mLabelFontName, mLabelFontSize);
  4. //使用专用模板将数值类型转换为对应的UI对象
  5. auto widget = new detail::FormWidget<Type>(mWindow);
  6. //getter,setter函数加入callbacks集合
  7. auto refresh = [widget, getter] {
  8. Type value = getter(), current = widget->value();
  9. if (value != current)
  10. widget->setValue(value);
  11. };
  12. refresh();
  13. widget->setCallback(setter);
  14. widget->setEditable(editable);
  15. widget->setFontSize(mWidgetFontSize);
  16. Vector2i fs = widget->fixedSize();
  17. widget->setFixedSize(Vector2i(fs.x() != 0 ? fs.x() : mFixedSize.x(),
  18. fs.y() != 0 ? fs.y() : mFixedSize.y()));
  19. mRefreshCallbacks.push_back(refresh);
  20. }

Python实例

python中直接将生成的lib文件和pyd文件放到.py文件的同一目录(或Python搜索路径),实现参考实例的中的Python代码。

关于作者

NanoGUI的作者是Wenzel Jakob,洛桑联邦理工学院(EPFL)助理教授,他的研究兴趣是真实感渲染。
Wenzel

posted @ 2017-10-15 15:07  combust  阅读(3810)  评论(0编辑  收藏  举报