我正在尝试开发一个带有两个GtkDrawarea小部件的小型监控系统,并且每当我为每个Drawarea设置按钮时,都会同时更新它们。我为绘制两个sinoides做了一个小例子。
然而,只有第一个GtkDrawarea Widget更新了,另一个仍然冻结,直到我重新确定GtkWindow。我尝试过使用g_timeout_add_full,但我只能使用一个GtkDrawArea。
我正在发送测试应用程序的图像。
如果有人可以帮助我,我将非常感激。
PS:对不起我的英文: - )
这是我的代码:
#include <stdlib.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <cairo.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
GtkWidget *window;
GtkWidget *darea1;
GtkWidget *darea2;
double w_larg = 1600;
double w_alt = 1200;
bool toggle_stat1 = false;
bool toggle_stat2 = false;
int width, height;
double fase1 = 2;
double amp1 = 1.25;
double fase2 = 4;
double amp2 = 1.25;
gboolean flag_amp1 = TRUE;
gboolean flag_amp2 = TRUE;
static gboolean invalidate_drawing1(gpointer data);
static gboolean invalidate_drawing2(gpointer data);
//*******************************************************************************
static gboolean on_toggled1(GtkWidget *widget, gpointer data)
{
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
{toggle_stat1 = true;
printf("ToggleButton01 --> Acionado / toggle_stat1 = %d\n",toggle_stat1);
g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE,250,invalidate_drawing1,darea1,NULL); // Variação atualizada da linha acima :-)
}
else
{toggle_stat1 = false;
printf("ToggleButton01 --> Liberado / toggle_stat1 = %d\n",toggle_stat1);
}
return FALSE;
}
//*******************************************************************************
static gboolean on_toggled2(GtkWidget *widget, gpointer data)
{
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
{toggle_stat2 = true;
printf("ToggleButton02 --> Acionado / toggle_stat2 = %d\n",toggle_stat2);
g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE,250,invalidate_drawing2,darea2,NULL); // Variação atualizada da linha acima :-)
}
else
{toggle_stat2 = false;
printf("ToggleButton02 --> Liberado / toggle_stat2 = %d\n",toggle_stat2);
}
return FALSE;
}
//*******************************************************************************
//*******************************************************************************
//*******************************************************************************
//*******************************************************************************
static gboolean draw_darea1(GtkWidget *widget, cairo_t *cr, gpointer data)
{
int valor1;
double valor2;
static const double dashed1[] = {4.0, 21.0, 2.0};
static const double dashed3[] = {2.0};
cr = gdk_cairo_create(gtk_widget_get_window(widget));
cairo_set_source_rgba(cr, 0.45, 0.45, 0.45, 1);
cairo_rectangle(cr,0 , 0, widget->allocation.width, widget->allocation.height);
cairo_fill(cr);
double i = widget->allocation.width;
double j = widget->allocation.height;
double sc = fase1*M_PI/i;
double y;
double h = 0;
if (amp1 != 0) h = h + j/amp1;
//---------------------------------------------------------------------------
cairo_set_source_rgba(cr, 0, 0, 1, 1);
cairo_set_line_width(cr, 1.5);
cairo_move_to(cr, 0, (j/2)+(sin( (-i/2)*sc )*(h/2)) );
for(double x=(-i/2);x<=(i/2);x=x+2)
{
valor1 = rand()%5;
valor2 = rand()%50;
y=x*sc;
if (valor1 < 3 ) cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) + valor2 );
if (valor1 == 3) cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) );
if (valor1 > 3 ) cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) - valor2 );
}
cairo_stroke(cr);
//---------------------------------------------------------------------------
cairo_set_source_rgba(cr, 1, 1, 0, 1);
cairo_set_dash(cr,dashed1, 1, 0 );
cairo_set_line_width(cr, 1.5);
cairo_move_to(cr, 0, (j/2)+(sin( (-i/2)*sc )*(h/2)) );
for(double x=(-i/2);x<=(i/2);x=x+10)
{
y=x*sc;
cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) );
}
cairo_stroke(cr);
//---------------------------------------------------------------------------
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1);
cairo_set_dash(cr,dashed3, 1, 0 );
cairo_set_line_width(cr, 1.0);
cairo_move_to(cr,0,(j/2));
cairo_line_to(cr,i,(j/2));
cairo_move_to(cr,(i/2),0);
cairo_line_to(cr,(i/2),j);
cairo_stroke(cr);
cairo_destroy(cr);
return TRUE;
}
//*******************************************************************************
//*******************************************************************************
//*******************************************************************************
//*******************************************************************************
static gboolean draw_darea2(GtkWidget *widget, cairo_t *cr, gpointer data)
{
int valor1;
double valor2;
static const double dashed1[] = {4.0, 21.0, 2.0};
static const double dashed3[] = {2.0};
cr = gdk_cairo_create(gtk_widget_get_window(widget));
cairo_set_source_rgba(cr, 0.45, 0.45, 0.45, 1);
cairo_rectangle(cr,0 , 0, widget->allocation.width, widget->allocation.height);
cairo_fill(cr);
double i = widget->allocation.width;
double j = widget->allocation.height;
double sc = fase2*M_PI/i;
double y;
double h = 0;
if (amp2 != 0) h = h + j/amp2;
//---------------------
cairo_set_source_rgba(cr, 0, 0, 1, 1);
cairo_set_line_width(cr, 1.5);
cairo_move_to(cr, 0, (j/2)+(sin( (-i/2)*sc )*(h/2)) );
for(double x=(-i/2);x<=(i/2);x=x+2)
{
valor1 = rand()%5;
valor2 = rand()%50;
y=x*sc;
if (valor1 < 3 ) cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) + valor2 );
if (valor1 == 3) cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) );
if (valor1 > 3 ) cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) - valor2 );
}
cairo_stroke(cr);
//---------------------
cairo_set_source_rgba(cr, 0, 1, 0, 1);
cairo_set_dash(cr,dashed1, 1, 0 );
cairo_set_line_width(cr, 1.5);
cairo_move_to(cr, 0, (j/2)+(sin( (-i/2)*sc )*(h/2)) );
for(double x=(-i/2);x<=(i/2);x=x+10)
{
y=x*sc;
cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) );
}
cairo_stroke(cr);
//---------------------
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1);
cairo_set_dash(cr,dashed3, 1, 0 );
cairo_set_line_width(cr, 1.0);
cairo_move_to(cr,0,(j/2));
cairo_line_to(cr,i,(j/2));
cairo_move_to(cr,(i/2),0);
cairo_line_to(cr,(i/2),j);
cairo_stroke(cr);
cairo_destroy(cr);
return TRUE;
}
//*******************************************************************************
//*******************************************************************************
//*******************************************************************************
//*******************************************************************************
static gboolean invalidate_drawing1(gpointer data)
{
GdkWindow *win;
g_print("T_Signal-1 | amp1 = %2.3f | ",amp1);
if (toggle_stat1==true)
{
if ((flag_amp1==TRUE)&&(amp1 <= 3))
amp1=amp1+0.25;
else
flag_amp1=FALSE;
if ((flag_amp1==FALSE)&&(amp1 >= 1.25))
amp1=amp1-0.25;
else
flag_amp1=TRUE;
}
//---------------------
win = gtk_widget_get_window(GTK_WIDGET(data));
if (win) {
GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(data), &allocation);
gdk_window_invalidate_rect(win, &allocation, FALSE);
}
if (flag_amp1 == TRUE)
return TRUE;
else
return FALSE;
}
//**********************
//**********************
//**********************
static gboolean invalidate_drawing2(gpointer data)
{
GdkWindow *win;
//---------------------
g_print("T_Signal-2 | amp2 = %2.3f\n",amp2);
if (toggle_stat2==true)
{
if ((flag_amp2==TRUE)&&(amp2 <= 3))
amp2=amp2+0.25;
else
flag_amp2=FALSE;
if ((flag_amp2==FALSE)&&(amp2 >= 1.25))
amp2=amp2-0.25;
else
flag_amp2=TRUE;
}
//---------------------
win = gtk_widget_get_window(GTK_WIDGET(data));
if (win) {
GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(data), &allocation);
gdk_window_invalidate_rect(win, &allocation, FALSE);
}
if (flag_amp2 == TRUE)
return TRUE;
else
return FALSE;
}
//**********************
//**********************
//**********************
int main (int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *togglebutton1;
GtkWidget *togglebutton2;
GtkWidget *togglebutton3;
GtkWidget *button1; // Amp+
GtkWidget *button2; // Amp-
gtk_init (&argc, &argv);
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "GTK_Glade_2DrawArea01-R00.glade", NULL); //Carrega as informações do projeto glade para o GtkBuilder
window = GTK_WIDGET(gtk_builder_get_object (builder, "window1")); //Retorna o objeto Window, para mostrá-lo mais tarde
darea1 = GTK_WIDGET(gtk_builder_get_object (builder, "drawingarea1")); //Retorna o objeto DrawingArea, para mostrá-lo mais tarde
darea2 = GTK_WIDGET(gtk_builder_get_object (builder, "drawingarea2")); //Retorna o objeto DrawingArea, para mostrá-lo mais tarde
togglebutton1 = GTK_WIDGET(gtk_builder_get_object (builder, "togglebutton1")); //Retorna o objeto togglebutton1, para mostrá-lo mais tarde
togglebutton2 = GTK_WIDGET(gtk_builder_get_object (builder, "togglebutton2")); //Retorna o objeto togglebutton1, para mostrá-lo mais tarde
togglebutton3 = GTK_WIDGET(gtk_builder_get_object (builder, "togglebutton3")); //Retorna o objeto togglebutton1, para mostrá-lo mais tarde
button1 = GTK_WIDGET(gtk_builder_get_object (builder, "button1")); //Retorna o objeto button1, para mostrá-lo mais tarde
button2 = GTK_WIDGET(gtk_builder_get_object (builder, "button2")); //Retorna o objeto button2, para mostrá-lo mais tarde
gtk_window_set_title(GTK_WINDOW(window), "GTK 2 Viewports DrawArea 01");
gtk_builder_connect_signals (builder, NULL); //Conecta todos os eventos dentro do projeto do glade.
g_object_unref (G_OBJECT (builder)); //Exclui o GtkBuilder, pois não iremos mais usá-lo nesse exemplo.
g_signal_connect(G_OBJECT(togglebutton1) , "toggled" , G_CALLBACK(on_toggled1) , NULL);
g_signal_connect(G_OBJECT(togglebutton2) , "toggled" , G_CALLBACK(on_toggled2) , NULL);
g_signal_connect(G_OBJECT(darea1), "expose-event", G_CALLBACK(draw_darea1), NULL);
g_signal_connect(G_OBJECT(darea2), "expose-event", G_CALLBACK(draw_darea2), NULL);
g_signal_connect_swapped(G_OBJECT(window) , "destroy", G_CALLBACK(gtk_main_quit) , G_OBJECT(window));
gtk_widget_show_all(window); //Mostra a janela com seus objetos
gtk_main ();
return 0;
}
这是在建议andlabs和wogsland之后修复的代码(下面)。谢谢。
#include <stdlib.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <cairo.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
GtkWidget *window;
GtkWidget *darea1;
GtkWidget *darea2;
bool toggle_stat1 = false;
bool toggle_stat2 = false;
double fase1 = 2;
double amp1 = 1.25;
double fase2 = 4;
double amp2 = 1.25;
gboolean flag_amp1 = TRUE;
gboolean flag_amp2 = TRUE;
//*******************************************************************************
static gboolean on_toggled1(GtkWidget *widget, gpointer data)
{
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
{toggle_stat1 = true;
printf("ToggleButton01 --> Acionado / toggle_stat1 = %d\n",toggle_stat1);
}
else
{toggle_stat1 = false;
printf("ToggleButton01 --> Liberado / toggle_stat1 = %d\n",toggle_stat1);
}
return FALSE;
}
//*******************************************************************************
static gboolean on_toggled2(GtkWidget *widget, gpointer data)
{
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
{toggle_stat2 = true;
printf("ToggleButton02 --> Acionado / toggle_stat2 = %d\n",toggle_stat2);
}
else
{toggle_stat2 = false;
printf("ToggleButton02 --> Liberado / toggle_stat2 = %d\n",toggle_stat2);
}
return FALSE;
}
//*******************************************************************************
//*******************************************************************************
static gboolean draw_darea1(GtkWidget *widget, cairo_t *cr, gpointer data)
{
static const double dashed1[] = {4.0, 21.0, 2.0};
cr = gdk_cairo_create(gtk_widget_get_window(widget));
cairo_set_source_rgba(cr, 0.45, 0.45, 0.45, 1);
cairo_rectangle(cr,0 , 0, widget->allocation.width, widget->allocation.height);
cairo_fill(cr);
double i = widget->allocation.width;
double j = widget->allocation.height;
double sc = fase1*M_PI/i;
double y;
double h = 0;
if (amp1 != 0) h = h + j/amp1;
//---------------------------------------------------------------------------
cairo_set_source_rgba(cr, 1, 1, 0, 1);
cairo_set_dash(cr,dashed1, 1, 0 );
cairo_set_line_width(cr, 1.5);
cairo_move_to(cr, 0, (j/2)+(sin( (-i/2)*sc )*(h/2)) );
for(double x=(-i/2);x<=(i/2);x=x+10)
{
y=x*sc;
cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) );
}
cairo_stroke(cr);
return TRUE;
}
//*******************************************************************************
//*******************************************************************************
static gboolean draw_darea2(GtkWidget *widget, cairo_t *cr, gpointer data)
{
static const double dashed1[] = {4.0, 21.0, 2.0};
cr = gdk_cairo_create(gtk_widget_get_window(widget));
cairo_set_source_rgba(cr, 0.45, 0.45, 0.45, 1);
cairo_rectangle(cr,0 , 0, widget->allocation.width, widget->allocation.height);
cairo_fill(cr);
double i = widget->allocation.width;
double j = widget->allocation.height;
double sc = fase2*M_PI/i;
double y;
double h = 0;
if (amp2 != 0) h = h + j/amp2;
//---------------------
cairo_set_source_rgba(cr, 0, 1, 0, 1);
cairo_set_dash(cr,dashed1, 1, 0 );
cairo_set_line_width(cr, 1.5);
cairo_move_to(cr, 0, (j/2)+(sin( (-i/2)*sc )*(h/2)) );
for(double x=(-i/2);x<=(i/2);x=x+10)
{
y=x*sc;
cairo_line_to(cr,x+(i/2),(j/2)+(sin(y)*(h/2)) );
}
cairo_stroke(cr);
return TRUE;
}
//*******************************************************************************
//*******************************************************************************
static gboolean invalidate_drawing1(GtkWidget *widget)
{
g_print("T_Signal-1 | amp1 = %2.3f | ",amp1);
if (toggle_stat1==true)
{
if ((flag_amp1==TRUE)&&(amp1 <= 3))
amp1=amp1+0.25;
else
flag_amp1=FALSE;
if ((flag_amp1==FALSE)&&(amp1 >= 1.25))
amp1=amp1-0.25;
else
flag_amp1=TRUE;
}
//---------------------
gtk_widget_queue_draw(widget);
return TRUE;
}
//**********************
//**********************
static gboolean invalidate_drawing2(GtkWidget *widget)
{
g_print("T_Signal-2 | amp2 = %2.3f\n",amp2);
if (toggle_stat2==true)
{
if ((flag_amp2==TRUE)&&(amp2 <= 3))
amp2=amp2+0.25;
else
flag_amp2=FALSE;
if ((flag_amp2==FALSE)&&(amp2 >= 1.25))
amp2=amp2-0.25;
else
flag_amp2=TRUE;
}
//---------------------
gtk_widget_queue_draw(widget);
return TRUE;
}
//**********************
int main (int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *togglebutton1;
GtkWidget *togglebutton2;
gtk_init (&argc, &argv);
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "GTK_Glade_2DrawArea01-R00.glade", NULL); //Carrega as informações do projeto glade para o GtkBuilder
window = GTK_WIDGET(gtk_builder_get_object (builder, "window1")); //Retorna o objeto Window, para mostrá-lo mais tarde
darea1 = GTK_WIDGET(gtk_builder_get_object (builder, "drawingarea1")); //Retorna o objeto DrawingArea, para mostrá-lo mais tarde
darea2 = GTK_WIDGET(gtk_builder_get_object (builder, "drawingarea2")); //Retorna o objeto DrawingArea, para mostrá-lo mais tarde
togglebutton1 = GTK_WIDGET(gtk_builder_get_object (builder, "togglebutton1")); //Retorna o objeto togglebutton1, para mostrá-lo mais tarde
togglebutton2 = GTK_WIDGET(gtk_builder_get_object (builder, "togglebutton2")); //Retorna o objeto togglebutton1, para mostrá-lo mais tarde
gtk_window_set_title(GTK_WINDOW(window), "GTK 2 Viewports DrawArea 01");
gtk_builder_connect_signals (builder, NULL); //Conecta todos os eventos dentro do projeto do glade.
g_object_unref (G_OBJECT (builder)); //Exclui o GtkBuilder, pois não iremos mais usá-lo nesse exemplo.
g_signal_connect(G_OBJECT(togglebutton1) , "toggled" , G_CALLBACK(on_toggled1) , NULL);
g_signal_connect(G_OBJECT(togglebutton2) , "toggled" , G_CALLBACK(on_toggled2) , NULL);
g_signal_connect(G_OBJECT(darea1), "expose-event", G_CALLBACK(draw_darea1), NULL);
g_signal_connect(G_OBJECT(darea2), "expose-event", G_CALLBACK(draw_darea2), NULL);
g_signal_connect_swapped(G_OBJECT(window) , "destroy", G_CALLBACK(gtk_main_quit) , G_OBJECT(window));
g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE,250,(GSourceFunc)invalidate_drawing1,(gpointer)darea1,NULL); // Variação atualizada da linha acima :-)
g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE,250,(GSourceFunc)invalidate_drawing2,(gpointer)darea2,NULL); // Variação atualizada da linha acima :-)
gtk_widget_show_all(window); //Mostra a janela com seus objetos
gtk_main ();
return 0;
}
最终影像。
答案 0 :(得分:1)
请勿使用gdk_window_invalidate_rect()
。使用gtk_widget_queue_draw()
或gtk_widget_queue_draw_area()
。