我用林间空地创建了一个非常简单的GTK3 C应用程序,其中包含按钮和GtkDrawingArea(与GtkPaned一起保存)。按下按钮后,应立即绘制一个矩形,但是不会发生。仅当鼠标在GtkPaned拆分部分上鸣叫时才会发生(请参阅.gif)。如果不使用Glade,则此问题不存在。
如何解决这个问题?
gif
C代码:
#include <gtk/gtk.h>
//==============================================================Global=variables========================================================================
static cairo_surface_t *surface = NULL;
GtkWidget *DrawArea;
//==============================================================Functions===============================================================================
void clear_surface (void)
{
cairo_t *cr;
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 0, 1, 1);
cairo_paint (cr);
cairo_destroy (cr);
}
//Create a new surface of the appropriate size to store our scribbles
gboolean configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, gpointer data)
{
if (surface)
{
cairo_surface_destroy (surface);
}
surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget), CAIRO_CONTENT_COLOR, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget));
/* Initialize the surface to white */
clear_surface ();
/* We've handled the configure event, no need for further processing. */
return TRUE;
}
/* Redraw the screen from the surface. Note that the ::draw
* signal receives a ready-to-be-used cairo_t that is already
* clipped to only draw the exposed areas of the widget
*/
gboolean draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data)
{
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
return FALSE;
}
//Draw a rectangle on the surface at the given position
void draw_brush (GtkWidget *widget, double x, double y)
{
cairo_t *cr;
/* Paint to the surface, where we store our state */
cr = cairo_create (surface);
cairo_rectangle (cr, x - 3, y - 3, 6, 6);
cairo_fill (cr);
cairo_destroy (cr);
//Now invalidate the affected region of the drawing area.
gtk_widget_queue_draw_area (widget, x - 3, y - 3, 6, 6);
}
void draw_rectangle (GtkWidget *widget, float posX, float posY, float length, float height, float colorR, float colorG, float colorB)
{
cairo_t *cr;
/* Paint to the surface, where we store our state */
cr = cairo_create (surface);
cairo_set_source_rgb (cr, colorR, colorG, colorB);
cairo_rectangle (cr, posX, posY, length, height);
cairo_fill (cr);
cairo_destroy (cr);
//Now invalidate the affected region of the drawing area.
gtk_widget_queue_draw_area (widget, posX, posY, length, height);
}
//==================================Button=stuff==========================
void Button_clicked(GtkWidget* widget, gpointer data)
{
g_print("Clicked\n");
draw_brush (DrawArea, 10, 10);
//gtk_widget_queue_draw (window_main);
}
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
gtk_init(&argc, &argv);
DrawArea = gtk_drawing_area_new ();
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "Resources/GUI_design.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(builder);
gtk_widget_show(window);
gtk_main();
return 0;
}
// called when window is closed
void on_window_main_destroy()
{
gtk_main_quit();
}
Glade代码:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window_main">
<property name="can_focus">False</property>
<property name="default_width">500</property>
<property name="default_height">500</property>
<property name="icon">icon.png</property>
<signal name="destroy" handler="on_window_main_destroy" swapped="no"/>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkPaned" id="paned">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="orientation">vertical</property>
<property name="position">300</property>
<property name="position_set">True</property>
<child>
<object class="GtkDrawingArea" id="DrawArea">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="configure-event" handler="configure_event_cb" swapped="no"/>
<signal name="draw" handler="draw_cb" swapped="no"/>
</object>
<packing>
<property name="resize">False</property>
<property name="shrink">False</property>
</packing>
</child>
<child>
<object class="GtkButton" id="Button">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="Button_clicked" swapped="no"/>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
最佳答案
我终于找到并解决了问题!!!!
int main现在看起来像这样(删除了1行并添加了1行)
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
gtk_init(&argc, &argv);
//DrawArea = gtk_drawing_area_new ();
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "Resources/GUI_design.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
gtk_builder_connect_signals(builder, NULL);
DrawArea = GTK_WIDGET(gtk_builder_get_object(builder, "DrawArea")); //This is very important
g_object_unref(builder);
gtk_widget_show(window);
gtk_main();
return 0;
}
描述导致此问题的原因:Glade和我创建了2个单独的指针,并且仅使用指针进行了操作,而不是Glade的。那条重要的线将这两个指针连接在一起,现在可以工作了。 h!
这个教程帮助我解决了这个问题:https://prognotes.net/2016/03/gtk-3-c-code-hello-world-tutorial-using-glade-3/
关于c - 如果使用Glade进行绘制,则GtkDrawingArea不会更新,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53459739/