Gtk +没有正确更新小部件

时间:2016-05-24 00:14:20

标签: gtk gtk3 archlinux

我希望我能很好地描述这个问题。我几天前跑了pacman Syu,我正在努力的GTK应用程序停止正常工作。之后我再次运行它,但问题仍然存在。

基本上,程序没有正确响应。作为一个例子,我有一个按钮,当按下时,应该打印" aqui"到控制台,然后向上移动画布(如,向上导航)。但是,画布未更新,并且不打印输出。只有当我关闭申请时," aqui"按下按钮时打印的次数很多。

应用程序似乎在打开另一个窗口时响应。如果我单击打开不同窗口的按钮,累积的更改将生效(多次" aqui"打印,并且画布向上移动的次数与我单击的次数相同)。当我点击应该关闭新窗口的按钮时,按钮消失,但窗口仍然存在。例如:

The new window, asking for an input

After clicking OK

这是向上按钮的代码:

static gboolean moveUp(GtkWidget *widget, GdkEventButton *event,
    gpointer user_data)
{
    windowData->moveY(STEP);
    gtk_widget_queue_draw((GtkWidget*) user_data);
    std::cout << "aqui";
    return TRUE;
}

旋转按钮的代码,用于打开图片中显示的较小窗口:

static gboolean rotateWindowWindow(GtkWidget *widget, GdkEventButton *event,
    gpointer user_data) {
  GtkBuilder *builder;
  GError *error = NULL;

  builder = gtk_builder_new();

  if (!gtk_builder_add_from_file(builder, "rotateWindow.glade", &error)) {
    g_warning("%s", error->message);
    g_free(error);
  }

  GtkWidget *rotateWindowWindow;

  rotateWindowWindow = GTK_WIDGET( gtk_builder_get_object( builder, "rotateWindowWindow" ) );
  rotationAngle = (GtkEntry*) GTK_WIDGET( gtk_builder_get_object( builder, "rotationAngle" ) );
  GtkWidget* okButton = GTK_WIDGET(gtk_builder_get_object(builder, "okButton"));

  g_signal_connect(G_OBJECT(okButton), "clicked", G_CALLBACK(rotateW), rotateWindowWindow);

  gtk_builder_connect_signals(builder, NULL);
  g_object_unref(G_OBJECT(builder));
  gtk_widget_show_all(rotateWindowWindow);
  gtk_main();

  return TRUE;
}

点击rotateW时调用的okButton方法:

static gboolean rotateW(GtkWidget *widget, GdkEventButton *event,
    gpointer user_data)
{
  double angle = atof(gtk_entry_get_text(GTK_ENTRY(rotationAngle)));
  windowData->rotate(angle);

  displayFile->rotateAll(windowData->getAngle(), windowData->getCenter());

  gtk_widget_destroy((GtkWidget*) user_data);
  return TRUE;
}

main方法:

int main(int argc, char **argv)
{
    GtkWidget       *viewport, *buttonUp,
     *buttonDown,   *buttonLeft, *buttonRight, *buttonZoomIn,
     *buttonZoomOut, *newLine, *listWindow, *mainBox, *buttonClose,
     *newPolygon, *newPoint, *translateButton, *scaleButton, 
     *rotateButton, *rotateWindowButton;
    GtkDrawingArea  *drawingArea;
    GError          *error = NULL;

    origin.x = 0;
    origin.y = 0;

    viewportData = new Viewport(300.0, 350.0);
    windowData = new Window(300.0, 350.0);
    sh = new SutherlandHodgeman(windowData);
    cs = new CohenSutherland(windowData);
    nc = new NoClipping(windowData);
    clipper = nc;

    displayFile = new DisplayFile(); 

    Polygon* l = new Polygon("line");
    l->addPoint(0, 0);
    l->addPoint(100, 0);
    displayFile->add(l);

    //l = new Polygon("line2");
    //l->addPoint(5, 5);
    //l->addPoint(500, 15);
    //displayFile->add(l);

    /* Init GTK+ */

    gtk_init( &argc, &argv );

    /* Create new GtkBuilder object */
    mainBuilder = gtk_builder_new();

    /* Load UI from file. If error occurs, report it and quit application.
     * Replace "tut.glade" with your saved project. */
    if( ! gtk_builder_add_from_file( mainBuilder, "interface.glade", &error ) )
    {
        g_warning( "%s", error->message );
        g_free( error );
        return 1;
    }

    /* Get main window pointer from UI */
    mainWindow = GTK_WIDGET( gtk_builder_get_object( mainBuilder, "mainWindow" ) );
    viewport = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "viewport"));
    drawingArea = GTK_DRAWING_AREA(gtk_builder_get_object(mainBuilder, "drawingArea"));
    listWindow = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "listWindow"));
    buttonClose = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "buttonClose"));
    mainBox = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "mainBox"));
    buttonUp = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "buttonUp"));
    buttonLeft = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "buttonLeft"));
    buttonRight = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "buttonRight"));
    buttonDown = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "buttonDown"));
    buttonZoomIn = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "zoomIn"));
    buttonZoomOut = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "zoomOut"));
    translateButton = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "translateButton"));
    scaleButton = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "scaleButton"));
    rotateButton = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "rotateButton"));
    newPolygon = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "newPolygon"));
    newLine = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "newLine"));
    newPoint = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "newPoint"));
    cohenButton = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "cohenButton"));
    sutherlandButton = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "hodgemanButton"));
    noClippingButton = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "noClipping"));
    rotateWindowButton = GTK_WIDGET(gtk_builder_get_object(mainBuilder, "rotateWindow"));

    g_signal_connect(mainWindow, "delete_event", G_CALLBACK(exit_app), NULL);
    g_signal_connect(buttonClose, "clicked", G_CALLBACK(exit_app), NULL);
    g_signal_connect(G_OBJECT(drawingArea), "draw", G_CALLBACK(on_draw_event), NULL); 
    g_signal_connect(G_OBJECT(buttonUp), "clicked", G_CALLBACK(moveUp), mainWindow);
    g_signal_connect(G_OBJECT(buttonDown), "clicked", G_CALLBACK(moveDown), mainWindow);
    g_signal_connect(G_OBJECT(buttonLeft), "clicked", G_CALLBACK(moveLeft), mainWindow);
    g_signal_connect(G_OBJECT(buttonRight), "clicked", G_CALLBACK(moveRight), mainWindow);
    g_signal_connect(G_OBJECT(buttonZoomIn), "clicked", G_CALLBACK(zoomIn), mainWindow);
    g_signal_connect(G_OBJECT(buttonZoomOut), "clicked", G_CALLBACK(zoomOut), mainWindow);
    g_signal_connect(G_OBJECT(translateButton), "clicked", G_CALLBACK(translateWindow), mainWindow);
    g_signal_connect(G_OBJECT(rotateButton), "clicked", G_CALLBACK(rotateWindow), mainWindow);
    g_signal_connect(G_OBJECT(scaleButton), "clicked", G_CALLBACK(scaleWindow), mainWindow);
    g_signal_connect(G_OBJECT(newLine), "clicked", G_CALLBACK(newLineWindow), NULL);
    g_signal_connect(G_OBJECT(newPolygon), "clicked", G_CALLBACK(newPolygonWindow), NULL);
    g_signal_connect(G_OBJECT(newPoint), "clicked", G_CALLBACK(newPointWindow), NULL);
    g_signal_connect(G_OBJECT(cohenButton), "clicked", G_CALLBACK(changeClipping), mainWindow);
    g_signal_connect(G_OBJECT(sutherlandButton), "clicked", G_CALLBACK(changeClipping), mainWindow);
    g_signal_connect(G_OBJECT(noClippingButton), "clicked", G_CALLBACK(changeClipping), mainWindow);
    g_signal_connect(G_OBJECT(rotateWindowButton), "clicked", G_CALLBACK(rotateWindowWindow), mainWindow);
    /* Connect signals */
    gtk_builder_connect_signals( mainBuilder, NULL );

    /* Destroy builder, since we don't need it anymore */
    //g_object_unref( G_OBJECT( mainBuilder ) );

    /* Show window. All other widgets are automatically shown by GtkBuilder */
    gtk_widget_show_all( mainWindow );

    /* Start main loop */
    gtk_main();

    return 0;
}

如果这还不够,则完整代码位于github。我提前道歉,代码很乱。

修改

std::endl添加到std::cout的末尾解决了实时未打印字符串的问题。现在,当我按下按钮时,它们正在打印,但按钮的其余功能(与影响界面有关)仍然无法更新,直到另一个窗口打开。

编辑2

I made a gif showing how it's behaving right now.

我尝试将gtk从3.20.6降级到3.16.1,但这并没有奏效。我还尝试降级每个包(通过编辑/etc/pacman.conf然后运行pacman -Syyuu)到2016年3月30日,也没有工作。

我还尝试删除gtk main()的其他实例但没有成功。

刚尝试添加此代码:

if(gtk_events_pending())
    gtk_main_iteration();

哪一个力一次运行主循环。这也没有解决问题。

2 个答案:

答案 0 :(得分:1)

您可能希望强制GTK刷新其待处理操作。

我用python这样做:

while gtk.events_pending():     #   this forces GTK to refresh the screen
    gtk.main_iteration()        

由于你没有提到你正在使用的语言,你必须找到如何重现这个,但它可能只是

 while gtk.events_pending():     #   this forces GTK to refresh the screen
    gtk.main_iteration();

答案 1 :(得分:1)

你的问题是你曾两次打电话给gtk_main。在你的主要(这是好的)和你的rotateWindowWindow功能(这是错误的)。这样做会创建一个新的主循环,在您退出之前,您将被卡住。

删除额外的通话应足以解决您的问题。