For my GUI having some buttons. If I were to change or update the label of any random button I select from the list what should I do?
The initial name of the button is written in button properties. My GUI is designed in Glade.
And now I will enter the new name in entry-text in my GUI.
I have created an update button for this. How to do it in Gtk ofcourse.
The related codes are as follows:
Creation of button in the window and find it.
UpdateButton = GTK_WIDGET( gtk_builder_get_object( builder, "UpdateButton" ) );
gtk_signal_connect (GTK_OBJECT (UpdateButton), "clicked", GTK_SIGNAL_FUNC (Update_Data), NULL);
On update button clicked.
void Update_Data( GtkWidget *widget, gpointer data)
{
const gchar *entry_text1;
const gchar *entry_text2;
const gchar *entry_text3;
g_print ("You have clicked Update... - %s was pressed\n", (char *) data);
entry_text1 = gtk_entry_get_text (GTK_ENTRY (entry1));
entry_text2 = gtk_entry_get_text (GTK_ENTRY (entry2));
entry_text3 = gtk_entry_get_text (GTK_ENTRY (entry3));
char sql[300];
sprintf(sql, "UPDATE DEVICES set NAME='%s ',\nUSERNAME='%s ',\nPASSWORD='%s '\nwhere ID=%s;"
, entry_text1, entry_text2, entry_text3, updateid);
//updateid is the ID taken from the array when a button is clicked
inserDatabase("myDatabase.db", sql);
getlastEntry(); //for taking the last entered info
updateData(sql); //for updating in database
}
If more information is required I will get you. Please do ask!
Your question is unclear, but if I understand you correctly...
You get the buttons...
GtkButton *click_button; // Button to click
GtkButton *change_button; // Button that changes label
click_button = GTK_BUTTON (gtk_builder_get_object (builder, "click_button"));
change_button = GTK_BUTTON (gtk_builder_get_object (builder, "change_button"));
Define a function for the click event to set the label...
static void
change_button_label (GtkWidget *click_button,
gpointer user_data)
{
GtkButton *change_button = (GtkButton *) user_data;
gtk_button_set_label (change_button, "New Label");
}
Connect the click signal function to the button, and pass it the change button...
g_signal_connect (click_button, "clicked", G_CALLBACK (change_button_label), change_button);
Related
The show signal seems to only be called the first time a widget is shown. If I call gtk_widget_show on the widget in question, if it has already been shown, any functions passed to g_signal_connect to the widget in question with the show signal will not be called. I attempted to use the show signal for a button whose text is determined by an external state that the button changes, so when the button first becomes visible it successfully shows the initial state, but even though I change the state in the button handler then call gtk_widget_show, the text is not updated when the button is clicked. How can I configure a widget to run on EVERY show event, not just the first.
Requirement:
update button label based on state
state change happen on button click
One solution could be to update the status when the button is clicked, and then set the button's label, e.g. like this:
update_state();
gtk_button_set_label(button, state);
If more parts of the user interface than just the button should be updated, one could think about introducing a separate function updateUI.
A small demo could look like this:
#include <gtk/gtk.h>
static int cnt;
static char state[16];
static void update_state() {
snprintf(state, sizeof(state), "clicked %d", cnt++);
}
static void button_show(__unused GtkWidget *widget, __unused gpointer data) {
g_print("show\n");
}
static void button_clicked(GtkButton *button, __unused gpointer data) {
g_print("clicked\n");
update_state();
gtk_button_set_label(button, state);
}
static void buildUI(GApplication *app, __unused gpointer data) {
GtkWidget *window = gtk_application_window_new(GTK_APPLICATION(app));
gtk_window_set_title(GTK_WINDOW(window), "GtkButton");
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_container_set_border_width(GTK_CONTAINER(window), 15);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
GtkWidget *button = gtk_button_new();
gtk_button_set_label(GTK_BUTTON(button), state);
gtk_widget_set_size_request(button, 80, 32);
gtk_widget_set_halign(button, GTK_ALIGN_START);
gtk_widget_set_valign(button, GTK_ALIGN_START);
gtk_container_add(GTK_CONTAINER(window), button);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(button_clicked), NULL);
g_signal_connect(G_OBJECT(button), "show",
G_CALLBACK(button_show), NULL);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(GTK_WIDGET(window));
}
int main(int argc, char *argv[]) {
GtkApplication *app = gtk_application_new("com.example.MyApp", G_APPLICATION_FLAGS_NONE);
update_state();
g_signal_connect(app, "activate", G_CALLBACK(buildUI), NULL);
g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return 0;
}
It updates the label whenever the button is clicked.
I'm trying to implement the Ctrl+C shortcut a widget without it disturbing other defined shortcuts.
Problem
My window looks like this:
GtkWindow
GtkEntry
GtkToggleButton
Part of the code
// --- add checkbox ---
GtkWidget * checkbutton = gtk_check_button_new_with_label("My Checkbox");
gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(checkbutton));
// --- setup checkbox shortcut ---
GtkAccelGroup * accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
gtk_widget_add_accelerator(checkbutton, "clicked", accel_group,
GDK_KEY_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
g_signal_connect(checkbutton, "clicked", G_CALLBACK(onCopyCheckbox), NULL);
// problem: this event fires, even if GtkEntry is focussed
// it then block the <kbd>Ctrl+C</kbd>-Event of GtkEntry
Expected behaviour
If GtkEntry is focussed and Ctrl+C is pressed, the function callback1() should be triggered.
If GtkToggleButton is focussed and Ctrl+C is pressed, it should print "onCopyCheckbox() called\n".
Actual behavior
If GtkEntry is focussed and Ctrl+C is pressed, "onCopyCheckbox() called\n" gets printed and nothing gets copied.
If GtkToggleButton is focussed and Ctrl+C is pressed, "onCopyCheckbox() called\n" gets printed.
Please do not...
tell me I should use a different shortcut / accelerator.
Full compilable and executable code:
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
// ------------------------------------------------------------
void
onCopyCheckbox (GtkWidget *widget,
GdkDragContext *context,
gpointer user_data)
{
printf("onCopyCheckbox() called\n");
}
// ------------------------------------------------------------
void fillWindow (GtkWindow * window)
{
// ------- create layout ------------
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(vbox));
// --- add line edit ---
GtkWidget * lineedit = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(lineedit));
// --- add checkbox ---
GtkWidget * checkbutton = gtk_check_button_new_with_label("My Checkbox");
gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(checkbutton));
// --- setup checkbox shortcut ---
GtkAccelGroup * accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
gtk_widget_add_accelerator(checkbutton, "clicked", accel_group,
GDK_KEY_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
g_signal_connect(checkbutton, "clicked", G_CALLBACK(onCopyCheckbox), NULL);
// problem: this event fires, even if GtkEntry is focussed
// it then block the <kbd>Ctrl+C</kbd>-Event of GtkEntry
}
// ------------------------------------------------------------
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
GtkWindow * window;
{
window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (window, "Window title");
gtk_window_set_default_size (window, 200, 200);
g_signal_connect(window, "destroy", gtk_main_quit, NULL);
}
fillWindow(window);
gtk_widget_show_all ((GtkWidget*)window);
gtk_main();
return 0;
}
// ------------------------------------------------------------
Imagine you want to spawn the function below on Ctrl+C while the checkbox is focussed.
void
shortcutAction(GSimpleAction* a, GVariant * b, gpointer c){
printf("shortcutAction() called\n");
}
This is how you setup your checkbox
// --- add checkbox ---
GtkWidget * checkbox = gtk_check_button_new_with_label("My Checkbox");
gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(checkbox));
// ========= setup checkbox shortcut ==============
GtkApplication * app = GTK_APPLICATION(g_application_get_default());
// ------- Part 1: create the action itself -----------
// All the action you want to add go in one ActionGroup
GSimpleActionGroup * group = g_simple_action_group_new();
// define all action you want to have
// these action can be basically seen as some kind of signal
static const GActionEntry actions[] {
{ .name="print", .activate=shortcutAction}
};
// ActionGroup.add(actions[])
g_action_map_add_action_entries(G_ACTION_MAP(group), actions, G_N_ELEMENTS(actions), NULL);
// Widget.addActionGroup(ActionGroup) // connect widget and action group
// No you also create a name for the group. Here "checkbox" (but can be anything)
gtk_widget_insert_action_group (GTK_WIDGET(checkbox), "checkbox", G_ACTION_GROUP(group));
// ------- Part 2: create the shortcut to create the action --------
const gchar * const shortcuts[] = { "<Ctrl>C", NULL };
gtk_application_set_accels_for_action (app, "checkbox.print", shortcuts);
Remarks
As you see in the code, there's a strict difference between
defining actions
defining shortcuts
On on GTK window there is a red close icon rendered in the title bar. Normally when you click on this, the window is closed and it's resources released.
Is there a way of intercepting the normal flow to prevent the window from being destroyed so that I can show it again later? i.e. I want to hide the window not close/destroy it.
This is what I have so far.
void destroy_window_callback(GtkWidget* widget, WebWindow_Linux* source)
{
printf("Don't destroy the window, just hide it.\n");
}
g_signal_connect(web_window, "destroy", G_CALLBACK(destroy_window_callback), this);
This is probably what you need
#include <gtk/gtk.h>
void
on_button_clicked(GtkButton *button, gpointer data)
{
GtkWidget *widget;
widget = (GtkWidget *) data;
if (widget == NULL)
return;
gtk_widget_show(widget);
return;
}
gboolean
on_widget_deleted(GtkWidget *widget, GdkEvent *event, gpointer data)
{
gtk_widget_hide(widget);
return TRUE;
}
int
main(int argc, char **argv)
{
GtkWidget *window1;
GtkWidget *window2;
GtkWidget *button;
gtk_init(&argc, &argv);
window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("Show again...");
g_signal_connect(G_OBJECT(window1),
"destroy", gtk_main_quit, NULL);
g_signal_connect(G_OBJECT(window2),
"delete-event", G_CALLBACK(on_widget_deleted), NULL);
g_signal_connect(G_OBJECT(button),
"clicked", G_CALLBACK(on_button_clicked), window2);
gtk_container_add(GTK_CONTAINER(window1), button);
gtk_widget_set_size_request(window1, 300, 100);
gtk_widget_set_size_request(window2, 300, 100);
gtk_widget_show_all(window1);
gtk_widget_show(window2);
gtk_main();
return 0;
}
We basically have three widgets, two top level windows and a button. The first window has it's "destroy" event connected to gtk_main_quit() quitting the application when the window's close button is pressed. The second window has it's "delete-event" connected to a custom function. This is the important one. As you see it returns TRUE indicating that the signal was handled and thus preventing to call the default handler and hence preventing the call to gtk_widget_destroy(). Also in it we can hide the widget if we want.
How can i change multible label values on single button click.Normally on a button click signal connect we can give only one user data.
Example code
void show_loop(GtkWidget *widget, gpointer user_data)
{
char buf[5];
int no = TxBuf.plBuf[7];
sprintf(buf, "%d",no);
gtk_label_set_text(GTK_LABEL(user_data), buf);
}
ID_label=GTK_WIDGET (gtk_builder_get_object (builder, "label24"));
DLC_label=GTK_WIDGET (gtk_builder_get_object (builder, "label25"));
check = GTK_WIDGET (gtk_builder_get_object (builder, "button3"));
g_signal_connect (check, "clicked", G_CALLBACK (show_loop), DLC_label);
I want to change both the labels on single button click.
Typically you would define, allocate and fill a struct that contains all the widgets that may have to be changed dynamically in your initialization code:
typedef struct AppData {
GtkWidget *id_label;
GtkWidget *dlc_label;
} AppData;
...
AppData *app_data = g_new0 (AppData, 1);
app_data->id_label = GTK_WIDGET (gtk_builder_get_object (builder, "label24"));
app_data->dlc_label = GTK_WIDGET (gtk_builder_get_object (builder, "label25"));
The you use the app_data as userdata parameter and can access the widgets inside the signal handler as e.g. app_data->id_label.
I want to create a grid with buttons. When a button is clicked I want it to change color, and 0 or 1 get stored in an array depending on the current state of the button.
Now I do this by creating the buttons with two for loops (rows, and columns).
Inside the for loops;
/*Create an ID number for the button being created*/
btn_nr ++;
char btn_nr_str[3];
sprintf(btn_nr_str,"%d",btn_nr); //convert nr to string
/*Create button*/
button = gtk_button_new();
/* When the button is clicked, we call the "callback" function
* with a pointer to the ID */
gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (callback)(gpointer) btn_nr_str);
/* Insert button into the table */
gtk_table_attach_defaults (GTK_TABLE(table), button, col, col+1, row, row+1);
gtk_widget_show (button);
The callback function;
void callback( GtkWidget *widget, gpointer nr)
{
GdkColor buttonColor;
gdk_color_parse ("black", &buttonColor);
gtk_widget_modify_bg ( GTK_WIDGET(widget), GTK_STATE_NORMAL, &buttonColor);
g_print ("Hello again - %s was pressed\n", (char *) nr);
}
The buttons are created like wanted, and when clicked they turn black.
However, all buttons print the last created button's ID.
How do I pass the right ID on?
You are accessing a local array (btn_nr_str) from outside (the callback) its scope (the for cycle). The idea is correct (using user_data) but the implementation is not.
For your specific case, you can use the type conversion macros provided by GLib. They are meant for exactly this purpose:
/* In the for cycle */
g_signal_connect(button, "clicked", G_CALLBACK(callback), GINT_TO_POINTER(btn_nr);
/* In the callback */
gint btn_nr = GPOINTER_TO_INT(user_data);
P.S.: gtk_signal_connect has been deprecated years ago.