GTK Timer - How to make a timer within a frame - c

How do g_timer_new works?
is it possible to do a
char timerz[50];
GTimer *timer
g_timer_start(GTimer *timer);
strcpy(timerz,(g_timer_elapsed(GTimer *timer))
Or what Could I do to have a timer in a gtk_frame???
Have a nice day! :D

You can use g_timeout_add or g_timeout_add_seconds which will call a timeout function at regular interval. Please note that this timeout function can be delayed due to event processing and should not be relied on for precise timing. Check this developer page for more info on main loop.
Here is an example to get you started (you can improvise over this). In the example the timeout is set in seconds thus using g_timeout_add_seconds, use g_timeout_add if you need millisecond precision.
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
/* Determines if to continue the timer or not */
static gboolean continue_timer = FALSE;
/* Determines if the timer has started */
static gboolean start_timer = FALSE;
/* Display seconds expired */
static int sec_expired = 0;
static void
_quit_cb (GtkWidget *button, gpointer data)
{
(void)button; (void)data; /*Avoid compiler warnings*/
gtk_main_quit();
return;
}
static gboolean
_label_update(gpointer data)
{
GtkLabel *label = (GtkLabel*)data;
char buf[256];
memset(&buf, 0x0, 256);
snprintf(buf, 255, "Time elapsed: %d secs", ++sec_expired);
gtk_label_set_label(label, buf);
return continue_timer;
}
static void
_start_timer (GtkWidget *button, gpointer data)
{
(void)button;/*Avoid compiler warnings*/
GtkWidget *label = data;
if(!start_timer)
{
g_timeout_add_seconds(1, _label_update, label);
start_timer = TRUE;
continue_timer = TRUE;
}
}
static void
_pause_resume_timer (GtkWidget *button, gpointer data)
{
(void)button;/*Avoid compiler warnings*/
if(start_timer)
{
GtkWidget *label = data;
continue_timer = !continue_timer;
if(continue_timer)
{
g_timeout_add_seconds(1, _label_update, label);
}
else
{
/*Decrementing because timer will be hit one more time before expiring*/
sec_expired--;
}
}
}
static void
_reset_timer (GtkWidget *button, gpointer data)
{
(void)button; (void)data;/*Avoid compiler warnings*/
/*Setting to -1 instead of 0, because timer will be triggered once more before expiring*/
sec_expired = -1;
continue_timer = FALSE;
start_timer = FALSE;
}
int main(void)
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *start_button;
GtkWidget *pause_resume_button;
GtkWidget *reset_button;
GtkWidget *quit_button;
GtkWidget *label;
gtk_init(NULL, NULL);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (gtk_main_quit),
NULL);
vbox = gtk_vbox_new (FALSE, 2);
gtk_container_add(GTK_CONTAINER(window), vbox);
label = gtk_label_new("Time elapsed: 0 secs");
start_button = gtk_button_new_with_label("Start");
g_signal_connect(G_OBJECT(start_button), "clicked", G_CALLBACK(_start_timer), label);
pause_resume_button = gtk_button_new_with_label("Pause/Resume");
g_signal_connect(G_OBJECT(pause_resume_button), "clicked", G_CALLBACK(_pause_resume_timer), label);
reset_button = gtk_button_new_with_label("Reset");
g_signal_connect(G_OBJECT(reset_button), "clicked", G_CALLBACK(_reset_timer), label);
quit_button = gtk_button_new_with_label("Quit");
g_signal_connect(G_OBJECT(quit_button), "clicked", G_CALLBACK(_quit_cb), NULL);
gtk_box_pack_start (GTK_BOX(vbox), label, 0, 0, 0);
gtk_box_pack_start (GTK_BOX(vbox), start_button, 0, 0, 0);
gtk_box_pack_start (GTK_BOX(vbox), pause_resume_button, 0, 0, 0);
gtk_box_pack_start (GTK_BOX(vbox), reset_button, 0, 0, 0);
gtk_box_pack_start (GTK_BOX (vbox), quit_button, 0, 0, 0);
gtk_widget_show_all(window);
g_timeout_add_seconds(1, _label_update, label);
continue_timer = TRUE;
start_timer = TRUE;
gtk_main();
return 0;
}
Hope this helps!

vbox = gtk_vbox_new (FALSE, 2);
In this line, "vbox" needs to be replaced with "box".
int main(int argc, char **argv);
gtk_init(&argc, &argv);

Related

How to handle double-click events in GTK+3?

I was wondering how to produce double clicks?
Take the following code that draws lines using single clicks http://zetcode.com/gfx/cairo/basicdrawing/:
#include <cairo.h>
#include <gtk/gtk.h>
static void do_drawing(cairo_t *);
struct {
int count;
double coordx[100];
double coordy[100];
} glob;
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
do_drawing(cr);
return FALSE;
}
static void do_drawing(cairo_t *cr)
{
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 0.5);
int i, j;
for (i = 0; i <= glob.count - 1; i++ ) {
for (j = 0; j <= glob.count - 1; j++ ) {
cairo_move_to(cr, glob.coordx[i], glob.coordy[i]);
cairo_line_to(cr, glob.coordx[j], glob.coordy[j]);
}
}
glob.count = 0;
cairo_stroke(cr);
}
static gboolean clicked(GtkWidget *widget, GdkEventButton *event,
gpointer user_data)
{
if (event->button == 1) {
glob.coordx[glob.count] = event->x;
glob.coordy[glob.count++] = event->y;
}
if (event->button == 3) {
gtk_widget_queue_draw(widget);
}
return TRUE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
glob.count = 0;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
g_signal_connect(G_OBJECT(darea), "draw",
G_CALLBACK(on_draw_event), NULL);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(window, "button-press-event",
G_CALLBACK(clicked), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_window_set_title(GTK_WINDOW(window), "Lines");
gtk_widget_show_all(window);
gtk_main();
return 0;
}
How do I get this program to respond to double clicks events instead of the single clicks?
I cannot find it in this list https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Button.html#Gtk.Button.signals.clicked.
From GdkEventButton:
For double-clicks the order of events will be:
GDK_BUTTON_PRESS
GDK_BUTTON_RELEASE
GDK_BUTTON_PRESS
GDK_2BUTTON_PRESS
GDK_BUTTON_RELEASE
Note that the first click is received just like a normal button press,
while the second click results in a GDK_2BUTTON_PRESS being received
just after the GDK_BUTTON_PRESS.
(...)
For a double click to occur, the second button press must occur within 1/4 of a second of the first.
Each GdkEvent has a GdkEventType field that you can check for GDK_2BUTTON_PRESS or GDK_DOUBLE_BUTTON_PRESS (alias added in 3.6):
a mouse button has been double-clicked (clicked twice within a short
period of time). Note that each click also generates a
GDK_BUTTON_PRESS event.
in button-press-event callback.
#include <gtk/gtk.h>
gboolean clicked(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
{
if(event->type == GDK_DOUBLE_BUTTON_PRESS)
printf("double\n");
return TRUE;
}
int main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
GtkWidget *window;
GtkWidget *label;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
label = gtk_label_new("label");
gtk_container_add(GTK_CONTAINER(window), label);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
g_signal_connect(window, "button-press-event", G_CALLBACK(clicked), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}

Is this simplification of GTK+ code correct?

I found the following GTK+3 code in Zetcode. It creates an animation using the cairo library while displaying an image:
#include <cairo.h>
#include <gtk/gtk.h>
/* compile with
*
* gcc spectrum.c -o spectrum `pkg-config --cflags --libs gtk+-3.0`
*
* */
static void do_drawing(cairo_t *);
struct {
gboolean timer;
cairo_surface_t *image;
cairo_surface_t *surface;
gint img_width;
gint img_height;
} glob;
static void init_vars()
{
glob.image = cairo_image_surface_create_from_png("beckov.png");
glob.img_width = cairo_image_surface_get_width(glob.image);
glob.img_height = cairo_image_surface_get_height(glob.image);
glob.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
glob.img_width, glob.img_height);
glob.timer = TRUE;
}
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
do_drawing(cr);
return FALSE;
}
static void do_drawing(cairo_t *cr)
{
cairo_t *ic;
static gint count = 0;
ic = cairo_create(glob.surface);
gint i, j;
for (i = 0; i <= glob.img_height; i+=7) {
for (j = 0 ; j < count; j++) {
cairo_move_to(ic, 0, i+j);
cairo_line_to(ic, glob.img_width, i+j);
}
}
count++;
if (count == 8) glob.timer = FALSE;
cairo_set_source_surface(cr, glob.image, 10, 10);
cairo_mask_surface(cr, glob.surface, 10, 10);
cairo_stroke(ic);
cairo_destroy(ic);
}
static gboolean time_handler(GtkWidget *widget)
{
if (!glob.timer) return FALSE;
gtk_widget_queue_draw(widget);
return TRUE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
init_vars();
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER (window), darea);
g_signal_connect(G_OBJECT(darea), "draw",
G_CALLBACK(on_draw_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 325, 250);
gtk_window_set_title(GTK_WINDOW(window), "Spectrum");
g_timeout_add(400, (GSourceFunc) time_handler, (gpointer) window);
gtk_widget_show_all(window);
gtk_main();
cairo_surface_destroy(glob.image);
cairo_surface_destroy(glob.surface);
return 0;
}
I achieve exatly the same result if I remove the do_drawing() function and move its code to the on_draw_event(), like:
#include <cairo.h>
#include <gtk/gtk.h>
/* compile with
*
* gcc spectrum.c -o spectrum `pkg-config --cflags --libs gtk+-3.0`
*
* */
struct {
gboolean timer;
cairo_surface_t *image;
cairo_surface_t *surface;
gint img_width;
gint img_height;
} glob;
static void init_vars()
{
glob.image = cairo_image_surface_create_from_png("beckov.png");
glob.img_width = cairo_image_surface_get_width(glob.image);
glob.img_height = cairo_image_surface_get_height(glob.image);
glob.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
glob.img_width, glob.img_height);
glob.timer = TRUE;
}
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
cairo_t *ic;
static gint count = 0;
ic = cairo_create(glob.surface);
gint i, j;
for (i = 0; i <= glob.img_height; i+=7) {
for (j = 0 ; j < count; j++) {
cairo_move_to(ic, 0, i+j);
cairo_line_to(ic, glob.img_width, i+j);
}
}
count++;
if (count == 8) glob.timer = FALSE;
cairo_set_source_surface(cr, glob.image, 10, 10);
cairo_mask_surface(cr, glob.surface, 10, 10);
cairo_stroke(ic);
cairo_destroy(ic);
return FALSE;
}
static gboolean time_handler(GtkWidget *widget)
{
if (!glob.timer) return FALSE;
gtk_widget_queue_draw(widget);
return TRUE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
init_vars();
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER (window), darea);
g_signal_connect(G_OBJECT(darea), "draw",
G_CALLBACK(on_draw_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 325, 250);
gtk_window_set_title(GTK_WINDOW(window), "Spectrum");
g_timeout_add(400, (GSourceFunc) time_handler, (gpointer) window);
gtk_widget_show_all(window);
gtk_main();
cairo_surface_destroy(glob.image);
cairo_surface_destroy(glob.surface);
return 0;
}
So... I wonder... Am I missing something here (loss of generality)?
Or was the call to do_drawing() in function on_draw_event() of the original code redundant?
Thanks
Yes. It's correct on compiler's side.
But it's a good practice for functions to solve exactly one task. do_drawing is busy with drawing lines and pixels, on_draw_event is busy with processing events. Probably in this code snippet there is no real reason to make a separate function, but usually on_draw_event would be much more complicated.

How can I create new window in GTK after click?

I'm new at GTK, and I was wondering how can I create a new window after a click button. I've got this function
void cb_create_entry(GtkWidget *, gpointer);
int create_window(int argc, char *argv[]){
GtkWidget *p_window = NULL;
GtkWidget *p_main_box = NULL;
GtkWidget *p_button[5];
gtk_init (&argc, &argv);
//Create window
p_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(p_window), "Hello");
gtk_window_set_default_size(GTK_WINDOW(p_window), 320, 200);
p_main_box = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(p_window), p_main_box);
{
p_button[0] = gtk_button_new_with_label("Create entry");
g_signal_connect(G_OBJECT(p_button[0]), "clicked",
G_CALLBACK(cb_create_entry), NULL);
gtk_box_pack_start(GTK_BOX(p_main_box), p_button[0], FALSE, FALSE, 0);
}
gtk_widget_show_all(p_window);
gtk_main ();
return EXIT_SUCCESS;
and callback.h
#ifndef CALLBACK_H_INCLUDED
#define CALLBACK_H_INCLUDED
#include <gtk/gtk.h>
void cb_create_entry(GtkWidget *p_widget, gpointer user_data){
gtk_button_released(p_widget);
GtkWidget *p_window;
GtkWidget *p_v_box;
GtkWidget *p_entry;
p_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(p_window), "Create DB");
gtk_window_set_default_size(GTK_WINDOW(p_window), 320, 200);
p_v_box = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(p_window), p_v_box);
p_entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(p_v_box), p_entry, TRUE, FALSE, 0);
}
and main
int main(int argc, char const *argv[]) {
create_window(argc, argv);
return 0;
}
But it doesn't work. I'd like to create a new window with an input. But when I click on button, nothing happens.
I'm a bit confused on how you laid out your file structure. Since there's no input on that I'll assume that the file with create_window function is the same where you have main. Then, callback.h should not have implementation code.
Nevertheless, i don't see any gtk_widget_show or gtk_widget_show_all calls and not sure you suppressed or just missed them. I'll assume the later because by your description it seems that you can see the initial window.
It's also missing a call to gtk_main.
Adding GtkWidget show functions and gtk_main to your code, it does work like expected:
Lets call the first file main.c :
#include <gtk/gtk.h>
#include "callback.h"
void cb_create_entry(GtkWidget *, gpointer);
int create_window(int argc, char *argv[]){
GtkWidget *p_window = NULL;
GtkWidget *p_main_box = NULL;
GtkWidget *p_button[5];
gtk_init (&argc, &argv);
//Create window
p_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(p_window), "Hello");
gtk_window_set_default_size(GTK_WINDOW(p_window), 320, 200);
p_main_box = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(p_window), p_main_box);
p_button[0] = gtk_button_new_with_label("Create entry");
g_signal_connect(G_OBJECT(p_button[0]), "clicked",
G_CALLBACK(cb_create_entry), NULL);
gtk_box_pack_start(GTK_BOX(p_main_box), p_button[0], FALSE, FALSE, 0);
gtk_widget_show_all(p_window);
}
int main (int argc, char *argv[]) {
create_window(argc, argv);
gtk_main ();
return 0;
}
And the other file callbacks.h :
#include <gtk/gtk.h>
void cb_create_entry(GtkWidget *p_widget, gpointer user_data){
gtk_button_released(p_widget);
GtkWidget *p_window;
GtkWidget *p_v_box;
GtkWidget *p_entry;
p_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(p_window), "Create DB");
gtk_window_set_default_size(GTK_WINDOW(p_window), 320, 200);
p_v_box = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(p_window), p_v_box);
p_entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(p_v_box), p_entry, TRUE, FALSE, 0);
gtk_widget_show_all(p_window);
}
Then compiling with:
gcc -o test main.c callback.h `pkg-config --cflags --libs gtk+-3.0`
will result in a window with a button, which after being pressed will create and show a new window with a GtkEntry:
now callback.h looks like that :
int cb_create_entry(GtkWidget *p_widget, gpointer user_data){
GtkWidget *p_window = NULL;
GtkWidget *p_entry = NULL;
GtkWidget *p_button = NULL;
GtkWidget *p_main_box = NULL;
GtkWidget *p_label = NULL;
p_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(p_window), "Create entry");
gtk_window_set_default_size(GTK_WINDOW(p_window), 320, 200);
g_signal_connect (G_OBJECT (p_window), "destroy", G_CALLBACK (cb_quit), NULL);
p_main_box = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(p_window), p_main_box);
p_label = gtk_label_new("Please, name your DB");
gtk_container_add(GTK_CONTAINER(p_main_box), p_label);
p_entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(p_main_box), p_entry);
p_button = gtk_button_new_with_label("Create !");
gtk_container_add(GTK_CONTAINER(p_main_box), p_button);
{
GtkWidget *p_quit = NULL;
p_quit = gtk_button_new_with_label("Quit");
g_signal_connect(G_OBJECT(p_quit), "clicked", G_CALLBACK(cb_quit), NULL);
gtk_box_pack_start(GTK_BOX(p_main_box), p_quit, FALSE, FALSE, 0);
}
//gtk_widget_show(p_entry);
gtk_widget_show_all(p_window);
return EXIT_SUCCESS;}

GTK Application doesn't quit from dialog

I'm programming my first bigger GTK+-Application and i have some troubles with exiting the application.
I want to have a Quit-Button in a dialog box, because normally you should run the program in full-screen-mode.
First I tried to call "gtk_main_quit" direktly from a signal but it also didn't work. Now i tried it through an event, the console output works but "gtk_main_quit" doesn't do anything!
Can somebody explain what I'm doing wrong? If you want to give me some tips for better coding, I will really welcome that, too!
Thanks for you help in advance!
#include <stdlib.h>
#include <gtk/gtk.h>
#include <time.h>
static gboolean gtk_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
g_message("delete event occured\n");
gtk_main_quit();
return TRUE;
}
static void check_toggle_fullscreen (GtkToggleButton *checkButton_fullscreen, GtkWindow *window)
{
if (gtk_toggle_button_get_active(checkButton_fullscreen))
{
gtk_window_fullscreen(GTK_WINDOW(window));
}
else
{
gtk_window_unfullscreen(GTK_WINDOW(window));
}
}
static gboolean double_clicked (GtkWidget *eventbox, GdkEventButton *event, GtkWindow *window)
{
GtkWidget *dialog, *hbox, *checkButton_fullscreen, *image, *button_preferences, *button_closeApp;
dialog = gtk_dialog_new_with_buttons("Schnelleinstellung", window, GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
checkButton_fullscreen = gtk_check_button_new_with_label("Fullscreen");
image = gtk_image_new_from_stock(GTK_STOCK_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
hbox = gtk_hbox_new(FALSE, 10);
gtk_box_pack_start_defaults (GTK_BOX(hbox), image);
gtk_box_pack_start_defaults (GTK_BOX(hbox), checkButton_fullscreen);
if (gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(window))) & GDK_WINDOW_STATE_FULLSCREEN)
{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkButton_fullscreen), TRUE);
}
button_closeApp = gtk_button_new_from_stock(GTK_STOCK_QUIT);
button_preferences = gtk_button_new_from_stock(GTK_STOCK_PREFERENCES);
//Fill dialog with content
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), button_preferences);
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), button_closeApp);
g_signal_connect(G_OBJECT(checkButton_fullscreen), "toggled", G_CALLBACK(check_toggle_fullscreen), (gpointer)window);
g_signal_connect(G_OBJECT(button_closeApp), "clicked", G_CALLBACK(gtk_delete_event), NULL);
if (event-> type == GDK_2BUTTON_PRESS)
{
gtk_widget_show_all(dialog);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
return FALSE;
}
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *vbox2;
GtkWidget *label[5];
GtkWidget *frame1, *frame2;
GtkWidget *eventbox;
PangoFontDescription *font;
gtk_init(&argc, &argv);
//Window_TOPLEVEL
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"Abnahme");
gtk_window_maximize(GTK_WINDOW(window));
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
gtk_window_set_decorated(GTK_WINDOW(window), TRUE);
vbox = gtk_vbox_new(FALSE, 10);
vbox2 = gtk_vbox_new(FALSE, 10);
frame1 = gtk_frame_new("Naechster Skid");
frame2 = gtk_frame_new("Warteschlange");
eventbox = gtk_event_box_new();
gtk_frame_set_shadow_type(GTK_FRAME(frame1), GTK_SHADOW_IN);
gtk_frame_set_shadow_type(GTK_FRAME(frame2), GTK_SHADOW_IN);
label[0] = gtk_label_new("1");
font = pango_font_description_from_string("Arial 40");
gtk_widget_modify_font(label[0], font);
gtk_label_set_markup(GTK_LABEL(label[0]), "<b>Erster Skid</b>");
int j = 1;
while(j<5)
{
gchar buffer[10];
label[j] = gtk_label_new("0");
g_snprintf(buffer, sizeof(buffer), "%i",j+1);
gtk_label_set_markup(GTK_LABEL(label[j]), buffer);
gtk_widget_modify_font(label[j], font);
j++;
}
//Level 0
gtk_container_add(GTK_CONTAINER(window), eventbox);
gtk_event_box_set_above_child(GTK_EVENT_BOX(eventbox), TRUE);
gtk_container_add(GTK_CONTAINER(eventbox), vbox);
//Level 1
gtk_box_pack_start(GTK_BOX(vbox),frame1, TRUE, TRUE, 0);
//Level 2
gtk_container_add(GTK_CONTAINER(frame1), label[0]);
//Level 1
gtk_box_pack_start(GTK_BOX(vbox),frame2, TRUE, TRUE, 0);
//Level 2
gtk_container_add(GTK_CONTAINER(frame2), vbox2);
//Level 3
int i = 1;
while(i<5)
{
gtk_box_pack_start(GTK_BOX(vbox2), label[i], TRUE, TRUE, 0);
i++;
}
//Signals
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_delete_event), NULL);
g_signal_connect(G_OBJECT(eventbox), "button_press_event", G_CALLBACK(double_clicked), (gpointer) window);
gtk_widget_set_events(eventbox, GDK_BUTTON_PRESS_MASK);
gtk_widget_realize(eventbox);
/* Enter the main loop */
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
gtk_dialog_run() enters a recursive main loop. gtk_main_quit() only exits the innermost recursion of the main loop.
I don't know if GTK+ provides a clean way to do what you want; you might have to do that yourself somehow.
To delete gtk_dialog_run() and gtk_widget_destroy() like under the code is available to quit dialog button.
if (event-> type == GDK_2BUTTON_PRESS)
{
gtk_widget_show_all(dialog);
/*
* gtk_dialog_run(GTK_DIALOG(dialog));
* gtk_widget_destroy(dialog);
*/
}
It seems that the reason is running dialog is blocking to quit app.

GDK Threads not allowing gtk changes(Making timer)

#include <gtk/gtk.h>
#include<string.h>
#include<stdio.h>
#include <stdbool.h>
#include<stdlib.h>
static GtkWidget *textlabel_question_no;
static GtkWidget *textlabel_answer1;
static GtkWidget *textlabel_answer2;
static GtkWidget *textlabel_answer3;
static GtkWidget *textlabel_answer4;
static GtkWidget *textlabel_question;
static GtkWidget *textlabel_timer;
static GtkWidget *textlabel_timeleft;
static GtkWidget *button_next;
static GtkWidget *window2;
static GtkWidget *window31;
static GThread *thread;
void show_info(GtkWidget *window2);
// thread for timer
static gpointer thread_Func(gpointer data)
{
// gdk_threads_enter();
int min=0,sec;//min=29
while(min > -1 )
{
sec = 10;
while(sec>=0)
{
sleep(1);
char* timer_text=malloc(sizeof(char)*40);
if(sec>9)
{
sprintf(timer_text,"%d : %d",min,sec);
}
else
{
sprintf(timer_text,"%d : 0%d",min,sec);
}
gtk_label_set_text(GTK_LABEL(textlabel_timer),timer_text);
sec--;
}
min--;
}
// gdk_threads_leave();
// gdk_threads_enter();
g_printf("in show_info\n");
GtkWidget *dialog;
dialog = gtk_message_dialog_new(GTK_WINDOW(window2),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Your Time is UP !!!\n Lets see the Result & Statistics...","title");
gtk_window_set_title(GTK_WINDOW(dialog), "Time Finished");
gint result=gtk_dialog_run(GTK_DIALOG(dialog));
switch(result)
{
case GTK_RESPONSE_OK:
gtk_widget_hide(window2);
g_printf("in show_info\n");
system("./result &");
//gtk_main_quit();
break;
}
//sleep(10);
gtk_widget_destroy(dialog);
/*
window31 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window31), GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(window31), "Examination Panel");
gtk_container_set_border_width(GTK_CONTAINER(window31),12);
gtk_window_set_resizable(GTK_WINDOW(window31),FALSE);
gtk_widget_set_size_request(window31,300,150);
gtk_widget_show_all(window31);
//sleep(10);
gdk_threads_leave();*/
return NULL;
}
static void next_question_label_change(GtkWidget *button_next,gpointer data)
{
g_printf("in button_next\n");
static int question_value=2;
char *question_label = malloc(sizeof(char)*50);
sprintf(question_label,"Question %d of 10.",question_value);
gtk_label_set_text(GTK_LABEL(textlabel_question_no),question_label);
if(question_value<10)
question_value++;
}
//For Submit button dialog box
static void test_submit_window(GtkWidget *button_next,GtkWidget *window2)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new(GTK_WINDOW(window2),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
"Are you sure to Submit the Test?");
gtk_window_set_title(GTK_WINDOW(dialog), "Submit Test Confirmation");
gint result = gtk_dialog_run (GTK_DIALOG (dialog));
switch(result)
{
case GTK_RESPONSE_YES:
system("./result &");
gtk_widget_hide(window2);
break;
case GTK_RESPONSE_NO:
break;
}
gtk_widget_destroy(dialog);
}
int
main (int argc,char *argv[])
{
GTimer *g_time;
GtkWidget *fixed;
GtkWidget *radio1,*radio2,*radio3,*radio4;
GtkWidget *button_submit;
GtkWidget *textlabel_title;
GtkWidget *image;
GtkWidget *image2;
GError *error = NULL;
GdkPixbuf *pixbuf;
GtkWidget *scrolled_window;
/* Secure glib */
if( ! g_thread_supported() )
g_thread_init( NULL );
//g_threads_init(NULL);
//g_thread_init(NULL);
/* Secure gtk */
gdk_threads_init();
/* Obtain gtk's global lock */
// intialiazation
gtk_init (&argc, &argv);
//window attributes position,size,title
window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window2), GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(window2), "Examination Panel");
gtk_container_set_border_width(GTK_CONTAINER(window2),12);
gtk_window_set_resizable(GTK_WINDOW(window2),FALSE);
gtk_widget_set_size_request(window2,800,450);
button_next = gtk_button_new_with_label("Next>>");
button_submit = gtk_button_new_with_label("Submit");
textlabel_title = gtk_label_new("-> TECHNICAL EXAM <-");
textlabel_question = gtk_label_new("question placed here");
textlabel_question_no = gtk_label_new(" Question 1 of 10.");
textlabel_answer1 = gtk_label_new(" answer 1");
textlabel_answer2 = gtk_label_new(" answer 2");
textlabel_answer3 = gtk_label_new(" answer 3");
textlabel_answer4 = gtk_label_new(" answer 4");
textlabel_timer = gtk_label_new("30:00");
textlabel_timeleft = gtk_label_new("Time Left :");
//radio button for option
radio1 = gtk_radio_button_new_with_label (NULL , "A. ");
radio2 = gtk_radio_button_new_with_label_from_widget
(GTK_RADIO_BUTTON(radio1),"B.");
radio3 = gtk_radio_button_new_with_label_from_widget
(GTK_RADIO_BUTTON (radio1),"C. ");
radio4 = gtk_radio_button_new_with_label_from_widget
(GTK_RADIO_BUTTON (radio1),"D. ");
// For image
pixbuf = gdk_pixbuf_new_from_file_at_size
("/home/trilok/trantorlogo.png", 100, 100, &error);
if(!pixbuf)
{
g_print ("Error: %s\n",error->message);
g_error_free (error);
/* Handle error here */
}
image = gtk_image_new_from_pixbuf(pixbuf);
image2 = gtk_image_new_from_pixbuf(pixbuf);
g_object_unref (pixbuf);
//For Signals
g_signal_connect (window2, "destroy", G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (button_next,"clicked",G_CALLBACK
(next_question_label_change), NULL);
g_signal_connect (button_submit,"clicked",G_CALLBACK(test_submit_window),window2);
//timer
// pthread_create(&pth,NULL,threadFunc,"foo");
/* Create new thread */
thread = g_thread_create( thread_Func,NULL,
FALSE,&error);
if( ! thread )
{
g_print( "Error: %s\n", error->message );
return( -1 );
}
// For scrolled window
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_window),10);
gtk_scrolled_window_set_policy
(GTK_SCROLLED_WINDOW
(scrolled_window)
,GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
//fixed
fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window2), fixed);
gtk_widget_show(fixed);
gtk_scrolled_window_add_with_viewport
(GTK_SCROLLED_WINDOW(scrolled_window),textlabel_question);
gtk_widget_set_size_request(scrolled_window,580,150);
//scrolled border
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_SHADOW_IN);
gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_CORNER_TOP_LEFT);
gtk_fixed_put(GTK_FIXED(fixed), scrolled_window, 70, 110);
gtk_fixed_put(GTK_FIXED(fixed), image, 0, 0);
gtk_fixed_put(GTK_FIXED(fixed), image2, 0, 510);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_title, 300, 20);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_timeleft, 610, 70);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_timer, 690, 70);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_question_no, 65, 70);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer1,170, 300);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer2,170, 350);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer3,170, 400);
gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer4,170, 450);
gtk_fixed_put(GTK_FIXED(fixed), radio1, 100,300);
gtk_fixed_put(GTK_FIXED(fixed), radio2, 100,350);
gtk_fixed_put(GTK_FIXED(fixed), radio3, 100,400);
gtk_fixed_put(GTK_FIXED(fixed), radio4, 100,450);
gtk_fixed_put(GTK_FIXED(fixed), button_next,620, 500);
gtk_fixed_put(GTK_FIXED(fixed), button_submit,690, 500);
gtk_widget_show_all(window2);
//gdk_threads_enter();
GDK_THREADS_ENTER();
gtk_main();
/* Release gtk's global lock */
//gdk_threads_leave();
GDK_THREADS_LEAVE();
return 0;
}
Actually i am making an timer on exam simulator . My timer is working correctly but the problem is this i have to open an dialog box when timer goes to 0:00. her i am have implemented the threads to make an timer. Problem is this when timer goes to 0:00 then i segmentation fault. the gdk thread is not allowing any call to gtk widget.
Thanks for the help in advance.
Some rectify the above code an make it happen will be appreciated
It's not clear if you're using gdk_threads_enter() or not, since there's a bunch of commented-out calls and a macro instead. GTK+ is not thread-safe, what you're trying is not the proper way.
You really shouldn't need a thread for this, just use a glib timer.
You're leaking the memory from the timer_text allocation; gtk_label_set_text() does not transfer ownership of the text buffer (notice that it's const).

Resources