Publi

Cómo crear ventanas semitransparentes en Gtk+-3.0 con GtkMM

Screenshot 17-02-2016-070256
Es algo que está muy chulo, y puede hacer que la experiencia de usuario de nuestras aplicaciones sea mucho mejor, además de dar un punto friki si queremos intercalar información de fondo, o queremos hacer una animación, una ventana splash chula mientras arranca nuestro programa, etc.

Lo que tenemos que hacer es que nuestra ventana se pinte en un contexto RGBA (rojo, verde, azul, alpha), donde alpha es nuestro valor de opacidad. Tenemos que tener en cuenta que GTK+ manejará los valores de las componentes de color de la ventana (las mencionadas rojo, verde, azul, alpha, con valores entre 0 y 1, por lo que serán valores double).

Una vez establecido esto, tenemos que controlar cada redibujado de la ventana. Normalmente se gestiona el redibujado automáticamente para dibujar una ventana normal, pero podemos personalizarlo, para eso conectaremos signal_draw a una función propia (en nuestro caso drawBackground), y ahí le decimos cómo queremos redibujar la ventana. Allá va un fragmento de código para probar esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <gtkmm.h>
#include <iostream>

using namespace std;
using namespace Gtk;

bool drawBackground(const Cairo::RefPtr <Cairo::Context> & cr)
{
  cr->set_source_rgba(.2, 1.0, 1.0, 0.5);
  cr->set_operator(Cairo::OPERATOR_SOURCE);
  cr->paint();
  cout<< "Redibujado!!!"<<endl;
  return false;
}

int main(int argc, char **argv) {

  Main app(argc, argv);
  Button button("Un botoncillo");
  Window win;
  win.set_app_paintable(true);
  win.resize(300,150);
  win.set_name("ventana_principal");

  Glib::RefPtr<Gdk::Screen> screen = Gdk::Screen::get_default();
  Glib::RefPtr<Gdk::Visual> visual = screen->get_rgba_visual();
  if (visual)
    cout << "Tenemos RGBA \n";
  if (win.is_composited())
    cout << "Tenemos composite\n";

  /* gtk_widget set visual no está implementado en GtkMM por lo que tenemos que
     tirar de GTK para conseguirlo*/

  if (visual)
    gtk_widget_set_visual(GTK_WIDGET(win.gobj()), GDK_VISUAL(visual->gobj()));

  win.add(button);
  win.set_border_width(100);
  win.show_all();
  win.signal_draw().connect(sigc::ptr_fun(&drawBackground), false);

  app.run(win);
  return 0;
}

En el código anterior, para una aplicación real podríamos quitar los cout (son sólo informativos, para que veamos qué está haciendo este ejemplo).

Tenemos que prestar especial atención a la línea:

1
  cr->set_source_rgba(.2, 1.0, 1.0, 0.5);

En este caso:

  • El rojo se multiplica por .2 (por lo que casi no pintamos esta componente)
  • El azul por 1.0 (por lo que la pintamos completamente)
  • El verde por 1.0 (por lo que también la pintamos por completo)
  • El alpha por 0.5 (por lo que tendremos 50% de opacidad)

Podemos jugar como queramos con estos valores. Por ejemplo, si no queremos que la ventana tenga un tinte de ningún color (como esta, que está de un color más cyan), debemos poner:

1
  cr->set_source_rgba(1.0, 1.0, 1.0, 0.5);

o, por ejemplo, podemos poner el alpha a 0 para tener una ventana 100% transparente, aunque veamos los bordes y la cabecera, pero luego podremos quitarlos también.

Bueno, esto se supone que es un post rápido, otro día veremos que podemos crear una clase derivada de Window con más cosas chulas y así mejorar aún más la experiencia de usuario de nuestras aplicaciones.

También podría interesarte....

Leave a Reply