Is it possible to put GtkLayouts inside GtkLayout? - c

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.

Related

How to add css style context providers for all labels in a grid?

I am trying to set the background color of all labels in GtkGrid. Here is a simplified example:
#include <gtk/gtk.h>
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label1 = gtk_label_new("Hello world!");
gtk_widget_set_hexpand( label1, TRUE);
gtk_grid_attach(GTK_GRID (grid), label1, 0,0,1,1);
GtkWidget *label2 = gtk_label_new("Simple Gtk example");
gtk_widget_set_hexpand( label2, TRUE);
gtk_grid_attach(GTK_GRID (grid), label2, 0,1,1,1);
GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (
provider, "label {background-color: #AAAAAA;}", -1, NULL);
GtkStyleContext *context = gtk_widget_get_style_context (grid);
gtk_style_context_add_provider(
context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new(
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
However, adding the style context provider to the grid's context (as shown above) does not work.
I've modified your code, this will change the background of the labels:
#include <gtk/gtk.h>
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label1 = gtk_label_new("Hello world!");
gtk_widget_set_hexpand( label1, TRUE);
gtk_grid_attach(GTK_GRID (grid), label1, 0,0,1,1);
GtkWidget *label2 = gtk_label_new("Simple Gtk example");
gtk_widget_set_hexpand( label2, TRUE);
gtk_grid_attach(GTK_GRID (grid), label2, 0,1,1,1);
GtkCssProvider *provider = gtk_css_provider_new ();
GdkDisplay *display = gdk_display_get_default();
GdkScreen *screen = gdk_display_get_default_screen (display);
gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_css_provider_load_from_data (
provider, "GtkLabel { background-color: #AAAAAA;}", -1, NULL);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new(
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
Result:

How can I add GtkEventBox in scrolled windows layout?

I have a GTK+2 program which combining GtkScrolledWindow and GtkLayout. It works fine. But, I found if I put a GtkEvent object to GtkLayout, it will not display properly. Anybody knows why ? Thanks.
#include <gtk/gtk.h>
int main( int argc, char *argv[] )
{
GtkWidget *window, *button, *layout, *eventbox, *scrollwindow;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 150, 150);
button = gtk_button_new_with_label ("button");
layout = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(layout), 300, 300);
scrollwindow = gtk_scrolled_window_new(GTK_LAYOUT(layout)->hadjustment, GTK_LAYOUT(layout)->vadjustment);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_layout_put( GTK_LAYOUT(layout), button, 50, 250 );
/* uncomment to use eventbox
eventbox = gtk_event_box_new();
gtk_container_add( GTK_CONTAINER(eventbox), layout);
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrollwindow), eventbox);
*/
// comment this line when use eventbox
gtk_container_add( GTK_CONTAINER(scrollwindow), layout);
gtk_container_add((GtkContainer*)window, scrollwindow);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
The picture if the eventbox is used.
I found it does not have to use GtkEventBox here. The GtkLayout can capture events directly.
The following widgets do not have an associated window. So, It should be used with the GtkEventBox if you want to capture events.
GtkAlignment
GtkArrow
GtkBin
GtkBox
GtkImage
GtkItem
GtkLabel
GtkPaned
GtkPixmap
GtkScrolledWindow
GtkSeparator
GtkTable
GtkViewport
GtkAspectFrame
GtkFrame
GtkVPaned
GtkHPaned
GtkVBox
GtkHBox
GtkVSeparator
GtkHSeparator
The fixed program :
#include <gtk/gtk.h>
static gboolean button_press_event( GtkWidget *widget, GdkEventButton *event ) {
if (event->button == 1 ) printf("but down %i , %i\n", (int)event->x, (int)event->y);
return TRUE;
}
int main( int argc, char *argv[] )
{
GtkWidget *window, *button, *layout, *eventbox, *scrollwindow;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 150, 150);
button = gtk_button_new_with_label ("button");
layout = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(layout), 300, 300);
scrollwindow = gtk_scrolled_window_new(gtk_layout_get_hadjustment(layout), gtk_layout_get_vadjustment(layout));
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_layout_put( GTK_LAYOUT(layout), button, 50, 250 );
gtk_container_add( GTK_CONTAINER(scrollwindow), layout);
gtk_container_add(GTK_CONTAINER(window), scrollwindow);
g_signal_connect (layout, "button_press_event", G_CALLBACK (button_press_event), NULL);
gtk_widget_set_events(layout, GDK_EXPOSURE_MASK
| GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK
| GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
The result of clicking on GtkLayout :

drawing on window using gtk 2.0

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.

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