using GtkAlignment for horizontal alignment - gtk

I am new to GTK+ world and trying to learn it from Foundations of GTK+ Development.
Mean while I am getting some problem in using GtkAlignment widget, as in the code below.
Even if I change the value of either one of the below I am not getting the Ok and calcel button getting aligned to right.
GtkWidget* halign = gtk_alignment_new(0, 0, 0, 0);
GtkWidget* halign = gtk_alignment_new(0, 1, 0, 0);
I think I'm missing something, but not getting exactly
Note: I am using GTK+3 on windows 7
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), "Gtk Alignment Sample");
gtk_container_set_border_width(GTK_CONTAINER(window), 5);
gtk_widget_set_size_request(window, 250, 400);
g_signal_connect(window, "delete_event", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget* ok_button = gtk_button_new_from_stock(GTK_STOCK_OK);
GtkWidget* cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
GtkWidget* hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(hbox), ok_button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), cancel_button, FALSE, FALSE, 0);
GtkWidget* halign = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), hbox);
GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);
GtkWidget* valign = gtk_alignment_new(0, 1, 0, 0);
gtk_container_add(GTK_CONTAINER(valign), vbox);
gtk_container_add(GTK_CONTAINER(window), valign);
gtk_widget_show_all(window);
gtk_main();
return 0;
}

Quote from the docs:
Note that the desired effect can in most cases be achieved by using
the "halign", "valign" and "margin" properties on the child widget, so
GtkAlignment should not be used in new code.
Try to just use
gtk_widget_set_alignment (button_ok, GTK_ALIGN_END);
gtk_widget_set_alignment (button_cancel, GTK_ALIGN_END);
//or
gtk_widget_set_alignment (hbox, GTK_ALIGN_END);
and remove all alignment widgets

Related

wxTreeCtrl always shows selected item as focused, on GTK2 and GTK3

I'm running Kubuntu 18.04 with the Breeze theme selected for both GTK2 and GTK3. Running the 'treectrl' program from the 'examples' directory on the source distribution creates the window shown below:
The window has a wxTreeCtrl with some items and a text control showing a log. If I click on an item on the tree it's background turns blue, indicating both selection and focus on the wxTreeCtrl. If I them click on the text control the caret appears, indicating that the text control has taken the focus but the selected item on the tree remains with a blue background.
Other (pretty much all other) controls change the background colour of the selection to a different colour to indicate selection without focus.
Why doesn't wxTreeCtrl follow this and can it be reverted back to the normal behaviour?
------ Edit -------
I've build a native GTK3 app using the code :
#include <gtk/gtk.h>
enum {
COLUMN = 0,
NUM_COLS
};
GtkTreeModel *create_and_fill_model(void) {
GtkTreeStore *treestore;
GtkTreeIter toplevel, child;
treestore = gtk_tree_store_new(NUM_COLS,
G_TYPE_STRING);
gtk_tree_store_append(treestore, &toplevel, NULL);
gtk_tree_store_set(treestore, &toplevel,
COLUMN, "Scripting languages",
-1);
gtk_tree_store_append(treestore, &child, &toplevel);
gtk_tree_store_set(treestore, &child,
COLUMN, "Python",
-1);
gtk_tree_store_append(treestore, &child, &toplevel);
gtk_tree_store_set(treestore, &child,
COLUMN, "Perl",
-1);
gtk_tree_store_append(treestore, &child, &toplevel);
gtk_tree_store_set(treestore, &child,
COLUMN, "PHP",
-1);
return GTK_TREE_MODEL(treestore);
}
GtkWidget *create_view_and_model(void) {
GtkTreeViewColumn *col;
GtkCellRenderer *renderer;
GtkWidget *view;
GtkTreeModel *model;
view = gtk_tree_view_new();
col = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(col, "Programming languages");
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(col, renderer, TRUE);
gtk_tree_view_column_add_attribute(col, renderer,
"text", COLUMN);
model = create_and_fill_model();
gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
g_object_unref(model);
return view;
}
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *view;
GtkTreeSelection *selection;
GtkWidget *vbox;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(window), "Tree view");
gtk_widget_set_size_request(window, 350, 300);
vbox = gtk_vbox_new(FALSE, 2);
gtk_container_add(GTK_CONTAINER(window), vbox);
view = create_view_and_model();
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 1);
GtkWidget *entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 1);
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
that shows a window with a Tree View control on top and a Entry control on bottom. The behaviour is the same, as seen in the picture:

GtkNotebook does not show tab label content

In an application with a GtkNotebook and a GtkBox as tab label, the tab label is visible, but the content of the tab label is not. How can I make the content of the tab label visible?
#include <gtk/gtk.h>
int main (int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget* notebook = gtk_notebook_new();
GtkWidget* page_content = gtk_label_new("Content");
GtkWidget* tab_label = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
GtkWidget* label_content_1 = gtk_label_new("Title");
GtkWidget* label_content_2 = gtk_button_new_with_label("Close");
gtk_box_pack_start(GTK_BOX(tab_label), label_content_1, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(tab_label), label_content_2, FALSE, FALSE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_content, tab_label);
gtk_container_add(GTK_CONTAINER(window), notebook);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
}
I got it working by showing the widgets in GTK_BOX explicitly, and calling gtk_notebook_set_show_tabs:
#include <gtk-3.0/gtk/gtk.h>
int main (int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget* notebook = gtk_notebook_new();
GtkWidget* page_content = gtk_label_new("Content");
GtkWidget* tab_label = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
GtkWidget* label_content_1 = gtk_label_new("Title");
GtkWidget* label_content_2 = gtk_button_new_with_label("Close");
gtk_widget_show(GTK_WIDGET(label_content_1));
gtk_widget_show(GTK_WIDGET(label_content_2));
gtk_widget_show(GTK_WIDGET(tab_label));
gtk_box_pack_start(GTK_BOX(tab_label), label_content_1, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(tab_label), label_content_2, FALSE, FALSE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_content, tab_label);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), TRUE);
gtk_container_add(GTK_CONTAINER(window), notebook);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
}
I am not in a position to explain the reason behind that though.
You may find this link about tabs with close button interesting.

stopping buttons in hbox to expand vertically

In gtk+3.0 in windows 7.
I am creating a button and packed them into horizontal box. I have set the expand to FALSE. Now the button is not expanding in x direction but expanding vertically. I don't want the button to expand vertically also.
int main(int argc, char* argv[]) {
gtk_init(&argc, &argv);
GtkWidget* window = NULL;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Layout using BOX");
//gtk_widget_set_size_request(window, 50, 300);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
g_signal_connect(window, "delete_event", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget* button[5] = {NULL};
for(int i = 0; i < 5; ++i) {
std::stringstream buton_label;
buton_label << "Button ";
buton_label << (i + 1);
button[i] = gtk_button_new_with_label(buton_label.str().c_str());
gtk_widget_set_hexpand(button[i], FALSE);
g_signal_connect(button[i], "clicked", G_CALLBACK(button_clicked_cb), (gpointer)window);
}
GtkWidget *hbox = NULL;
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
//hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
for(int i = 0; i < 5; ++i) {
gtk_box_pack_start(GTK_BOX(hbox), button[i], FALSE, TRUE, 10);
}
gtk_container_add(GTK_CONTAINER(window), hbox);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
In GTK 3, the widget tells the container how it wants to be expanded (was the opposite in GTK 2). So you need to use the hexpand and vexpand properties of your widget for horizontal and vertical expanding, with functions like gtk_widget_set_hexpand. Same for alignment with halign and valign.
EDIT:
As an exception to the rule, read the documentation of gtk_box_pack_start and its fill parameter:
fill
TRUE if space given to child by the expand option is actually
allocated to child , rather than just padding it. This parameter has
no effect if expand is set to FALSE. A child is always allocated the
full height of a horizontal GtkBox and the full width of a vertical
GtkBox. This option affects the other dimension.
So if you want to control the other dimension, put the horizontal box inside a vertical box where you'll set expand to FALSE when calling gtk_box_pack_start.
#include <gtk/gtk.h>
#include <sstream>
int main(int argc, char* argv[]) {
gtk_init(&argc, &argv);
GtkWidget* window = NULL;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Layout using BOX");
//gtk_widget_set_size_request(window, 50, 300);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
g_signal_connect(window, "delete_event", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget* button[5] = {NULL};
for(int i = 0; i < 5; ++i) {
std::stringstream buton_label;
buton_label << "Button ";
buton_label << (i + 1);
button[i] = gtk_button_new_with_label(buton_label.str().c_str());
gtk_widget_set_hexpand(button[i], FALSE);
// g_signal_connect(button[i], "clicked", G_CALLBACK(button_clicked_cb), (gpointer)window);
}
GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
for(int i = 0; i < 5; ++i) {
gtk_box_pack_start(GTK_BOX(hbox), button[i], FALSE, FALSE, 10);
}
gtk_container_add(GTK_CONTAINER(vbox), hbox);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Intead of using boxes (which may be a bit difficult to use because you have to figure out how things expand), try using the more powerful GtkGrid. It works with the hexpand/vexpand properties of the chidren like I said above.

How I can maximize GtkGrid to fill the entire GtkWindow?

I made a basic GtkGrid application with a simple layout but I can't make the GtkGrid fill the entire GtkWindow. This is the code for creating the layout:
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
GtkWidget *grid = gtk_grid_new();
g_signal_connect(window,"destroy", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget *vpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
gtk_paned_set_position (GTK_PANED (vpaned), 400);
GtkWidget *label = gtk_label_new("Label1111111111111111111111111111111");
GtkWidget *label2 = gtk_label_new("Label2");
GtkWidget *label3 = gtk_label_new("Label3");
GtkWidget *label4 = gtk_label_new("Label4");
gtk_paned_pack1 (GTK_PANED (vpaned), label, FALSE, TRUE);
gtk_paned_pack2 (GTK_PANED (vpaned), label2, FALSE, TRUE);
gtk_widget_show (label);
gtk_widget_show (label2);
gtk_widget_show (label3);
gtk_widget_show (label4);
gtk_widget_show (vpaned);
gtk_grid_attach(GTK_GRID(grid), label3, 0,0,1,1);
gtk_grid_attach(GTK_GRID(grid), vpaned, 0,1,1,1);
gtk_grid_attach(GTK_GRID(grid), label4, 0,2,1,1);
gtk_widget_show(grid);
gtk_container_add(GTK_CONTAINER(window), grid);
gtk_widget_show (window);
You may have a look at expand property and assure it is set to TRUE (default if you do your UI within glade designer)

Gtk, How to scroll at bottom of viewport list?

I have created one list with GtkVBox and GtkViewPort.
and i am doing the scroll by two up/down GtkButtons.
GtkAdjustment* adjustment;
adjustment = gtk_viewport_get_vadjustment(GTK_VIEWPORT(viewport_ptr));
gtk_adjustment_set_value(adjustment, gtk_adjustment_get_value(adjustment)+(gdouble)SCROLL_SIZE);
gtk_widget_show_all(viewport_ptr);
But when I add the widget to VBox it gets added at the end of the VBox as I am using gtk_box_pack_start. So i want to scroll viewport up to this newly added last widget which is at bottom of the list.
Did you try just setting the adjustment to the maximum value:
gtk_adjustment_set_value(adjustment, gtk_adjustment_get_upper(adjustment));
Note that you might need to delay this, or trigger it from a suitable event, since the upper bound will change as the scrolled vbox grows.
My suggestion would be to hook it into the size-allocate signal of the GtkVBox.
Here's an example that shows what #unwind means when he suggests hooking the adjustment into the size-allocate signal.
/***
This basic example program shows how to (automatically) move the
scrollbar of a GTK+ text view to the very bottom after text has been added.
Public domain code by N.L.M. de Jonge.
gcc `pkg-config gtk+-3.0 --cflags` -O2 -std=c99 -g -pedantic -Wall \
-Wextra -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes \
-Wmissing-prototypes -D_REENTRANT example.c -o example `pkg-config \
gtk+-3.0 --libs`
***/
#include <gtk/gtk.h>
#include <stdlib.h>
GtkAdjustment *adj;
GtkWidget *scroll;
GtkTextBuffer *buffer;
GtkTextIter iter;
int iCounter;
void ScrollToEnd (GtkWidget *widget, GdkRectangle *allocation);
void Add (GtkButton *button);
/*****************************************************************************/
void ScrollToEnd (GtkWidget *widget, GdkRectangle *allocation)
/*****************************************************************************/
{
if (widget != NULL) { }
if (allocation != NULL) { }
adj = gtk_scrolled_window_get_vadjustment
(GTK_SCROLLED_WINDOW (scroll));
gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj));
}
/*****************************************************************************/
void Add (GtkButton *button)
/*****************************************************************************/
{
char sText[10];
if (button != NULL) { }
iCounter++;
snprintf (sText, 10, "\n%i", iCounter);
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
g_locale_to_utf8 (sText, -1, NULL, NULL, NULL), -1, "red_fg", NULL);
/*** We just added text, but we do NOT call ScrollToEnd() here. ***/
}
/*****************************************************************************/
int main (int argc, char *argv[])
/*****************************************************************************/
{
GtkWidget *window, *box, *grid, *text, *button;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "delete_event",
G_CALLBACK (exit), NULL);
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_widget_realize (window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), box);
gtk_widget_show (box);
grid = gtk_grid_new();
gtk_widget_show (grid);
gtk_box_pack_start (GTK_BOX (box), grid, TRUE, TRUE, 0);
scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_size_request (scroll, 200, 200);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
/***/
/*** We call ScrollToEnd() if scroll receives the size-allocate signal. ***/
/***/
g_signal_connect (scroll, "size-allocate", G_CALLBACK (ScrollToEnd), NULL);
gtk_grid_attach (GTK_GRID (grid), scroll, 0, 0, 1, 1);
g_object_set (scroll, "vexpand", TRUE, NULL);
g_object_set (scroll, "margin", 10, NULL);
gtk_widget_show (scroll);
text = gtk_text_view_new();
gtk_container_add (GTK_CONTAINER (scroll), text);
gtk_widget_show (text);
buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (buffer, "red_fg", "foreground", "red", NULL);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (text), buffer);
button = gtk_button_new_with_label ("Add");
g_signal_connect (button, "clicked", G_CALLBACK (Add), NULL);
gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1);
g_object_set (button, "hexpand", TRUE, NULL);
gtk_widget_show (button);
gtk_widget_show (window);
iCounter = 0;
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert (buffer, &iter, g_locale_to_utf8
("Click \"Add\" to add numbers.", -1, NULL, NULL, NULL), -1);
gtk_main();
return 0;
}
/*****************************************************************************/
As a bonus it shows how to add colored text.