| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

BeagleBoard GTK Development

Page history last edited by Chris 12 years, 4 months ago

The BeagleBoard and BeagleTouch OLED display together run the Linux Angstrom operating system which provides many toolkit options for developers to write embedded applications. We'll briefly describe a few based on GTK+ and provide basic examples of using each.

 


 

User Interface Toolkits

Linux has many powerful GUI design tools to write applications for the BeagleBoard and BeagleTouch OLED display. Some are bound to the C programming language, while others are hooked into scripting languages such as python. The C/C++ language is used to generate highly optimized code on embedded hardware. The ultimate choice depends on the scope of the project, performance constraints, and ease of GUI design.

 

Use the Glade user interface designer above.

 

GTK+

A graphical user interface toolkit written for X windows that provides windows, buttons, labels, images, off screen drawing buffers as widgets.

 

Language syntax

  GtkWidget *button;

  button = gtk_button_new_with_label ("Hello World");

 

More examples

 

GTK+ and Cairo

Cairo adds vector graphics capability to the GTK toolkit making it easily draw vector based shapes. Cairo is reportedly used as the backend to draw the user interface on Mozilla Firefox and other applications.

 

Language syntax:

  cairo_t *cr;

  cr = gdk_cairo_create (widget->window);

 

  cairo_set_source_rgb(cr, 0.69, 0.19, 0);
  cairo_arc(cr, xc, yc,
            20, 0, 2 * M_PI);
  cairo_stroke_preserve(cr);

 

More examples

 

GTK+ and Glade

Glade is a user interface designer that automatically generates a graphical interface and saves it to a single XML file. Your C application can read this file and parse out the GUI elements, all you need to do is write the event handlers.

 

Language syntax:

  #define UI_FILE "4button.glade"

 

  GtkBuilder              *builder;

 

  builder = gtk_builder_new();

  gtk_builder_add_from_file(builder, UI_FILE, NULL);

 

More examples

 

Installation

Installing gtk+, cairo, pango, etc. libraries to your beagleboard is easy if you have the Linux Angstrom OS rootfs and kernel already running. Precompiled rootfs and kernel images can be used to save some time, see the BeagleTouch downloads section.

 

You'll need the following hardware: BeagleBoard, BeagleBoot SD Card, BeagleTouch Display, USB Ethernet (or Wifi)

 

1.) Insert the BeagleBoot SD card

2.) Attach your USB ethernet module or Wifi

3.) Boot your beagleboard

 

User login: root

Password: there is no password, hit enter

 

4.) Test the ethernet connection

 

$ ping www.google.com

 

ping should reply back.

 

5.) Run this command to install the gtk+ development files

 

$ opkg install gtk+-dev

 

Now you have the basic setup to build gtk+ GUI applications.

 

Read on for some example apps...

 

Examples

Here are some BeagleBoard code examples that can be used as building blocks to create more sophisticated applications.

 

GTK+

GTK+ and Cairo

GTK+ and Glade

HelloWorld
PongBall
4ButtonWindow
   
 
     

 

HelloWorld

The classic demonstration code snippet creates a window and button using GTK+. The button event "clicked" is connected to a function which prints "Hello World" to the console.

 

Instructions:

1.) Echo the following text into a file named helloworld.c, here is the command:

 

$ echo 'paste text from below' > helloworld.c

#include <gtk/gtk.h>

void hello (void) {
     g_print ("Hello World\n");
}

void destroy (void) {
     gtk_main_quit ();
}

int main (int argc, char *argv[]) {
     GtkWidget *window;
     GtkWidget *button;

     gtk_init (&argc, &argv);

     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
     gtk_signal_connect (GTK_OBJECT (window), "destroy",
                         GTK_SIGNAL_FUNC (destroy), NULL);
     gtk_container_border_width (GTK_CONTAINER (window), 10);

     button = gtk_button_new_with_label ("Hello World");

     gtk_signal_connect (GTK_OBJECT (button), "clicked",
                         GTK_SIGNAL_FUNC (hello), NULL);
     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                         GTK_SIGNAL_FUNC (gtk_widget_destroy),
                         GTK_OBJECT (window));
     gtk_container_add (GTK_CONTAINER (window), button);
     gtk_widget_show (button);

     gtk_widget_show (window);

     gtk_main ();
     
     return 0;
}

 

2.) Paste the compiler command and hit enter

gcc -Wfatal-errors \
-mfpu=neon -mfloat-abi=softfp -mcpu=cortex-a8 -fomit-frame-pointer -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize \
-export-dynamic \
-I/usr/include/gtk-2.0 \
-I/usr/lib/gtk-2.0/include \
-I/usr/include/atk-1.0 \
-I/usr/include/cairo \
-I/usr/include/pango-1.0 \
-I/usr/include/glib-2.0 \
-I/usr/lib/glib-2.0/include \
-I/usr/include/freetype2 \
-I/usr/include/libpng12 \
-L/usr/lib \
-Xlinker -rpath -Xlinker /usr/lib \
-I. \
-lm -lpthread \
helloworld.c \
-Xlinker -L/usr/lib -Xlinker -l:libgtk-x11-2.0.so.0 -l:libatk-1.0.so.0 \
-l:libgdk_pixbuf-2.0.so.0 -l:libpango-1.0.so.0 -l:libcairo.so.2 \
-l:libgobject-2.0.so.0 -l:libgmodule-2.0.so.0 -l:libdl.so -l:libglib-2.0.so.0

 

3.) Set the DISPLAY variable (only the first time on bootup)

 

      $ export DISPLAY=:0.0

 

4.) Run the application- gcc creates the application as a single file called a.out

 

     $ ./a.out

 

 

PongBall

This example moves a ball like the Pong game. Drawn using GTK+ and Cairo. The timer loop and animation is frame rate limited to 30fps, or 33 millisecond timed events.

 

Use the compiler command below.

 

pongball.c

#include <gtk/gtk.h>
#include <cairo.h>
#include <math.h>
#include <time.h>


static char buffer[256];

void hello (void)
{
  g_print ("Hello World\n");
}

void destroy (void)
{
  gtk_main_quit ();
}

int xc = 60;
int yc = 60;
int dirx = 2;
int diry = 2;

/* Expose Event
   Draw everthing here */
static gboolean on_expose_event (GtkWidget *widget,
                                 GdkEventExpose *event,
                                 gpointer data)
{
  cairo_t *cr;
  int width, height;
 
  cr = gdk_cairo_create (widget->window);
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height);

  if ((xc > width) || (xc < 0)) {
    dirx = dirx * -1;
  }

  if ((yc > height) || (yc < 0)) {
    diry = diry * -1;
  }

  xc = xc + dirx;
  yc = yc + diry;

  cairo_set_line_width(cr, 9);

  cairo_set_source_rgb(cr, 0.69, 0.19, 0);
  cairo_arc(cr, xc, yc,
            20, 0, 2 * M_PI);
  cairo_stroke_preserve(cr);

  cairo_set_source_rgb(cr, 0.3, 0.4, 0.6);
  cairo_fill(cr);

  cairo_destroy(cr);

  return FALSE;
}

/* Timer event
   Forces a window expose event.
   Consider this the main loop (framerate controlled) */
static gboolean time_handler(GtkWidget *widget)
{
  if (widget->window == NULL) return FALSE;

  time_t curtime;
  struct tm *loctime;

  curtime = time(NULL);
  loctime = localtime(&curtime);
  strftime(buffer, 256, "%T", loctime);

  //printf("%s\n", buffer);

  gtk_widget_queue_draw(widget);
  return TRUE;
}

int main (int argc, char *argv[])
{
  GtkWidget *window;
  GdkColor b = { 0, 0, 0, 0};

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (destroy), NULL);
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  gtk_window_fullscreen(GTK_OBJECT(window));
  gtk_widget_modify_bg(GTK_OBJECT(window),GTK_STATE_NORMAL,&b);

  gtk_widget_show (window);

  g_signal_connect(G_OBJECT(window), "expose-event",
                   G_CALLBACK(on_expose_event), NULL);
  g_signal_connect(G_OBJECT(window), "destroy",
                   G_CALLBACK(gtk_main_quit), NULL);

  g_timeout_add(33, (GSourceFunc) time_handler, (gpointer) window);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 200, 150);

  gtk_widget_set_app_paintable(window, TRUE);
  gtk_widget_show_all(window);

  time_handler(window);

  gtk_main ();

  return 0;
}

 

Compiler command:

gcc -Wfatal-errors \
-mfpu=neon -mfloat-abi=softfp -mcpu=cortex-a8 -fomit-frame-pointer -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize \
-export-dynamic \
-I/usr/include/gtk-2.0 \
-I/usr/lib/gtk-2.0/include \
-I/usr/include/atk-1.0 \
-I/usr/include/cairo \
-I/usr/include/pango-1.0 \
-I/usr/include/glib-2.0 \
-I/usr/lib/glib-2.0/include \
-I/usr/include/freetype2 \
-I/usr/include/libpng12 \
-L/usr/lib \
-Xlinker -rpath -Xlinker /usr/lib \
-I. \
-lm -lpthread \
pongball.c \
-Xlinker -L/usr/lib -Xlinker -l:libgtk-x11-2.0.so.0 -l:libatk-1.0.so.0 \
-l:libgdk_pixbuf-2.0.so.0 -l:libpango-1.0.so.0 -l:libcairo.so.2 \
-l:libgobject-2.0.so.0 -l:libgmodule-2.0.so.0 -l:libdl.so -l:libglib-2.0.so.0

 

YouTube plugin error

 

4ButtonWindow

This code examples demonstrates how to read an autogenerated .glade XML file from current directory, load up GUI elements, and attach events.

 

Two files are needed: 4buttonwindow.c and 4button.glade

 

Use the compiler command below.

 

4buttonwindow.c

#include <gtk/gtk.h>
#include <cairo.h>
#include <math.h>
#include <time.h>

#define UI_FILE "4button.glade"

void on_window_destroy (GtkObject *object, gpointer user_data)
{
        gtk_main_quit();
}

void on_linkbutton1_released (GtkButton *button, gpointer user_data)
{
    g_print("%s released\n", gtk_button_get_label(button));
}

void on_linkbutton2_released (GtkButton *button, gpointer user_data)
{
    g_print("%s released\n", gtk_button_get_label(button));
}

void on_linkbutton3_released (GtkButton *button, gpointer user_data)
{
    g_print("%s released\n", gtk_button_get_label(button));
}

void on_linkbutton4_released (GtkButton *button, gpointer user_data)
{
    g_print("%s released\n", gtk_button_get_label(button));
    gtk_main_quit();
}

int main (int argc, char *argv[])
{
    GtkWidget               *window;
    GtkBuilder              *builder;

    gtk_init (&argc, &argv);

    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, UI_FILE, NULL);    

 
    window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
    gtk_builder_connect_signals (builder, NULL);          
    g_object_unref (G_OBJECT (builder));

    gtk_widget_show (window);   

    gtk_main ();

  return 0;
}

 

4button.glade - Autogenerated using Glade - a user interface designer. Download Mac/Windows binaries

<?xml version="1.0"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="window">
    <property name="resizable">False</property>
    <property name="window_position">center</property>
    <property name="default_width">480</property>
    <property name="default_height">272</property>
    <property name="decorated">False</property>
    <child>
      <object class="GtkTable" id="table1">
        <property name="visible">True</property>
        <property name="n_rows">2</property>
        <property name="n_columns">2</property>
        <child>
          <object class="GtkLinkButton" id="linkbutton1">
            <property name="label" translatable="yes">Start</property>
            <property name="width_request">240</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="has_tooltip">True</property>
            <property name="relief">none</property>
            <property name="uri">http://glade.gnome.org</property>
            <signal name="released" handler="on_linkbutton1_released"/>
          </object>
        </child>
        <child>
          <object class="GtkLinkButton" id="linkbutton2">
            <property name="label" translatable="yes">Hello World</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="has_tooltip">True</property>
            <property name="relief">none</property>
            <property name="uri">http://glade.gnome.org</property>
            <signal name="released" handler="on_linkbutton2_released"/>
          </object>
          <packing>
            <property name="top_attach">1</property>
            <property name="bottom_attach">2</property>
          </packing>
        </child>
        <child>
          <object class="GtkLinkButton" id="linkbutton3">
            <property name="label" translatable="yes">Stop</property>
            <property name="width_request">240</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="has_tooltip">True</property>
            <property name="relief">none</property>
            <property name="uri">http://glade.gnome.org</property>
            <signal name="released" handler="on_linkbutton3_released"/>
          </object>
          <packing>
            <property name="left_attach">1</property>
            <property name="right_attach">2</property>
          </packing>
        </child>
        <child>
          <object class="GtkLinkButton" id="linkbutton4">
            <property name="label" translatable="yes">exit</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="has_tooltip">True</property>
            <property name="relief">none</property>
            <property name="uri">http://glade.gnome.org</property>
            <signal name="released" handler="on_linkbutton4_released"/>
          </object>
          <packing>
            <property name="left_attach">1</property>
            <property name="right_attach">2</property>
            <property name="top_attach">1</property>
            <property name="bottom_attach">2</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
  <object class="GtkAction" id="action1"/>
</interface>

 

Compiler command:

gcc -Wfatal-errors \
-mfpu=neon -mfloat-abi=softfp -mcpu=cortex-a8 -fomit-frame-pointer -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize \
-export-dynamic \
-I/usr/include/gtk-2.0 \
-I/usr/lib/gtk-2.0/include \
-I/usr/include/atk-1.0 \
-I/usr/include/cairo \
-I/usr/include/pango-1.0 \
-I/usr/include/glib-2.0 \
-I/usr/lib/glib-2.0/include \
-I/usr/include/freetype2 \
-I/usr/include/libpng12 \
-L/usr/lib \
-Xlinker -rpath -Xlinker /usr/lib \
-I. \
-lm -lpthread \
4buttonwindow.c \
-Xlinker -L/usr/lib -Xlinker -l:libgtk-x11-2.0.so.0 -l:libatk-1.0.so.0 \
-l:libgdk_pixbuf-2.0.so.0 -l:libpango-1.0.so.0 -l:libcairo.so.2 \
-l:libgobject-2.0.so.0 -l:libgmodule-2.0.so.0 -l:libdl.so -l:libglib-2.0.so.0

 

 

 

#include <gtk/gtk.h>
#include <cairo.h>
#include <math.h>
#include <time.h>


static char buffer[256];

void hello (void)
{
  g_print ("Hello World\n");
}

void destroy (void)
{
  gtk_main_quit ();
}

int xc = 60;
int yc = 60;
int deg = 0;

/* Expose Event
   Draw everthing here */
static gboolean on_expose_event (GtkWidget *widget,
                                 GdkEventExpose *event,
                                 gpointer data)
{
  cairo_t *cr;
  int width, height;

  deg = deg + 5;
 
  cr = gdk_cairo_create (widget->window);
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height);

  xc = (sin(deg*0.01745) * 100) + width/2;
  yc = (cos(deg*0.01745) * 50) + height/2;

  cairo_set_line_width(cr, 9);

  cairo_set_source_rgb(cr, 0.69, 0.19, 0);
  cairo_arc(cr, xc, yc,
            20, 0, 2 * M_PI);
  cairo_stroke_preserve(cr);

  cairo_set_source_rgb(cr, 0.3, 0.4, 0.6);
  cairo_fill(cr);

  cairo_destroy(cr);

  return FALSE;
}

/* Timer event
   Forces a window expose event.
   Consider this the main loop (framerate controlled) */
static gboolean time_handler(GtkWidget *widget)
{
  if (widget->window == NULL) return FALSE;

  time_t curtime;
  struct tm *loctime;

  curtime = time(NULL);
  loctime = localtime(&curtime);
  strftime(buffer, 256, "%T", loctime);

  //printf("%s\n", buffer);

  gtk_widget_queue_draw(widget);
  return TRUE;
}

int main (int argc, char *argv[])
{
  GtkWidget *window;
  GdkColor b = { 0, 0, 0, 0};

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (destroy), NULL);
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  gtk_window_fullscreen(GTK_OBJECT(window));
  gtk_widget_modify_bg(GTK_OBJECT(window),GTK_STATE_NORMAL,&b);

  gtk_widget_show (window);

  g_signal_connect(G_OBJECT(window), "expose-event",
                   G_CALLBACK(on_expose_event), NULL);
  g_signal_connect(G_OBJECT(window), "destroy",
                   G_CALLBACK(gtk_main_quit), NULL);

  g_timeout_add(33, (GSourceFunc) time_handler, (gpointer) window);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 200, 150);

  gtk_widget_set_app_paintable(window, TRUE);
  gtk_widget_show_all(window);

  time_handler(window);

  gtk_main ();

  return 0;
}

Comments (0)

You don't have permission to comment on this page.