es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Dibujar un Clutter::Actor personalizado utilizando cairo.

Quiero crear un actor personalizado usando la biblioteca gráfica Cairo.
Estoy utilizando cluttermm y clutter-gtkmm.
Según algunas recomendaciones y códigos de amigos, esto se puede implementar en clutter (no cluttermm).
Un ejemplo en Vala:

using Clutter;

void main(string[] args)
{
    Clutter.init(ref args);

    // Nota: la API Clutter.Texture está obsoleta, pero la API que la reemplazó es muy engorrosa, por lo que continuamos utilizando Clutter.Texture
    var linus = new Texture.from_file("Linus_Torvalds.jpeg");

    int width, height;
    linus.get_base_size(out width, out height);

    var stage = new Stage() {
        width = width,
        height = height
    };

    stage.add_child(linus);

    var canvas = new Canvas() {
        width = width,
        height = height
    };

    canvas.draw.connect((cr, width, height) => {
        cr.set_line_width(10);
        cr.set_source_rgba(0, 0, 0, 1);
        cr.move_to(310, 355);
        cr.line_to(260, 340);
        cr.stroke();
        return true;
    });

    var canvasActor = new Actor() {
        x = 0,
        y = 0,
        width = width,
        height = height,
        content = canvas
    };

    stage.add_child(canvasActor);
    canvas.invalidate();
    stage.show();
    stage.destroy.connect(Clutter.main_quit);
    Clutter.main();
}

Sin embargo, cuando intento hacer esto en cluttermm y clutter-gtkmm, obtengo un error.
No se puede inicializar un miembro subobjeto de tipo ‘Clutter::Content *’ con un rvalor de tipo ‘Clutter::Canvas *’.
Sé que puedo usar la API COGL, pero creo que Cairo es una mejor opción para el dibujo en 2D.
Por favor, ayúdeme.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para crear un actor personalizado utilizando gráficos Cairo en cluttermm y clutter-gtkmm, puedes utilizar la clase Clutter::Canvas. Aquí tienes un ejemplo de fragmento de código en C++:

    #include <cluttermm.h>
    
    class MyActor : public Clutter::Actor
    {
    public:
        MyActor()
        {
            m_canvas = Clutter::Canvas::create(get_width(), get_height());
            m_canvas->set_size(get_width(), get_height());
            add_child(m_canvas);
    
            m_canvas->signal_draw().connect(sigc::mem_fun(this, &MyActor::on_draw));
        }
    
    private:
        Glib::RefPtr<clutter::canvas> m_canvas;
    
        bool on_draw(const Cairo::RefPtr<cairo::context>& cr)
        {
            cr->set_source_rgb(0.0, 0.0, 1.0);
            cr->move_to(0.0, 0.0);
            cr->line_to(get_width(), get_height());
            cr->stroke();
    
            return true;
        }
    };
    
    int main(int argc, char** argv)
    {
        Clutter::init(argc, argv);
    
        auto stage = Clutter::Stage::create();
        stage->set_size(400, 400);
    
        auto my_actor = MyActor();
        my_actor.set_size(200, 200);
        my_actor.set_position(100, 100);
        stage->add_child(my_actor);
    
        stage->show();
    
        Clutter::Main::run();
    
        return 0;
    }
    

    En este código, definimos un actor personalizado llamado MyActor que consiste en un Clutter::Canvas. El objeto Clutter::Canvas se crea y se añade a los hijos del actor en el constructor. También conectamos la señal signal_draw() del canvas a una función miembro llamada on_draw() que toma un Cairo::Context como parámetro. En la función on_draw(), utilizamos Cairo para dibujar una línea diagonal en el canvas.

    Para utilizar este actor personalizado en una aplicación clutter-gtkmm, puedes crear un widget Gtk::ClutterEmbed y añadir el escenario (stage) a él. Aquí tienes un ejemplo:

    #include <cluttermm.h>
    #include <gtkmm.h>
    
    class MyActor : public Clutter::Actor
    {
        // Igual que antes
    };
    
    int main(int argc, char** argv)
    {
        Gtk::Main kit(argc, argv);
    
        Clutter::init();
    
        auto stage = Clutter::Stage::create();
        stage->set_size(400, 400);
    
        auto my_actor = MyActor();
        my_actor.set_size(200, 200);
        my_actor.set_position(100, 100);
        stage->add_child(my_actor);
    
        auto embed = Gtk::manage(new Gtk::ClutterEmbed());
        embed->set_size_request(400, 400);
        embed->realize();
    
        embed->add(stage->gobj());
    
        auto window = Gtk::Window();
        window.add(*embed);
    
        window.show_all();
    
        Clutter::Main::run();
    
        return 0;
    }
    

    En este código, creamos un widget Gtk::ClutterEmbed y añadimos el escenario a él utilizando el método add() del widget. Luego, creamos una ventana Gtk::Window y añadimos el widget Gtk::ClutterEmbed a ella. Finalmente, llamamos a Gtk::Main::run() para iniciar el bucle principal de eventos.</gtkmm.h></cluttermm.h></cluttermm.h>

Comments are closed.