Gtkmm нарисовать линию с событиями мыши
Я хочу нарисовать линию с помощью мышиных событий на Gtk::DrawableArea
, Что я хочу, это что-то вроде:
- Нажмите на кнопку "Линия", чтобы активировать событие линии
- Выберите первую точку (уже нарисованную) в области рисования
- Теперь выберите вторую точку (снова уже нарисованную) в области рисования.
- линия должна быть проведена между двумя точками
Что у меня уже есть:
Gtk::DrawingArea
- 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);
}