Gtk 3 - 我在哪里以及如何指定主循环的内容?

时间:2016-09-19 13:30:17

标签: c++ opengl gtk3

我正在尝试用GTK 3编写一个简单的“游戏循环”。我创建了一个GL上下文并尝试清除它。但是,显示的窗口只有一些黑色和白色矩形,可能是“占位符”显示。显然,颜色清除属于主循环,或者只执行一次,但我无法弄清楚如何注册我自己的主循环。我应该覆盖gtk_main还是完全替换它?

#include <gtk/gtk.h>
#include <GL/gl.h>

int main(int argc, char *argv[]) {
    GtkWidget *win, *area;
    gtk_init(&argc, &argv);
    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(win), "Hello, GNU");
    gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(win), 480, 480);
    g_signal_connect(win, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    area = gtk_gl_area_new();
    gtk_container_add(GTK_CONTAINER(win), area);
    gtk_widget_show_all(win);
    gtk_gl_area_make_current(GTK_GL_AREA(area));
    glClearColor(1,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    gtk_main();
    return 0;
}

g_signal_connect似乎是相关的,但信号似乎是特定事件,如激活,关闭等。

2 个答案:

答案 0 :(得分:3)

不确定OpenGL代码,但是这里有一个示例,您可能可以适应OpenGL,显示了回调如何更新GdkPixbuf

//g++ test.cpp `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0`
#include <gtk/gtk.h>

int width = 320, height = 240;

GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
GtkImage *image;

inline void drawPixel (int x, int y, char red, char green, char blue)
{
    *(pixels + y * rowstride + x * 3) = red;
    *(pixels + y * rowstride + x * 3 + 1) = green;
    *(pixels + y * rowstride + x * 3 + 2) = blue;
}

gboolean game_loop (GtkWidget *widget, GdkFrameClock *clock, gpointer data)
{
    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < height; j++)
        {
            drawPixel(i, j, rand() % 255, rand() % 255, rand() % 255);
        }
    }
    gtk_image_set_from_pixbuf (image, pixbuf);  
    return 1;
} 

int main()
{
    gtk_init (NULL, NULL);
    GtkWidget *window, *box;
    image = GTK_IMAGE (gtk_image_new());
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
    gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET(image), TRUE, TRUE, 0);
    gtk_container_add (GTK_CONTAINER (window), box);
    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
    gtk_widget_add_tick_callback(window, game_loop, NULL, NULL);
    gtk_widget_show_all (window);
    gtk_main();
}

结果:

gdkpixbuf

答案 1 :(得分:0)

这是演示如何使用OpenGL在Gtk 2中绘制多维数据集:

// gcc cube.c `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` \
  `pkg-config --cflags gtkgl-2.0 gtk+-2.0` `pkg-config --libs gtkgl-2.0 gtk+-2.0`
#include    <gtk/gtk.h>
#include    <gtkgl/gtkglarea.h>
#include    <GL/gl.h>
#include    <GL/glu.h>

const int MIN_WIDTH = 640;
const int MIN_HEIGHT = 480;

GtkWidget *glwindow;
GtkWidget *glarea = NULL;

// adapted from: https://www.opengl.org/archives/resources/code/samples/glut_examples/examples/cube.c

GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0};  /* Red diffuse light. */
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};  /* Infinite light location. */
GLfloat n[6][3] = {  /* Normals for the 6 faces of a cube. */
  {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
  {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} };
GLint faces[6][4] = {  /* Vertex indices for the 6 faces of a cube. */
  {0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4},
  {4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} };
GLfloat v[8][3];  /* Will be filled in with X,Y,Z vertexes. */

void
drawBox(void)
{
  int i;

  for (i = 0; i < 6; i++) {
    glBegin(GL_QUADS);
    glNormal3fv(&n[i][0]);
    glVertex3fv(&v[faces[i][0]][0]);
    glVertex3fv(&v[faces[i][1]][0]);
    glVertex3fv(&v[faces[i][2]][0]);
    glVertex3fv(&v[faces[i][3]][0]);
    glEnd();
  }
}

void
display(void)
{
  /* ... DRAW STUFF HERE ... */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  drawBox();
}

void
init(void)
{
  /* Setup cube vertex data. */
  v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
  v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
  v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
  v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
  v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
  v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;

  /* Enable a single OpenGL light. */
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHTING);

  /* Use depth buffering for hidden surface elimination. */
  glEnable(GL_DEPTH_TEST);

  /* Setup the view of the cube. */
  glMatrixMode(GL_PROJECTION);
  gluPerspective( /* field of view in degree */ 40.0,
    /* aspect ratio */ 1.0,
    /* Z near */ 1.0, /* Z far */ 10.0);
  glMatrixMode(GL_MODELVIEW);
  gluLookAt(0.0, 0.0, 5.0,  /* eye is at (0,0,5) */
    0.0, 0.0, 0.0,      /* center is at (0,0,0) */
    0.0, 1.0, 0.);      /* up is in positive Y direction */

  /* Adjust cube position to be asthetic angle. */
  glTranslatef(0.0, 0.0, -1.0);
  glRotatef(60, 1.0, 0.0, 0.0);
  glRotatef(-20, 0.0, 0.0, 1.0);
}

gint glarea_expose(GtkWidget *widget, GdkEventExpose *event)
{
    if (event->count > 0) {
        return TRUE;
    }
    g_print("drawing...\n");

    gtk_widget_grab_focus(GTK_WIDGET(glarea));

    if (gtk_gl_area_begingl(GTK_GL_AREA(glarea))) {

        display();

        gtk_gl_area_endgl(GTK_GL_AREA(glarea));
    }
    gtk_gl_area_swapbuffers(GTK_GL_AREA(glarea));

    return TRUE;
}

gint glarea_configure(GtkWidget *widget, GdkEventConfigure *event)
{
    if (gtk_gl_area_begingl(GTK_GL_AREA(widget))) {
        glViewport(0,0, widget->allocation.width, widget->allocation.height);
        gtk_gl_area_endgl(GTK_GL_AREA(widget));
    }
    return TRUE;
}

GtkWidget *create_gl_window()
{
    glwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect (glwindow, "delete_event",
    G_CALLBACK (gtk_main_quit), NULL);
    gtk_quit_add_destroy(1, GTK_OBJECT(glwindow));
    glarea = gtk_gl_area_new_vargs(NULL,
                       GDK_GL_DOUBLEBUFFER,
                       GDK_GL_RGBA,
                       GDK_GL_DEPTH_SIZE,1,
                       GDK_GL_NONE);
    if(!glarea) { 
        return FALSE;
    }

    gtk_widget_set_events(GTK_WIDGET(glarea),
                        GDK_EXPOSURE_MASK);
    gtk_signal_connect (GTK_OBJECT(glarea), "expose_event",
                      GTK_SIGNAL_FUNC(glarea_expose), NULL);
    gtk_signal_connect (GTK_OBJECT(glarea), "configure_event",
                      GTK_SIGNAL_FUNC(glarea_configure), NULL);
    gtk_signal_connect (GTK_OBJECT(glarea), "delete_event",
                      GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
    gtk_widget_set_usize(glarea, MIN_WIDTH, MIN_HEIGHT);
    gtk_quit_add_destroy(1, GTK_OBJECT(glarea));

    gtk_container_add(GTK_CONTAINER(glwindow),glarea);
    gtk_widget_show(glarea);
    gtk_widget_show(glwindow);

    GTK_WIDGET_SET_FLAGS(glarea,GTK_CAN_FOCUS);
    gtk_widget_grab_focus(GTK_WIDGET(glarea));
    init();

    return glwindow;
}

int main(int argc, char **argv)
{
    gtk_init(&argc, &argv);
    glwindow = create_gl_window();
    gtk_main();
    return 0;
}

结果: enter image description here