用Gtkmm实现利用鼠标事件绘制直线

3
我希望你能在Gtk :: DrawableArea上使用鼠标事件来绘制一条线。 我想要的是:
  1. 单击"Line Button"以激活线事件
  2. 在绘图区中选择第一个点(已经绘制)
  3. 现在选择第二个点(同样已经绘制)
  4. 线应该在两个点之间绘制出来
我已经拥有以下内容:
  1. Gtk::DrawingArea
  2. 使用cairo手动绘制的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;
}

附言:我可以在on_draw函数中轻松地添加两个点。我是Gtkmm的新手,所以请帮忙解释一下。

1个回答

4
你需要使用add_events(Gdk::BUTTON_PRESS_MASK)方法设置鼠标按键事件的掩码。然后你需要编写on_button_press_event(GdkEventButton *event)函数,在鼠标按键事件发生时被调用。 以下是一个示例程序:

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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接