Gtkmm нарисовать линию с событиями мыши

Я хочу нарисовать линию с помощью мышиных событий на Gtk::DrawableArea, Что я хочу, это что-то вроде:

  1. Нажмите на кнопку "Линия", чтобы активировать событие линии
  2. Выберите первую точку (уже нарисованную) в области рисования
  3. Теперь выберите вторую точку (снова уже нарисованную) в области рисования.
  4. линия должна быть проведена между двумя точками

Что у меня уже есть:

  1. Gtk::DrawingArea
  2. 2 точки (ручные кружки), нарисованные с помощью Каира, необходимые для создания линии

Это мой конструктор, который вызывает функцию on_draw.

 drawingArea:: drawingArea()
 {
    signal_draw().connect(sigc::mem_fun(*this, &drawingArea::on_draw), false);
 }

И функция on_draw рисует фон:

bool drawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
    cr->set_source_rgb(1.0, 1.0, 1.0);   // white background
    cr->paint();

    cr->save();
    cr->arc(10.0, 10.0, 1.0, 0.0, 2 * M_PI); // full circle        
    cr->set_source_rgba(0.0, 0.0, 0.8, 0.6); // partially translucent
    cr->fill_preserve();
    cr->restore();  
    cr->stroke();

    return true;
}

PS: я могу легко добавить две точки в эту функцию on_draw. Я новичок в Gtkmm, так что помогите пролить немного света на это.

1 ответ

Вы должны установить маску события нажатия кнопки мыши с помощью метода add_events(Gdk::BUTTON_PRESS_MASK). И тогда у вас есть функция on_button_press_event(событие GdkEventButton *), которая вызывается, когда наступает событие нажатия кнопки мыши. Вот пример этой программы:

DrawingArea.h

#ifndef DRAWINGAREA_H
#define DRAWINGAREA_H

#include <gtkmm.h>


class DrawingArea: public Gtk::DrawingArea {
    public: DrawingArea();

    protected:
        // Override default signal handler:
        virtual bool on_draw(const Cairo::RefPtr < Cairo::Context > & cr);

        // Override mouse events
        bool on_button_press_event(GdkEventButton * event);

    private:

        //display Pixbuf
        Glib::RefPtr < Gdk::Pixbuf > display;

        //two coordinates
        int x1;
        int y1;
        int x2;
        int y2;
        //two bools for the clicks
        bool firstclick;
        bool secondclick;

};
#endif // DRAWINGAREA_H

DrawingArea.cpp

#include "DrawingArea.h"

DrawingArea::DrawingArea()
{
    // Set masks for mouse events
    add_events(Gdk::BUTTON_PRESS_MASK);
    //startvalues
    firstclick=false;
    secondclick=false;
}

// Mouse button press event
bool DrawingArea::on_button_press_event(GdkEventButton *event)
{
    // Check if the event is a left(1) button click.
    if( (event->type == GDK_BUTTON_PRESS) && (event->button == 1) )
    {
        //check whether this is the first click
        if(!firstclick&&!secondclick)
        {
            //the first coordinate
            x1=event->x;
            y1=event->y;
            firstclick=true;
        }
        //check whether this is the second click, and not on the same point as the previous
        if(firstclick&&!secondclick&&(int)event->x!=x1&&(int)event->y!=y1)
        {
            //the second coordinate
            x2=event->x;
            y2=event->y;
            secondclick=true;
            //refresh the screen
            queue_draw();
        }
        // The event has been handled.
        return true;
    }
}
// Call when the display need to be updated
bool DrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
    //check whether it was clicked two times
    if(firstclick&&secondclick)
    {
        //set the width of the line
        cr->set_line_width(2);
        //set the color: black
        cr->set_source_rgb(0,0,0);
        //move the "brush" to the first point
        cr->move_to(x1,y1);
        //draw the line to the second point
        cr->line_to(x2,y2);
        //draw the line
        cr->stroke();
    }
    return true;
}

main.cpp

#include <DrawingArea.h>
#include <gtkmm.h>


int main(int argc, char* argv[])
{
    // Initialize gtkmm and create the main window
    Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "betontalpfa");
    Gtk::Window window;

    // Create the drawing
    DrawingArea Dwg;
    // Insert the drawing in the window
    window.add(Dwg);
    // Size of the window
    window.resize(720,640);
    // Set the window title
    window.set_title("Line");
    // Show the drawing
    Dwg.show();

    // Start main loop
    return app->run(window);
}
Другие вопросы по тегам