想看一下在Ubuntu系统中是不是GTK和GLUT是否可以相互协作,经过初次的测试,得出的结论算是可行的,在下面也将分享C源代码,供大家参考。
在以下demo中,我们可以点击由GTK创建的按钮然后弹出用GLUT创建的窗口。由于GTK和GLUT是两个完全独立的库,两者均含有各自的消息循环(也就是通常所说的runloop),因此当我们点击按钮弹出GLUT窗口的时候,其实相应的都是GLUT的消息循环,GTK此时处于冻结状态。只有当我们将GLUT窗口关闭之后,GTK窗口才会被再次激活,侦听消息。
跟以往一样,这里先给出本次demo所需的shell文件内容,便于编译构建。 clang main.c -std=gnu11 -fblocks -lBlocksRuntime -lglut -lGL -I/usr/include/glib-2.0/ -I/usr/include/atk-1.0/ -I/usr/include/gdk-pixbuf-2.0/ -I/usr/include/cairo/ -I/usr/include/pango-1.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -I/usr/include/gtk-3.0/ -L/usr/lib/x86_64-linux-gnu/ -lgtk-3 -lgobject-2.0 -lpangocairo-1.0 -lgio-2.0 -latk-1.0 -lgdk-3 -lglib-2.0-o gtk-glut
同样,如果各位使用的是GCC编译器,那么将上述的clang变为gcc,同时删除-fblocks -lBlocksRuntime这两个命令行选项。
下面则是C源代码: #include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <stdnoreturn.h> #include <stdatomic.h> #include <string.h> #include <assert.h> #include <gtk/gtk.h> #include <glib/gprintf.h> #include <GL/freeglut.h> #include <GL/gl.h> #ifndef var #define var __auto_type #endif static const GLfloat sRectVertices[] = { // top left -0.4f, 0.4f, // bottom left -0.4f, -0.4f, // top right 0.4f, 0.4f, // bottom right 0.4f, -0.4f }; static const GLfloat sTriangleVertices[] = { // top center 0.0f, 0.4f, // bottom left -0.4f, -0.4f, // bottom right 0.4f, -0.4f }; static const GLfloat sColors[] = { // red 1.0f, 0.0f, 0.0f, 1.0f, // green 0.0f, 1.0f, 0.0f, 1.0f, // blue 0.0f, 0.0f, 1.0f, 1.0f, // white 1.0f, 1.0f, 1.0f, 1.0f }; static int sRotAngle = 0; static void TimerHandler(int value); static void RenderHandler(void) { // 以50FPS的帧率进行刷新 glutTimerFunc(20, TimerHandler, 0); glClear(GL_COLOR_BUFFER_BIT); // Draw rectangle glVertexPointer(2, GL_FLOAT, 0, sRectVertices); glColorPointer(4, GL_FLOAT, 0, sColors); glLoadIdentity(); glTranslatef(-0.5f, 0.0f, -2.0f); glRotatef(sRotAngle, 0.0f, 0.0f, 1.0f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Draw triangle glVertexPointer(2, GL_FLOAT, 0, sTriangleVertices); glColorPointer(4, GL_FLOAT, 0, sColors); glLoadIdentity(); glTranslatef(0.5f, 0.0f, -2.1f); glRotatef(-sRotAngle, 0.0f, 0.0f, 1.0f); glDrawArrays(GL_TRIANGLES, 0, 3); glFlush(); glutSwapBuffers(); if(++sRotAngle == 360) sRotAngle = 0; } static void TimerHandler(int value) { RenderHandler(); } static int sGLUTWindow; static int sStoredArgC; static char **sStoredArgv; static void GLUTWindowCloseHandler(void) { glutDestroyWindow(sGLUTWindow); glutLeaveMainLoop(); } static void ShowOpenGLWindow(GtkWidget *widget, gpointer window) { if(window != NULL) g_printf("Button clicked\n"); // 每次打开GLUT窗口前必须先调用一次glutInit函数 glutInit(&sStoredArgC, sStoredArgv); // 当用户点击GLUT窗口时,应用不直接退出 glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); glutCloseFunc(GLUTWindowCloseHandler); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE); glutInitWindowSize(480, 480); glutInitWindowPosition(200, 100); sGLUTWindow = glutCreateWindow("OpenGL GLUT Window"); glutSetOption(GLUT_MULTISAMPLE, 4); glutDisplayFunc(RenderHandler); var vendor = (const char*)glGetString(GL_VENDOR); var renderer = (const char*)glGetString(GL_RENDERER); var version = (const char*)glGetString(GL_VERSION); g_printf("The vendor is: %s\n", vendor); g_printf("The renderer is: %s\n", renderer); g_printf("The GL version is: %s\n", version); glViewport(0, 0, 480, 480); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glShadeModel(GL_SMOOTH); glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glEnable(GL_MULTISAMPLE_ARB); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 3.0f); glMatrixMode(GL_MODELVIEW); glutMainLoop(); g_printf("GLUT runloop has quit!\n"); } int main(int argc, char *argv[]) { // 保存argc与argv sStoredArgC = argc; sStoredArgv = argv; gtk_init(&argc, &argv); var window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "GTK-GLUT"); gtk_window_set_default_size(GTK_WINDOW(window), 480, 320); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window), 15); var button = gtk_button_new_with_label("Show GLUT"); gtk_widget_set_halign(button, GTK_ALIGN_START); gtk_widget_set_valign(button, GTK_ALIGN_START); gtk_widget_set_tooltip_text(button, "This is a button widget"); g_signal_connect(button, "clicked", G_CALLBACK(ShowOpenGLWindow), window); gtk_container_add(GTK_CONTAINER(window), button); gtk_widget_show_all(window); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); static_assert(sizeof(int) == 4, "Not compatible architecture!"); puts("Will enter GTK runloop..."); gtk_main(); puts("Program terminated!"); }
我们编译构建完此程序之后,直接在命令行输入gtk-glut这个app即可运行。我们每次点击按钮均能弹出GLUT窗口,点击关闭GLUT窗口可再次对GTK窗口中的按钮进行点击。
相关主题 |