LED virtual usando GTK3
Sep 16 2020
Estoy intentando hacer un LED virtual usando GTK3. No estoy familiarizado con la programación de GUI. No sé si mi enfoque es correcto. De todos modos, esto es lo que he hecho hasta ahora:
// gcc ledgui.c `pkg-config --cflags gtk+-3.0 pkg-config --libs gtk+-3.0`
#include <stdint.h>
#include <stdbool.h>
#include <gtk/gtk.h>
#define LED_COLOR_RED 0
#define LED_COLOR_GREEN 1
#define LED_COLOR_YELLOW 2
#define LED_COLOR_OFF 3
#define LED_COLOR_COUNT 4
static GtkTextBuffer *buffer;
GtkTextTag *tagLed[LED_COLOR_COUNT];
uint8_t ledColorData[] = {0,0};
static void activate (GtkApplication* app, gpointer user_data);
static void SetGuiLedColor(int id, GtkTextTag *tag);
static void SetLedColorTags();
void Task_sleep_ms(int ms);
int main()
{
GtkApplication *app;
int status;
app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
SetGuiLedColor(0, tagLed[LED_COLOR_RED]);
// Task_sleep_ms(500);
// SetGuiLedColor(0, tagLed[LED_COLOR_GREEN]);
// Task_sleep_ms(500);
status = g_application_run(G_APPLICATION(app), 0, NULL);
g_object_unref(app);
}
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "LED");
gtk_window_set_default_size(GTK_WINDOW(window), 200, 50);
GtkWidget *view;
GtkCssProvider *provider;
GtkStyleContext *context;
view = gtk_text_view_new();
gtk_container_add (GTK_CONTAINER (window), view);
gtk_widget_set_name (view, "led1");
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
gtk_text_buffer_set_text(buffer, "1 2 3 4\no o o o", -1);
/* Change default font and color throughout the widget */
provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider,
"* {"
" color: white;"
" background-color: black;"
" font: 20 monospace;"
"}",
-1,
NULL);
context = gtk_widget_get_style_context(view);
gtk_style_context_add_provider(context,
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
/* Change left margin throughout the widget */
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 40);
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (view), 2);
SetLedColorTags();
// g_print ("Hello World\n");
SetGuiLedColor(0, tagLed[LED_COLOR_YELLOW]);
gtk_widget_show_all(window);
}
static void SetLedColorTags()
{
int i;
char *color[] = {"red", "green", "yellow", "black"};
/* Use a tag to change the color for just one part of the widget */
if (buffer == NULL)
{
printf("Error!! buffer is NULL\n");
return;
}
for (i=0; i<LED_COLOR_COUNT; i++)
{
tagLed[i] = gtk_text_buffer_create_tag (buffer, color[i] /*tag name*/,
"foreground", color[i], NULL);
}
}
static void SetGuiLedColor(int id, GtkTextTag *tag)
{
GtkTextIter start, end;
int idStart, idEnd;
idStart = id*2+8;
idEnd = idStart+1;
g_print ("LED color %p\n", tag);
gtk_text_buffer_get_iter_at_offset (buffer, &start, idStart);
gtk_text_buffer_get_iter_at_offset (buffer, &end, idEnd);
gtk_text_buffer_apply_tag (buffer, tag, &start, &end);
}
void Task_sleep_ms(int ms)
{
printf("sleep %d ms\n", ms);
usleep(ms * 1000);
}
Llamo a la SetGuiLedColorfunción 3 veces. Cuando ejecuto el código, solo muestra AMARILLO. Pero espero que se muestre AMARILLO, ROJO y luego VERDE secuencialmente. ¿Cómo puedo hacerlo?
Respuestas
YoungminKim Sep 17 2020 at 10:17
Gracias Alexander, con tu ayuda, he escrito este código de trabajo. ¿Podrías avisarme si algo anda mal?
// https://stackoverflow.com/questions/26429173/getting-a-gtk-label-to-dislay-an-int-in-c
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#define LED_COLOR_RED 0
#define LED_COLOR_GREEN 1
#define LED_COLOR_YELLOW 2
#define LED_COLOR_OFF 3
#define LED_COLOR_COUNT 4
char *color[] = {"red", "green", "yellow", "black"};
GtkWidget *ledLight;
void *LedControllerTask (void *vargp);
void *LedGuiThread (void *vargp);
void SetFontColors(GtkWidget *grid);
void updateLabel(GtkLabel *led, char* fcolor);
void Task_sleep_ms(int ms);
int main()
{
pthread_t thread_id;
pthread_t thread_id2;
// InitSemaphore();
pthread_create(&thread_id2, NULL, LedControllerTask, NULL);
pthread_create(&thread_id, NULL, LedGuiThread, NULL);
pthread_join(thread_id2, NULL);
pthread_join(thread_id, NULL);
exit(0);
}
void *LedControllerTask (void *vargp)
{
Task_sleep_ms(1000);
updateLabel(GTK_LABEL(ledLight), color[LED_COLOR_RED]);
Task_sleep_ms(1000);
updateLabel(GTK_LABEL(ledLight), color[LED_COLOR_GREEN]);
Task_sleep_ms(1000);
updateLabel(GTK_LABEL(ledLight), color[LED_COLOR_YELLOW]);
}
void *LedGuiThread (void *vargp)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *ledLabel;
int argc=0;
char **argv=NULL;
gtk_init (&argc,&argv);
//Declarations
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "LED");
grid = gtk_grid_new ();
SetFontColors(grid);
ledLabel = gtk_label_new ("1");
ledLight = gtk_label_new ("O");
//Set Properties
gtk_container_set_border_width (GTK_CONTAINER(window), 20);
gtk_widget_set_size_request (GTK_WIDGET(window), 200, 50);
gtk_grid_set_row_spacing (GTK_GRID(grid), 4);
gtk_grid_set_column_spacing (GTK_GRID(grid), 4);
gtk_container_add (GTK_CONTAINER(window), grid);
//Fill the grid with shit (x, y, h, v)
gtk_grid_attach (GTK_GRID(grid), ledLabel, 2, 2, 2, 1);
gtk_grid_attach (GTK_GRID(grid), ledLight, 2, 3, 2, 1);
gtk_widget_show_all (window);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
}
void SetFontColors(GtkWidget *grid)
{
GtkCssProvider *provider;
GtkStyleContext *context;
/* Change default font and color throughout the widget */
provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider,
"* {"
" color: white;"
" background-color: black;"
" font: 20px monospace;"
"}",
-1,
NULL);
context = gtk_widget_get_style_context(grid);
gtk_style_context_add_provider(context,
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
void updateLabel(GtkLabel *led, char* fcolor)
{
char text[256];
// https://unix.stackexchange.com/questions/457584/gtk3-change-text-color-in-a-label-raspberry-pi
snprintf(text, 256, "<span background=\"black\" foreground=\"%s\">O</span>", fcolor);
gtk_label_set_markup (GTK_LABEL (led), text);
}
void Task_sleep_ms(int ms)
{
printf("sleep %d ms\n", ms);
usleep(ms * 1000);
}
YoungminKim Sep 23 2020 at 06:09
Por consejo de Alexander, he actualizado el código para que sea seguro para subprocesos.
// gcc ledgui.c `pkg-config --cflags gtk+-3.0 pkg-config --libs gtk+-3.0`
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#define LED_COLOR_RED 0
#define LED_COLOR_GREEN 1
#define LED_COLOR_YELLOW 2
#define LED_COLOR_OFF 3
#define LED_COLOR_COUNT 4
char *color[] = {"red", "green", "yellow", "black"};
GtkWidget *ledLight;
GMutex mutex;
gchar ledText[256];
void *LedControllerTask (void *vargp);
void *LedGuiThread (void *vargp);
void SetFontColors(GtkWidget *grid);
gboolean updateLabel(gpointer data);
void Task_sleep_ms(int ms);
void SetTextColor(char* fcolor);
int main()
{
pthread_t thread_id;
pthread_t thread_id2;
pthread_create(&thread_id2, NULL, LedControllerTask, NULL);
pthread_create(&thread_id, NULL, LedGuiThread, NULL);
{
Task_sleep_ms(1000);
while (1)
{
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_GREEN]);
g_idle_add(updateLabel, ledLight);
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_OFF]);
g_idle_add(updateLabel, ledLight);
}
}
pthread_join(thread_id2, NULL);
pthread_join(thread_id, NULL);
exit(0);
}
void *LedControllerTask (void *vargp)
{
Task_sleep_ms(1000);
while (1)
{
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_RED]);
g_idle_add(updateLabel, ledLight);
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_OFF]);
g_idle_add(updateLabel, ledLight);
}
}
void *LedGuiThread (void *vargp)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *ledLabel;
int argc=0;
char **argv=NULL;
gtk_init (&argc,&argv);
//Declarations
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "LED");
grid = gtk_grid_new ();
SetFontColors(grid);
ledLabel = gtk_label_new ("1");
ledLight = gtk_label_new ("O");
//Set Properties
gtk_container_set_border_width (GTK_CONTAINER(window), 20);
gtk_widget_set_size_request (GTK_WIDGET(window), 200, 50);
gtk_grid_set_row_spacing (GTK_GRID(grid), 4);
gtk_grid_set_column_spacing (GTK_GRID(grid), 4);
gtk_container_add (GTK_CONTAINER(window), grid);
//Fill the grid with shit (x, y, h, v)
gtk_grid_attach (GTK_GRID(grid), ledLabel, 2, 2, 2, 1);
gtk_grid_attach (GTK_GRID(grid), ledLight, 2, 3, 2, 1);
gtk_widget_show_all (window);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
}
void SetFontColors(GtkWidget *grid)
{
GtkCssProvider *provider;
GtkStyleContext *context;
/* Change default font and color throughout the widget */
provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider,
"* {"
" color: white;"
" background-color: black;"
" font: 20px monospace;"
"}",
-1,
NULL);
context = gtk_widget_get_style_context(grid);
gtk_style_context_add_provider(context,
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
gboolean updateLabel(gpointer data)
{
char text[256];
GtkLabel *led = data;
g_mutex_lock (&mutex);
strncpy(text, ledText, sizeof(text));
g_mutex_unlock (&mutex);
gtk_label_set_markup (GTK_LABEL (led), text);
}
void Task_sleep_ms(int ms)
{
// printf("sleep %d ms\n", ms);
usleep(ms * 1000);
}
void SetTextColor(char* fcolor)
{
g_mutex_lock(&mutex);
snprintf(ledText, 256, "<span background=\"black\" foreground=\"%s\">O</span>", fcolor);
g_mutex_unlock(&mutex);
}
¡Gracias David !. He actualizado el código. Se ve mucho mejor.
// gcc ledgui.c `pkg-config --cflags gtk+-3.0 pkg-config --libs gtk+-3.0`
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#define LED_COLOR_RED 0
#define LED_COLOR_GREEN 1
#define LED_COLOR_YELLOW 2
#define LED_COLOR_OFF 3
#define LED_COLOR_COUNT 4
char *color[] = {"red", "green", "yellow", "black"};
GtkWidget *ledLight;
GMutex mutex;
gchar ledText[256];
void *LedTask1 (void *vargp);
void *LedTask2 (void *vargp);
void LedGuiThread ();
void SetFontColors(GtkWidget *grid);
gboolean updateLabel(gpointer data);
void Task_sleep_ms(int ms);
void SetTextColor(char* fcolor);
int main()
{
pthread_t thread_id;
pthread_t thread_id2;
LedGuiThread();
pthread_create(&thread_id2, NULL, LedTask1, NULL);
pthread_create(&thread_id, NULL, LedTask2, NULL);
gtk_main();
// pthread_join(thread_id2, NULL);
// pthread_join(thread_id, NULL);
exit(0);
}
void *LedTask1 (void *vargp)
{
while (1)
{
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_RED]);
g_idle_add(updateLabel, ledLight);
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_OFF]);
g_idle_add(updateLabel, ledLight);
}
}
void *LedTask2 (void *vargp)
{
while (1)
{
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_GREEN]);
g_idle_add(updateLabel, ledLight);
Task_sleep_ms(100);
SetTextColor(color[LED_COLOR_OFF]);
g_idle_add(updateLabel, ledLight);
}
}
void LedGuiThread()
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *ledLabel;
int argc=0;
char **argv=NULL;
gtk_init (&argc,&argv);
//Declarations
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "LED");
grid = gtk_grid_new ();
SetFontColors(grid);
ledLabel = gtk_label_new ("1");
ledLight = gtk_label_new ("O");
//Set Properties
gtk_container_set_border_width (GTK_CONTAINER(window), 20);
gtk_widget_set_size_request (GTK_WIDGET(window), 200, 50);
gtk_grid_set_row_spacing (GTK_GRID(grid), 4);
gtk_grid_set_column_spacing (GTK_GRID(grid), 4);
gtk_container_add (GTK_CONTAINER(window), grid);
//Fill the grid with shit (x, y, h, v)
gtk_grid_attach (GTK_GRID(grid), ledLabel, 2, 2, 2, 1);
gtk_grid_attach (GTK_GRID(grid), ledLight, 2, 3, 2, 1);
gtk_widget_show_all (window);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
}
void SetFontColors(GtkWidget *grid)
{
GtkCssProvider *provider;
GtkStyleContext *context;
/* Change default font and color throughout the widget */
provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider,
"* {"
" color: white;"
" background-color: black;"
" font: 20px monospace;"
"}",
-1,
NULL);
context = gtk_widget_get_style_context(grid);
gtk_style_context_add_provider(context,
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
gboolean updateLabel(gpointer data)
{
char text[256];
GtkLabel *led = data;
g_mutex_lock (&mutex);
strncpy(text, ledText, sizeof(text));
g_mutex_unlock (&mutex);
gtk_label_set_markup (GTK_LABEL (led), text);
}
void Task_sleep_ms(int ms)
{
// printf("sleep %d ms\n", ms);
usleep(ms * 1000);
}
void SetTextColor(char* fcolor)
{
g_mutex_lock(&mutex);
snprintf(ledText, 256, "<span background=\"black\" foreground=\"%s\">O</span>", fcolor);
g_mutex_unlock(&mutex);
}