为什么用
NanoGUI是一个支持OpenGL绘制的gui 库,也提供python的绑定(由pybind11实现)
优点
支持Mac、Windows和Linux,能够在windows平台上提供OpenGL3.x支持。
体积小
支持高清屏
使用lambda回调函数,逻辑清晰
缺点
维护不及时
功能少
缺少移动版本
总体来说,对于一般应用已经足够。
编译
从github下载:
git clone --recursive
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() {
//代码效果参考:http://www.lyjsj.net.cn/wx/art_23328.html
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 = 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::vectorvoid()] mRefreshCallbacks;
void refresh() {
for (auto const &callback : mRefreshCallbacks)
callback();
}
加入UI对象
template detail::FormWidget
addVariable(const std::string &label, const std::function[span class="hljs-title function invoke__">void(Type)> &setter, const std::function[span class="hljs-title function invoke__">Type()> &getter, bool editable = true) {
Label labelW = new Label(mWindow, label, mLabelFontName, mLabelFontSize);
//使用专用模板将数值类型转换为对应的UI对象
auto widget = new detail::FormWidget(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代码。