I am making a program in C with GTK and Glade for a serial communication. I am having problem using g_timeout_add. For example I have a function serial_data() which contain my serial data and I have a button handler on_update_button_clicked(). So till now I have done that if update button is clicked, gtk_timeout should run. But it running just for one time.
on_update_button_clicked(GtkButton *Update_Button)
{
//2nd argument is serial_data function which contain actual data
g_timeout_add(250,serial_data,NULL);
}
where I am missing the point?
I have another button stop button. So i want that timeout should stop when stop button handler is clicked. How to do that.??
One more question to ask, I want to count the number of times timeout is running like a counter. So that I can display the numbers of counter. How is this possible.?
Please help thanks.
From the documentation, The function is called repeatedly until it returns FALSE. You can call on_update_button with a boolean argument to toggle the timeout call from being continually called, set it running when argument evaluates to TRUE, and delete the thread with g_source_remove(threadID) if argument is FALSE. Here's a demonstration:
// compiling with: gcc test.c `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0` -o test
#include <stdio.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
guint threadID = 0;
guint serial_counter = 0;
static gboolean
serial_data (gpointer user_data)
{
// do something
printf("counter: %d\n", serial_counter);
serial_counter++;
return user_data;
}
static void
on_update_button_clicked (GtkButton* button, gpointer user_data)
{
if (user_data == 1)
{
threadID = g_timeout_add(250, serial_data, user_data);
}
else if (user_data == 0)
{
g_source_remove(threadID);
threadID = 0;
}
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
gtk_init (&argc, &argv);
GtkWidget *update_button;
GtkWidget *stop_button;
GtkWidget *box;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "test.c");
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
update_button = gtk_button_new_with_label (_("Update"));
stop_button = gtk_button_new_with_label (_("Stop"));
gtk_box_pack_start (GTK_BOX (box), update_button, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), stop_button, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), box);
g_signal_connect (update_button, "clicked", G_CALLBACK (on_update_button_clicked), 1);
g_signal_connect (stop_button, "clicked", G_CALLBACK (on_update_button_clicked), 0);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
g_timeout_add() returns an event source id that you should store. You can use g_source_remove() with that id in your stop button handler to stop the timeout.
check the developer site
https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add
its quite explicit.
you can have a gpointer to a gboolean STOP, finish the serial_data func in return STOP, and make your stop button change that STOP = FALSE and it will stop calling on that function. Or something like that.
Related
I am receiving this error and not sure why...Please take a look at my buttons array, maybe I messed smth there, I am not sure...
The error i get is: Xlib: extension "RANDR" missing on display ":24.0".
and nothing happens after that, meaning my program doesnt run at all....
#include <gtk/gtk.h>
/* Our new improved callback. The data passed to this function
* is printed to stdout. */
static void callback (GtkWidget *widget, gpointer data)
{
system ((gchar *) data);
}
/* another callback */
static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
{
gtk_main_quit ();
return FALSE;
}
int main (int argc, char *argv[])
{
/* GtkWidget is the storage type for widgets */
GtkWidget *window;
GtkWidget *box1;
/* This is called in all GTK applications. Arguments are parsed
* from the command line and are returned to the application. */
gtk_init (&argc, &argv);
/* Create a new window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/* This is a new call, which just sets the title of our
* new window to "My Assignments" */
gtk_window_set_title (GTK_WINDOW (window), "My Assignments");
/* Here we just set a handler for delete_event that immediately
* exits GTK. */
g_signal_connect (window, "delete-event",
G_CALLBACK (delete_event), NULL);
/* Sets the border width of the window. */
gtk_container_set_border_width (GTK_CONTAINER (window), 50);
/* We create a box to pack widgets into. This is described in detail
* in the "packing" section. The box is not really visible, it
* is just used as a tool to arrange widgets. */
box1 = gtk_vbox_new (FALSE,0);
/* Put the box into the main window. */
gtk_container_add (GTK_CONTAINER (window), box1);
/*array is here*/
GtkWidget *button[2];
int i;
for (i=0; i<2; i++)
{
button[i]=gtk_button_new();
}
button[0] = gtk_button_new_with_label ("Run shellscript");
g_signal_connect (button[0], "clicked",
G_CALLBACK (callback), "shellscript");
gtk_box_pack_start (GTK_BOX (box1), button[0], TRUE, TRUE, 0);
gtk_widget_show(button[0]);
button[1] = gtk_button_new_with_label ("Run program2 ");
g_signal_connect (button[1], "clicked",
G_CALLBACK (callback), "program");
gtk_box_pack_start (GTK_BOX (box1), button[1], TRUE, TRUE, 0);
gtk_widget_show(button[1]);
gtk_widget_show (box1);
/* Rest in gtk_main and wait for the fun to begin! */
gtk_main ();
return 0;
}
How can I make a Gtk button label bold?
I know how to set a label markup as:
GtkWidget *label = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(label), "<b>Text to be bold</b>");
but not sure how to pass the argument to:
gtk_button_set_label()
The following pygtk code to make Bold Label Button should be easy to translate in C
# Create "Quit" button
button = gtk.Button("")
for child in button.get_children():
child.set_label("<b>Quit</b>")
child.set_use_markup(True)
# When the button is clicked, we call the main_quit function
# and the program exits
button.connect("clicked", lambda wid: gtk.main_quit())
# Insert the quit button
table.attach(button, 1,2,1,2, gtk.SHRINK|gtk.EXPAND|gtk.FILL)
button.show()
This code works for me
button = gtk_button_new_with_label("");
list = gtk_container_get_children(GTK_CONTAINER (button));
gtk_label_set_markup(GTK_LABEL(list->data), "<b>hello!</b>");
The issue is that gtk_button_new_with_label(...) does not accept NULL as valid param and thus things get wacky.
Below a minimal working example.
Compile using gcc $(pkg-config --libs --cflags gtk+-3.0) ./main.c && ./a.out
main.c:
#include <gtk/gtk.h>
#include "stdlib.h"
void mycb (GtkWidget *button, gpointer user_data)
{
GList *list;
GtkWidget *label;
list = gtk_container_get_children (GTK_CONTAINER (button));
// list should only contain one element, since the button can only hold one child
if (list->data && GTK_IS_LABEL (list->data)) {
// set the markup string
// for the markup syntax see
// https://developer.gnome.org/pygtk/stable/pango-markup-language.html
//gtk_label_set_markup (GTK_LABEL (list->data), "<span weight=\"bold\">hello markup A!</span>");
gtk_label_set_markup (GTK_LABEL (list->data), "hello <b>bold</b> markup");
} else {
label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL (label), "hello <span style=\"italic\">italic </span> markup B!");
gtk_container_add (GTK_CONTAINER (button), label);
}
}
int main(int argc, char *argv[])
{
gtk_init (&argc, &argv);
GtkWidget *window;
GtkWidget *button;
GtkWidget *label;
GList *list;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("no markup");
//button = gtk_button_new ();
#if 0
g_signal_connect (button, "clicked", G_CALLBACK (mycb), NULL);
#else
mycb(button, NULL);
#endif
gtk_container_add (GTK_CONTAINER (window), button);
gtk_widget_show_all (window);
gtk_main();
return EXIT_SUCCESS;
}
I've tried a few things and may be nearing a solution but here goes ...
on a (possibly realised) widget, has anyone got a good example of say an
GtkEntry widget receiving a ALT+ Down or CTRL + n key press which will raise
a "new" signal e.g. SIG-NEW on the widget. which I know how to catch with g_signal_connect.
I appended a minimal working example.
The important point is to connect the key-press-event of an GtkEntry-instance to a suitable callback. In that callback you have to extract the GdkEventKey struct that is a member of the GdkEvent struct which is a parameter of the callback function.
GdkEventKey contains all information you need to check which key+modifier was pressed.
Since i tested the code with gtk+-3.0 you may have to modify the GdkEventMask of the widget to receive key-press-event's. For gtk+-3.0 it seems that is already the default setting. If the callback isn't invoked you should enable it with gdk_window_set_events () (of course you have to invoke it upon the gdk window of the widget).
#include <gtk/gtk.h>
#include <glib.h>
gboolean
key_press_event_cb (GtkWidget * widget, GdkEvent * event,
gpointer data)
{
GdkEventKey key = event->key;
/* check modifier key */
/* on most keyboards GDK_MOD1_MASK is the Alt key */
if (key.state == GDK_MOD1_MASK) {
/* check for key that was pressed */
switch (key.keyval) {
case GDK_KEY_d:
g_print
("`Alt-d` deletes the content in the entry box\n");
gtk_entry_set_text (GTK_ENTRY (widget), "");
break;
}
}
/* check for unmodified key presses */
switch (key.keyval) {
case GDK_KEY_x:
g_print
("`x` deletes the content in the entry box\n");
gtk_entry_set_text (GTK_ENTRY (widget), "");
return TRUE;
break;
}
return FALSE;
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *entry;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
entry = gtk_entry_new ();
gtk_container_add (GTK_CONTAINER (window), entry);
gtk_widget_show_all (window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (entry, "key-press-event",
G_CALLBACK (key_press_event_cb), NULL);
gtk_main ();
return 0;
}
gtk+ ver 2.24.8
vte ver 0.28.2
I just starting out creating a terminal application, however, none of the examples I have found online (5) have working scrollback. Is there a problem with scrollback in vte or is it something I'm not seeing? Here is one example:
#include <gtk/gtk.h>
#include <vte/vte.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <gdk/gdkkeysyms.h> // includes GDK_q
/* gcc -Wall -g term.c -o term `pkg-config --cflags --libs gtk+-2.0 vte` */
long size;
char *buf;
char *ptr;
gboolean key_press_win_main (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
void quit_activated();
static gboolean delete_event(GtkWidget *,GdkEvent *);
int main( int argc, char *argv[] )
{
size = pathconf(".", _PC_PATH_MAX);
if ((buf = (char *)malloc((size_t)size)) != NULL) ptr = getcwd(buf, (size_t)size);
GtkWidget *window_main;
GtkWidget *vbox;
GtkWidget *vte;
GtkWidget *notebook;
GtkWidget *scrolled_window;
GtkWidget *label;
gtk_init (&argc, &argv);
window_main = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window_main), "Caraterm v0.0.1");
vbox = gtk_vbox_new(FALSE,0);
gtk_container_add (GTK_CONTAINER (window_main), vbox);
notebook = gtk_notebook_new ();
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_BOTTOM);
gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
label = gtk_label_new ("term1");
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_window, label);
vte = vte_terminal_new();
vte_terminal_set_background_transparent(VTE_TERMINAL(vte), FALSE);
vte_terminal_set_size(VTE_TERMINAL(vte), 80, 45);
vte_terminal_set_scrollback_lines(VTE_TERMINAL (vte), -1); /* infinite scrollback */
vte_terminal_fork_command(VTE_TERMINAL(vte), NULL, NULL, NULL, ptr, TRUE, TRUE,TRUE);
vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL (vte), TRUE);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), vte);
printf("%s\n", vte_terminal_get_emulation(VTE_TERMINAL (vte)));
g_signal_connect(G_OBJECT(window_main),"destroy",G_CALLBACK(quit_activated),NULL);
g_signal_connect(G_OBJECT(window_main),"delete_event",G_CALLBACK(delete_event),NULL);
g_signal_connect (G_OBJECT (window_main), "key_press_event", G_CALLBACK (key_press_win_main), NULL);
gtk_widget_show (label);
gtk_widget_show (notebook);
gtk_widget_show (scrolled_window);
gtk_widget_show (vte);
gtk_widget_show (vbox);
gtk_widget_show (window_main);
gtk_main ();
return 0;
}
gboolean key_press_win_main (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
switch (event->keyval)
{
case GDK_q:
if (event -> state & GDK_CONTROL_MASK)
{
printf("entered q\n");
quit_activated();
}
break;
default:
return FALSE;
}
return FALSE;
}
void quit_activated()
{
gtk_main_quit();
}
static gboolean delete_event(GtkWidget *window_main,GdkEvent *event)
{
return FALSE;
}
This example will scroll but only to accomodate the original size of the vte set via vte_terminal_set_size(VTE_TERMINAL(vte), 80, 45); If more lines are added to the terminal by simply hitting return or producing output from a program the scrollback buffer does not expand. It is fixed at 45 lines despite the fact that an unlimited scrollback was specified vte_terminal_set_scrollback_lines(VTE_TERMINAL (vte), -1); /* infinite scrollback */
What am I missing? Thanks.
In order to get scrollback to work the line that needed to be changed was:
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
to:
scrolled_window = gtk_scrolled_window_new (NULL, terminal->adjustment);
where terminal is defined as:
VteTerminal *terminal;
vte = vte_terminal_new();
terminal = VTE_TERMINAL (vte);
I'm not all that confident since I haven't worked with VTE before. However, it looks like the vte_terminal is itself a scrollable widget. I'd suggest you try to get rid of the scrolled_window and see.
Also, here is what I've found as an example.
try this it's works
//gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), vte);
gtk_container_add (GTK_CONTAINER(scrolled_window),vte);
I am developing an application that has a numeric keypad and a text box when clicked on a button, text box shows the number.
I need to write a function to each button? Or you can pass a text and a widget as parameter?
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
void callback( GtkWidget *widget,
gpointer data )
{
gtk_entry_append_text(entry, text);
}
void create_button(GtkWidget* table,GtkWidget* entry,
int start_r,int end_r,
int start_c,int end_c,
char* label)
{
GtkWidget *button;
button = gtk_button_new_with_label (label);
g_object_set_data( G_OBJECT( button ),
"char", (gpointer)label );
g_signal_connect (button, "clicked",
G_CALLBACK (callback), entry);
gtk_table_attach_defaults (GTK_TABLE(table), button, start_c, end_c, start_r, end_r);
gtk_widget_show (button);
}
gint delete_event( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
gtk_main_quit ();
return(FALSE);
}
int main(int argc,char* argv[]){
GtkWidget *window;
//GtkWidget *button;
GtkWidget *table;
GtkWidget *entry;
//GtkWidget *label;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Armario");
g_signal_connect (GTK_OBJECT (window), "delete_event",
G_CALLBACK (delete_event), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 20);
table = gtk_table_new (2, 2, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
entry = gtk_entry_new();
gtk_entry_set_max_length(GTK_ENTRY(entry),10);
gtk_entry_set_placeholder_text(GTK_ENTRY(entry),"Teste");
gtk_table_attach_defaults (GTK_TABLE(table), entry, 0, 2, 1, 2);
gtk_widget_show(entry);
create_button(table,entry,0,1,0,1,"Botao");
gtk_widget_show (table);
gtk_widget_show (window);
gtk_main ();
return 0;
}
The answer to your question is yes, you can pass a widget in Gtk+ to a callback. Actually, the first parameter of the callback for the clicked signal is the button which received the signal (ie. usually the button that was clicked). As you can see in the sample code below, you can extract from the button its label and use it as text.
[...] /* In create_button... */
/* Make your buttons be notified when they are clicked */
g_signal_connect (button, "clicked", G_CALLBACK (on_button_clicked), entry);
[...]
/* Append the text in the button to the text entry */
void on_button_clicked (GtkButton *button, gpointer user_data)
{
GtkEntry *entry = user_data;
const gchar *text = gtk_button_get_label (button);
gint position = 0;
gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &position);
}
I'm using gtk_editable_insert_text because gtk_entry_append_text has been deprecated for a long time. Passing the "entry" parameter to the callback is possible by using the last parameter of g_signal_connect which allows you to specify some data that you need to access in your callback. This info is then made available to the callback in the "user_data" parameter.
Your exemple could also be improved by using gtk_widget_show_all, and I also don't see the point in calling g_object_set_data on the "char" property, as the text is already set in the label property (and retrieved with gtk_button_get_label).
Two options, that I can think of:
GTK widgets are really GObjects, so you can attach to them arbitrary pieces of data. See the functions g_object_set_data/g_object_set_data_full/g_object_get_data. So you can just add the text to the button as an attached data and retrieve it when needed.
You can pass any data you need to a callback by defining a struct with all the fields, and passing a pointer to it. If the struct cannot be declared statically, you can malloc it and use g_signal_connect_data to specify the function to release the data:
For example:
struct entry_and_text;
{
GtkWidget *w;
char *text;
};
void free_data(gpointer data, GClosure *closure)
{
free(data);
}
entry_and_text *data = (entry_and_text *)malloc(sizeof(entry_and_text));
data->w = entry;
data->text = label;
g_signal_connect_data (button, "clicked",
G_CALLBACK (callback), data, free_data, 0);