I am currently working on an user interface with gtk.
What I've done for now is that you can select an image from your file and display it with the button "open".
The problem is that when I open a second image it add the image to the window without removing the current one.
I would like to know how to change the displayed image when the user choose to open another image.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "../Threshold/delete_color.h"
#define GTK_STOCK_CANCEL ((GtkStock)"gtk-cancel")
GtkWidget *image;
gchar* path;
void cb_quit(GtkWidget *p_widget, gpointer user_data)
{
gtk_main_quit();
(void)p_widget;
(void)user_data;
}
void solve(const gchar* path)
{
SDL_Surface* image;
// Binarization
image = binarization((char*) file_name);
SDL_SaveBMP(image, "binarize.bmp");
// Rotation
//rotation(image);
SDL_SaveBMP(image, "rotation.bmp");
// Grid Detection
SDL_SaveBMP(image, "grid.bmp");
// Case detection
// TODO
// Get the grid.txt
// TODO
// Get the grid solution
// TODO
// Create the solution image
// TODO
}
static void set_image(const gchar *file_name, gpointer user_data)
{
GtkWidget *pVBox;
GdkPixbuf *pixbuf;
GError *error = NULL;
pVBox = (GtkWidget*) user_data;
int width = gtk_widget_get_allocated_width(pVBox);
int height = gtk_widget_get_allocated_height(pVBox);
pixbuf = gdk_pixbuf_new_from_file("result.bmp", &error);
if (!error)
{
GdkPixbuf *pixbuf_mini = NULL;
pixbuf_mini = gdk_pixbuf_scale_simple(pixbuf,
width,
height - 200,
GDK_INTERP_NEAREST);
image = gtk_image_new_from_pixbuf(pixbuf_mini);
gtk_container_add(GTK_CONTAINER(pVBox), image);
gtk_widget_show(image);
}
}
void cb_open(GtkWidget *p_widget, gpointer user_data)
{
GtkWidget *p_dialog = NULL;
p_dialog = gtk_file_chooser_dialog_new("Open file", NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
if(gtk_dialog_run (GTK_DIALOG (p_dialog)) == GTK_RESPONSE_ACCEPT)
{
gchar *file_name = NULL;
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (p_dialog));
file_name = path;
g_print("%s\n", path);
set_image(file_name, user_data);
g_free (file_name), file_name = NULL;
}
gtk_widget_destroy(p_dialog);
(void)p_widget;
}
int main(int argc, char **argv)
{
GtkWidget *p_window = NULL;
GtkWidget *p_main_box = NULL;
// Initialisation
gtk_init (&argc, &argv);
// Main window
p_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(p_window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(p_window), 600, 400);
g_signal_connect (G_OBJECT (p_window), "destroy",
G_CALLBACK (cb_quit), NULL);
// Main container
p_main_box = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER (p_window), p_main_box);
// Exit button
{
GtkWidget *p_button = NULL;
p_button = gtk_button_new_with_label("Exit");
g_signal_connect(G_OBJECT (p_button), "clicked", G_CALLBACK (cb_quit), NULL);
gtk_box_pack_start(GTK_BOX (p_main_box), p_button, FALSE, FALSE, 0);
}
// Open button
{
GtkWidget *p_button = NULL;
p_button = gtk_button_new_with_label ("Open");
g_signal_connect (G_OBJECT (p_button), "clicked", G_CALLBACK (cb_open), (gpointer*) p_main_box);
gtk_box_pack_start (GTK_BOX (p_main_box), p_button, FALSE, FALSE, 0);
}
// Display
gtk_widget_show_all(p_window);
g_print("%s\n", path);
gtk_main();
return EXIT_SUCCESS;
}
You can try multiple approaches.
Remove old image and add new image
Use gtk_container_get_children to retrieve your old image if present and remove it using gtk_container_remove. Then add as you have done before.
You can replace the content of the image
Again, use gtk_container_get_children to retrieve your old image if present and replace the content using gtk_image_set_from_pixbuf.
(additionally to 1 or 2 above)
You can also create an image already when you create the container and use the pointer to that image as user_data for your callback. That would remove the need for retrieving the child from your container.
Related
I'm designing a text editor in C/GTK3+, using the GtkSourceView class to be able to show the line numbers via the method gtk_source_view_set_show_line_numbers. I'm able to modify the background color of textview and text but not that of panel containing line numbers. By default it seems to be white. Can you show me how to modify it?
This is the code:
#include <gtk/gtk.h>
#include <gtksourceview/gtksource.h>
void find (GtkTextView *text_view, const gchar *text, GtkTextIter *iter)
{
GtkTextIter mstart, mend;
GtkTextBuffer *buffer;
gboolean found;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
found = gtk_text_iter_forward_search (iter, text, 0, &mstart, &mend, NULL);
if (found)
{
gtk_text_buffer_select_range (buffer, &mstart, &mend);
gtk_text_buffer_create_mark (buffer, "last_pos", &mend, FALSE);
}
}
typedef struct App
{
GtkWidget *text_view;
GtkWidget *search_entry;
} App;
/* Called when main window is destroyed. */
void
win_destroy (void)
{
gtk_main_quit();
}
void
next_button_clicked (GtkWidget *next_button, App *app)
{
const gchar *text;
GtkTextBuffer *buffer;
GtkTextMark *last_pos;
GtkTextIter iter;
text = gtk_entry_get_text (GTK_ENTRY (app->search_entry));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (app->text_view));
last_pos = gtk_text_buffer_get_mark (buffer, "last_pos");
if (last_pos == NULL)
return;
gtk_text_buffer_get_iter_at_mark (buffer, &iter, last_pos);
find (GTK_TEXT_VIEW (app->text_view), text, &iter);
}
/* Called when search button is clicked. */
void
search_button_clicked (GtkWidget *search_button, App *app)
{
const gchar *text;
GtkTextBuffer *buffer;
GtkTextIter iter;
text = gtk_entry_get_text (GTK_ENTRY (app->search_entry));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (app->text_view));
gtk_text_buffer_get_start_iter (buffer, &iter);
find (GTK_TEXT_VIEW (app->text_view), text, &iter);
}
int
main (int argc, char *argv[])
{
GtkWidget *win;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *search_button;
GtkWidget *next_button;
GtkWidget *swindow;
GtkCssProvider *provider;
GtkStyleContext *context;
App app;
gtk_init (&argc, &argv);
/* Create a window with a search entry, search button and a text
area. */
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (win), "destroy", win_destroy, NULL);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL,0);
gtk_container_add (GTK_CONTAINER (win), vbox);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL,0);
gtk_container_add(GTK_CONTAINER (vbox), hbox);
app.search_entry = gtk_entry_new ();
search_button = gtk_button_new_with_label ("Search");
next_button = gtk_button_new_with_label ("Next");
gtk_container_add(GTK_CONTAINER (hbox), app.search_entry);
gtk_container_add(GTK_CONTAINER (hbox), search_button);
gtk_container_add(GTK_CONTAINER (hbox), next_button);
g_signal_connect (G_OBJECT (search_button), "clicked",
G_CALLBACK (search_button_clicked), &app);
g_signal_connect (G_OBJECT (next_button), "clicked",
G_CALLBACK (next_button_clicked), &app);
/* A scrolled window which automatically displays horizontal and
vertical scrollbars when the text exceeds the text view's size. */
swindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand (swindow, TRUE);
gtk_container_add(GTK_CONTAINER (vbox), swindow);
app.text_view = gtk_source_view_new ();
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider,
"textview{"
"font-size: 30px;"
"font-family: serif;"
"} text{"
"color: green;"
"background: black;"
"}",
-1,
NULL);
context = gtk_widget_get_style_context (app.text_view);
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
gtk_container_add (GTK_CONTAINER (swindow), app.text_view);
gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW((app.text_view)), TRUE);
gtk_widget_show_all (win);
gtk_main();
}
There are generally two possibilities.
The typical way this is done is not by changing colors on the GtkSourceView, but to instead use a style scheme with gtk_source_buffer_set_style_scheme(). The style scheme has a "line-number" and "current-line-number" style which can have a color associated with it.
Another way, that is typically only used to show information about marks, is to have a GtkSourceMark with GtkSourceMarkAttributes:background set. Then you can show marks in the gutter.
Generally speaking, when you get to certain levels of complexity, it's just easier to write your own gutter renderer to optimize for the problem space.
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;}
I have a simple GTK3 app that displays an image from a file in a window.
When you resize the window, the image is scaled in the expose callback to fit the window.
However, once the window has grown, you can't shrink it again; the resize handles only let you make the window ever bigger.
With GTK2 it was trivial to allow grow and shrink with gtk_window_set_policy(w,1,1,1).
How can the same effect be achieved in GTK3?
Here's the ever-growing code example:
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
gboolean resize_image(GtkWidget *widget, GdkEvent *event, void *data)
{
GdkPixbuf *pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(widget));
if (pixbuf == NULL)
{
g_printerr("Failed to get pixbuf\n");
return 1;
}
pixbuf = gdk_pixbuf_scale_simple(pixbuf,
widget->allocation.width, widget->allocation.height,
GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(widget), pixbuf);
return FALSE;
}
int main(int argc, char **argv)
{
GtkWidget *window = NULL;
GtkWidget *image = NULL;
if (argc < 2 || argc > 3)
{
g_printerr("Usage: %s <image>\n", argv[0]);
return 1;
}
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
image = gtk_image_new_from_file(argv[1]);
if (image == NULL)
{
g_printerr("Could not open \"%s\"\n", argv[1]);
return 1;
}
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(image, "expose-event", G_CALLBACK(resize_image), NULL);
gtk_container_add(GTK_CONTAINER(window), image);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
Eric Cecashon on the gtk-list mailing list suggests using a cairo drawing area inside a 1x1 grid container, which works fairly well:
/*
gcc -Wall da_resize.c -o da_resize `pkg-config gtk+-3.0 --cflags --libs`
Tested on Ubuntu16.04, GTK3.18.
*/
#include<gtk/gtk.h>
gboolean draw_picture(GtkWidget *da, cairo_t *cr, gpointer data)
{
gint width=gtk_widget_get_allocated_width(da);
gint height=gtk_widget_get_allocated_height(da);
GdkPixbuf *temp=gdk_pixbuf_scale_simple((GdkPixbuf*)data, width, height, GDK_INTERP_BILINEAR);
gdk_cairo_set_source_pixbuf(cr, temp, 0, 0);
cairo_paint(cr);
g_object_unref(temp);
return FALSE;
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Resize Picture");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
//Needs a valid picture.
GdkPixbuf *pixbuf=gdk_pixbuf_new_from_file(argc>1 ? argv[1] : "image.jpg", NULL);
GtkWidget *da1=gtk_drawing_area_new();
gtk_widget_set_hexpand(da1, TRUE);
gtk_widget_set_vexpand(da1, TRUE);
g_signal_connect(da1, "draw", G_CALLBACK(draw_picture), pixbuf);
GtkWidget *grid=gtk_grid_new();
gtk_grid_attach(GTK_GRID(grid), da1, 0, 0, 1, 1);
gtk_container_add(GTK_CONTAINER(window), grid);
gtk_widget_show_all(window);
gtk_main();
g_object_unref(pixbuf);
return 0;
}
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.
#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).