drawing on window using gtk 2.0 - c

I have a program using pthreads. I want add an interface using gtk2.0, but have a problem with drawing on window. When I call g_signal_connect(G_OBJECT(window), "configure_event",G_CALLBACK(draw_things), NULL);
lines which I draw appear and at once disappear. If I move a window calling function
gtk_window_move (GTK_WINDOW(widget), 10,10);
or by means of a mouse, lines appear. If I call g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(draw_things), NULL); my lines are displayed correctly, but buttons and labels are not displayed. My code looks like this:
int main(int argc, char *argv[]){
pthread_t tr1;
pthread_t tr2;
pthread_t *trs;
int rc = 0;
type j;
int16_t *id;
type Stop_Point;
GtkWidget *window;
GtkWidget *button;
GtkWidget *table;
GtkWidget *drawing_area;
g_thread_init (NULL);
gdk_threads_init ();
gdk_threads_enter ();
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request(window, width/1.6, height/1.33);
gtk_window_set_position(GTK_WINDOW(window), -1);
gtk_window_set_title (GTK_WINDOW (window), "Window");
g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 2);
table = gtk_table_new ( width/1.6, height/1.33, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
button = gtk_button_new_with_label ("next >>");
gtk_table_attach_defaults (GTK_TABLE (table), button, 1110, 1190, 750, 790);
gtk_widget_show (button);
button = gtk_button_new_with_label ("<< prev");
gtk_table_attach_defaults (GTK_TABLE (table), button, 1020, 1100 , 750, 790);
gtk_widget_show (button);
rc = pthread_create(&tr1, NULL, tr1_func, &id);
rc = pthread_create(&Generator, NULL, tr2_func, &Stop_Point);
trs = (pthread_t*)malloc(Num * sizeof(pthread_t));
for(j = 0; j < Num; j++) {
rc = pthread_create(trs + j, NULL, trs_func, id + j);
}
// g_signal_connect(G_OBJECT(window), "configure-event", GTK_SIGNAL_FUNC(draw_things), NULL);
g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(draw_things), NULL);
gtk_widget_show_all (window);
gtk_main ();
gdk_threads_leave ();
return 0;
}
Fnction for drawing looks like this
gboolean draw_things(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
GdkGC *gc;
gc=gdk_gc_new(GDK_DRAWABLE(widget->window));
gdk_gc_set_line_attributes(gc, 5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 5, 35, 1200, 35);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 1170, 45, 1200, 35);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 1170, 25 , 1200, 35);
// gtk_window_move (GTK_WINDOW(widget), 1,1);
return TRUE;
}
Any help is welcomed, because now I use "configure_event" and call gtk_window_move (GTK_WINDOW(widget), 0,0); every time when I need to draw the picture.

Related

Scrollable layout in GTK3

I'm trying my hand at writing a C program using GTK (GTK 3 to be precise) (up to now, my experience has mainly been using ObjC, Visual Studio and so on but Cross Platform FTW!)
I need to have a scrollable table, so I've been playing with some of the example code that I've found on the web. The only table code that I've been able to find so far grows the window, and pushes any other elements down the screen as rows are added. I need the table to be a fixed size and to scroll (leaving the header row visible, of course).
This is what I've got so far:
#include <gtk/gtk.h>
enum {
FILE_NAME,
FILE_OFFSET,
FILE_SIZE,
FILE_DESCRIPTION, /* Not used by the view, maybe used elsewhere */
COLOR, /* Just to show how the model can affect the view */
N_COLUMNS
};
void add_row (GtkWidget *widget, gpointer data) {
gtk_list_store_insert_with_values(data, NULL, -1,
COLOR, "blue",
-1);
}
void destroy (GtkWidget *widget,gpointer data) {
gtk_main_quit ();
}
gint main(gint argc, gchar **argv)
{
GtkListStore* model;
GtkWidget* view;
GtkTreeViewColumn* column;
gtk_init(&argc, &argv);
/* MODEL */
model = gtk_list_store_new(N_COLUMNS,
G_TYPE_STRING, /* FILE_NAME */
G_TYPE_UINT, /* FILE_OFFSET */
G_TYPE_UINT, /* FILE_SIZE */
G_TYPE_STRING, /* FILE_DESCRIPTION */
G_TYPE_STRING /* COLOR */
);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "test name",
FILE_OFFSET, 0,
FILE_SIZE, 10,
-1);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "Dummy",
FILE_OFFSET, 123,
COLOR, "black",
-1);
/* VIEW */
view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
g_object_unref(model);
column = gtk_tree_view_column_new_with_attributes("Name",
gtk_cell_renderer_text_new(),
"text", FILE_NAME,
"background", COLOR,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Offset",
gtk_cell_renderer_spin_new(),
"text", FILE_OFFSET,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Size",
gtk_cell_renderer_text_new(),
"text", FILE_SIZE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Test App");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
/* Button */
GtkWidget *button;
button = gtk_button_new_with_label ("Add row");
g_signal_connect (button, "clicked", G_CALLBACK(add_row), model);
/* Layoutbox */
GtkWidget *layout_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), layout_box);
/* Scrollview */
GtkWidget *scrollview = gtk_layout_new(NULL, NULL);
g_object_set(G_OBJECT(scrollview), "app-paintable", TRUE, NULL);
gtk_widget_add_events (scrollview, GDK_ALL_EVENTS_MASK);
gtk_layout_put (GTK_LAYOUT (scrollview), view, 10, 10);
gtk_widget_set_size_request(view, 300, 200);
gtk_container_add (GTK_CONTAINER (layout_box), scrollview); //view
gtk_widget_show_all(window);
GdkWindow *win = gtk_layout_get_bin_window (GTK_LAYOUT(scrollview));
gdk_window_set_events (win, gdk_window_get_events (win) | GDK_STRUCTURE_MASK);
gtk_main ();
return 0;
}
It is a bit of a mess at the moment! My apologies - that's partly inexperience with GTK and mostly multiple iterations in trying to get it to work.
At the moment the table displays very briefly before disappearing (that interesting behaviour only started when I tried to make it into a scroll box).
Note, I only want the table to scroll - not the entire window. In a perfect world, the table would be the width of the window (or layout that contains it) but limited to n pixels high, with a scrollbar if the height exceeds that limit.
I'm a simple guy though, so I also want any solution to be simple - so that I can wrap my brain around it!
Any ideas?
You are using a GtkLayout but the widget to use for scrolling is GtkScrolledWindow.
Here's the adapted code:
#include <gtk/gtk.h>
enum {
FILE_NAME,
FILE_OFFSET,
FILE_SIZE,
FILE_DESCRIPTION, /* Not used by the view, maybe used elsewhere */
COLOR, /* Just to show how the model can affect the view */
N_COLUMNS
};
void add_row (GtkWidget *widget, gpointer data) {
gtk_list_store_insert_with_values(data, NULL, -1,
COLOR, "blue",
-1);
}
void destroy (GtkWidget *widget,gpointer data) {
gtk_main_quit ();
}
gint main(gint argc, gchar **argv)
{
GtkListStore* model;
GtkWidget* view;
GtkTreeViewColumn* column;
gtk_init(&argc, &argv);
/* MODEL */
model = gtk_list_store_new(N_COLUMNS,
G_TYPE_STRING, /* FILE_NAME */
G_TYPE_UINT, /* FILE_OFFSET */
G_TYPE_UINT, /* FILE_SIZE */
G_TYPE_STRING, /* FILE_DESCRIPTION */
G_TYPE_STRING /* COLOR */
);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "test name",
FILE_OFFSET, 0,
FILE_SIZE, 10,
-1);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "Dummy",
FILE_OFFSET, 123,
COLOR, "black",
-1);
/* VIEW */
view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
g_object_unref(model);
column = gtk_tree_view_column_new_with_attributes("Name",
gtk_cell_renderer_text_new(),
"text", FILE_NAME,
"background", COLOR,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Offset",
gtk_cell_renderer_spin_new(),
"text", FILE_OFFSET,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Size",
gtk_cell_renderer_text_new(),
"text", FILE_SIZE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Test App");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
/* Button */
GtkWidget *button;
button = gtk_button_new_with_label ("Add row");
g_signal_connect (button, "clicked", G_CALLBACK(add_row), model);
/* Layoutbox */
GtkWidget *layout_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), layout_box);
/* Scrollview */
GtkWidget *scrollview = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add (GTK_CONTAINER (scrollview), view);
/* expand to fill all available space left in the window */
gtk_widget_set_hexpand(scrollview, TRUE);
gtk_widget_set_vexpand(scrollview, TRUE);
gtk_container_add (GTK_CONTAINER (layout_box), scrollview); //view
gtk_container_add (GTK_CONTAINER (layout_box), button);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}

Is it possible to put GtkLayouts inside GtkLayout?

I want to put 2 GtkLayouts into GtkLayout. But, it seems to not be working. Anyone knows why ? or, there are some restrictions using gtk components.
#include <gtk/gtk.h>
int main( int argc, char *argv[] )
{
GtkWidget *window, *main_container, *t, *p;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "layout test");
gtk_window_maximize(GTK_WINDOW(window));
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
main_container = gtk_layout_new(NULL, NULL);
GdkColor color;
gdk_color_parse ("green", &color);
gtk_widget_modify_bg( GTK_WIDGET(main_container), GTK_STATE_NORMAL, &color);
gdk_color_parse ("red", &color);
t = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(t), 300, 300);
gtk_widget_modify_bg( GTK_WIDGET(t), GTK_STATE_NORMAL, &color);
gdk_color_parse ("yellow", &color);
p = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(p), 300, 300);
gtk_widget_modify_bg( GTK_WIDGET(p), GTK_STATE_NORMAL, &color);
gtk_layout_put( GTK_LAYOUT(main_container), t, 0, 0 );
gtk_layout_put( GTK_LAYOUT(main_container), p, 0, 300 );
gtk_container_add(GTK_CONTAINER(window), main_container);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
I found the answer. If the container is appended into another container, it should be treated as a widget. Therefore, uses gtk_widget_set_size_request instead of gtk_layout_set_size will solve this problem.

c GTK3 Text should scoll upward and not hide

here is my problem: I just put a gtk_text_view_new() in a gtk_scrolled_window_new(). Now when I write in the textField, at the end of the gtk_widget_set_size_request->high the text is hidden and the whole text does not scroll upwards as I want.
-> The textfield should automatically scroll upwards and show its last line.
#include <gtk/gtk.h>
int main(int argc, char **argv) {
gtk_init(&argc, &argv);
GtkWidget *window;
GtkWidget *myGrid;
GtkWidget *scollwindow;
GtkWidget *textField;
GtkTextBuffer *buffer;
GtkWidget *quitbutton;
//---------------------widgets-------------------------------
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
quitbutton = gtk_button_new_with_label("QUIT");
myGrid = gtk_grid_new ();
//---------------------textField-------------------------------
textField = gtk_text_view_new ();
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textField));
gtk_text_buffer_set_text (buffer, "Hello, this is some text, ", -1);
//---------------------insert textField in scrollwindow-------------------------------
scollwindow = gtk_scrolled_window_new (NULL,NULL);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scollwindow), textField);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scollwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
//---------------------widgets size-------------------------------
gtk_widget_set_size_request (scollwindow, 200, 200);
gtk_widget_set_size_request (window, 200, 200);
//---------------------grid attache-------------------------------
gtk_grid_attach(GTK_GRID(myGrid), scollwindow, 0, 0, 1, 1);
gtk_grid_attach(GTK_GRID(myGrid), quitbutton, 0, 1, 1, 1);
//---------------------add to grid-------------------------------
gtk_container_add(GTK_CONTAINER(window), myGrid);
//---------------------signals-------------------------------
g_signal_connect(quitbutton, "clicked", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(window, "destroy", gtk_main_quit, NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Got it, just change line " gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scollwindow), textField);" to "gtk_container_add (GTK_CONTAINER(scollwindow), textField);"

GtkEntry manipulation

I'm trying to make a small program to manipilate data between GtkEntry fields. To do this I'm using global variables. But using g_print functions to show me the contents I get NULL data! What is wrong in my way?
#include <gtk/gtk.h>
const gchar *entry0_text;
const gchar *entry1_text;
const gchar *entry2_text;
static void my_function (GtkWidget *widget, GtkWidget *entry)
{
g_print ("Entry0 contents: %s\n", gtk_entry_get_text (GTK_ENTRY (entry)));
g_print ("Entry1 contents: %s\n", *entry0_text);
g_print ("Entry2 contents: %s\n", *entry1_text);
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
GtkWidget *entry0;
GtkWidget *entry1;
GtkWidget *entry2;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), ":-)");
gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
gtk_container_set_border_width (GTK_CONTAINER (window), 20);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (grid));
entry0 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry0, 0, 0, 1, 1);
entry0_text = gtk_entry_get_text (GTK_ENTRY (entry0));
entry1 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry1, 1, 0, 1, 1);
entry1_text = gtk_entry_get_text (GTK_ENTRY (entry1));
entry2 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry2, 0, 1, 1, 1);
entry2_text = gtk_entry_get_text (GTK_ENTRY (entry2));
button = gtk_button_new ();
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
g_signal_connect (button, "clicked", G_CALLBACK (my_function), entry0);
gtk_widget_show_all (window);
}
int
main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
I'm using Debian GNU/Linux and compiling with a script like this:
gcc pkg-config --libs --cflags gtk+-3.0 -o $2 $1
Thank You!
The values for entry0_text - entry2.text are retrieved during the startup of your program. But since there has been no entry made yet, they contain empty strings.
You have to use gtk_entry_get_text for all of your entry widgets inside the callback function my_function, not inside the activate function.
Besides that, you are using the second and third g_print incorrectly; you should use
g_print ("Entry1 contents: %s\n", entry1_text);
g_print ("Entry2 contents: %s\n", entry2_text);
Remember that after your program has started, entry1_text and entry2_text contain empty strings. But with *entry1_text and *entry2_text you won't receive the empty string, but the first element of this string, which is the terminating '\0' null character, this is why you receive a 'null' for these g_prints. So use entry1_text instead of *entry1_text.
The following code is working properly; I've used the entry widgets and strings as global variables for simplicity.
#include <gtk/gtk.h>
#include <string.h>
GtkWidget *entry0;
GtkWidget *entry1;
GtkWidget *entry2;
const gchar *entry0_text;
const gchar *entry1_text;
const gchar *entry2_text;
static void my_function (void)
{
entry0_text = gtk_entry_get_text (GTK_ENTRY (entry0));
entry1_text = gtk_entry_get_text (GTK_ENTRY (entry1));
entry2_text = gtk_entry_get_text (GTK_ENTRY (entry2));
g_print ("Entry0 contents: %s\n", entry0_text);
g_print ("Entry1 contents: %s\n", entry1_text);
g_print ("Entry2 contents: %s\n", entry2_text);
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), ":-)");
gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
gtk_container_set_border_width (GTK_CONTAINER (window), 20);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (grid));
entry0 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry0, 0, 0, 1, 1);
entry1 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry1, 1, 0, 1, 1);
entry2 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry2, 0, 1, 1, 1);
button = gtk_button_new ();
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
g_signal_connect (button, "clicked", G_CALLBACK (my_function), NULL);
gtk_widget_show_all (window);
}
int
main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}

How to make gtk_window_set_position of gtk work?

I want to set the position of the window using gtk_window_set_position
but it seems that after the window is created, the gtk_window_set_position will not take effect.
I'm wondering how to call gtk_window_set_position after the window shows up, i.e. a button event?
I just wrote a minimal working example that implements two approaches. One approach uses gtk_window_move and the other gtk_window_set_position.
If you have the gtk+ reference at hand the code should be self explanatory.
#include <gtk/gtk.h>
#include <glib.h>
void
button1_clicked_cb (GtkWidget * widget, GtkWindow * window)
{
GdkWindow *root;
gint width, height, rwidth, rheight;
gtk_window_get_size (window, &width, &height);
root = gtk_widget_get_root_window (GTK_WIDGET (window));
gdk_window_get_geometry (root, NULL, NULL, &rwidth,
&rheight);
gtk_window_move (window, (rwidth - width) / 2,
(rheight - height) / 2);
}
void
button2_clicked_cb (GtkWidget * widget, GtkWindow * window)
{
gtk_widget_hide (GTK_WIDGET (window));
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_show_all (GTK_WIDGET (window));
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *box;
GtkWidget *button1;
GtkWidget *button2;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
button1 = gtk_button_new_with_label ("approach 1");
button2 = gtk_button_new_with_label ("approach 2");
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_box_pack_start (GTK_BOX (box), button1, TRUE, TRUE,
10);
gtk_box_pack_start (GTK_BOX (box), button2, TRUE, TRUE,
10);
gtk_container_add (GTK_CONTAINER (window), box);
gtk_widget_show_all (window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (button1, "clicked",
G_CALLBACK (button1_clicked_cb),
window);
g_signal_connect (button2, "clicked",
G_CALLBACK (button2_clicked_cb),
window);
gtk_main ();
return 0;
}

Resources