Re: Motion events in a DrawingArea
- From: Daniel Kasak <d j kasak dk gmail com>
- To: Torsten Schoenfeld <kaffeetisch gmx de>, gtk-perl mailing list <gtk-perl-list gnome org>
- Subject: Re: Motion events in a DrawingArea
- Date: Thu, 17 Aug 2017 20:33:12 +1000
Thanks Torsten.
I've gotten closer, and also reduced my app down to a minimal example
- see below.
So what's happening now is that my callback is being called, but
*only* when I click+drag inside the drawing area. Is there a different
signal that will fire for *just* mouse movements?
In the example, you can ignore the render_graph() and
draw_graph_text() methods - I left them there just so there was
*something* being rendered.
Dan
---
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
use Gtk3 -init;
use Pango;
my $window = Gtk3::Window->new;
$window->set_title('drawing area');
$window->signal_connect( destroy => sub { Gtk3->main_quit } );
my $drawing_area = Gtk3::DrawingArea->new;
$drawing_area->set_size_request( 600, 300 );
$drawing_area->signal_connect( draw => sub { render_graph( @_ ) } );
$drawing_area->set_events(
[ qw/ exposure-mask
leave-notify-mask
button-press-mask
motion_notify_event
pointer-motion-mask
pointer-motion-hint-mask
/
]
);
$drawing_area->signal_connect(
'motion_notify_event'
, sub { handle_graph_mouse_move( @_ ) }
);
$window->add( $drawing_area );
$window->show_all;
Gtk3->main();
sub render_graph {
my ( $widget, $cairo_context ) = @_;
use constant NO_OF_GRAPHS => 1;
use constant GRAPH_NO => 1;
my $surface = $cairo_context->get_target;
# Create a white backing for the graphs
$cairo_context->set_source_rgb( 0, 0, 0 );
my $total_width = $widget->get_allocated_width;
my $total_height = $widget->get_allocated_height;
my $graph_area_height = $total_height;
my $ac_power_y_scale = $graph_area_height / ( 3000 ) / NO_OF_GRAPHS;
my $y_segment = 1;
print "==================================\n";
print "total height: $total_height\n";
print "==================================\n";
my $earliest_sec = 0 * 3600;
my $latest_sec = 24 * 3600;
my $sec_scale = $total_width / ( $latest_sec - $earliest_sec );
$cairo_context->rectangle( 0, 0, $total_width, $total_height );
$cairo_context->fill;
$cairo_context->set_source_rgb( 255, 255, 255 );
# Now render the X & Y axis labels and partitioning lines
my $line_context = Cairo::Context->create( $surface );
$line_context->set_source_rgba( 1, 1, 1, 0.2 );
$line_context->set_line_width( 3 );
for ( my $hour = 0; $hour <= 24; $hour++ ) {
my $secs_past_earliest = ( $hour * 3600 ) - $earliest_sec;
my $this_x = $secs_past_earliest * $sec_scale;
# For the text label, the X value we pass into
$self->draw_graph_text is where it starts rendering text.
# We want the text centered around $this_x ... which is
different for 1 & 2 digit numbers ...
my $label_x_offset = $hour < 10 ? -3 : -8;
draw_graph_text( $cairo_context, $hour, 0, $this_x +
$label_x_offset, $total_height - 20 );
# white line
# $cairo_context->set_source_rgb( 255, 255, 255 );
# $cairo_context->rectangle( $this_x, $total_height, 5, 0 );
# $cairo_context->fill;
$line_context->move_to( $this_x, $total_height - 23 );
$line_context->line_to( $this_x, 0 );
$line_context->line_to( $this_x + 1, 0);
$line_context->line_to( $this_x + 1, $total_height - 23 );
$line_context->line_to( $this_x, $total_height - 23 );
$line_context->fill;
}
$cairo_context->set_source_rgb( 255, 255, 255 );
# kw scale
print "Rendering POWER axis ticks ...\n";
my $tick_increment = 3000 / 4;
foreach my $tick_no ( 1, 2, 3, 4 ) {
my $this_tick_value = $tick_no * $tick_increment;
my $y = ( $y_segment * GRAPH_NO ) - ( $tick_no *
$tick_increment * $ac_power_y_scale );
# For the text, the $y that we pass into $self->draw_graph_text
# is the TOP ( lower value ) that the text can occupy
my $label_y_offset = -8;
draw_graph_text(
$cairo_context
, $tick_no * $tick_increment
, 0
, 0
, $y + $label_y_offset
);
$line_context->move_to( 30, $y );
$line_context->line_to( $total_width, $y );
$line_context->line_to( $total_width, $y - 1 );
$line_context->line_to( 30, $y - 1 );
$line_context->line_to( 30, $y );
$line_context->fill;
}
}
sub draw_graph_text {
my ( $cr, $text, $angle, $x, $y ) = @_;
print "Writing [$text] at x [$x] y [$y]\n";
my $layout = Pango::Cairo::create_layout( $cr );
$layout->set_text( $text );
my $desc = Pango::FontDescription->from_string( "Sans Bold 10" );
$layout->set_font_description( $desc );
$cr->save;
$cr->rotate( $angle );
# Inform Pango to re-layout the text with the new transformation
Pango::Cairo::update_layout( $cr, $layout );
my ( $width, $height ) = $layout->get_size;
$cr->move_to( $x, $y );
Pango::Cairo::show_layout( $cr, $layout );
$cr->restore;
}
sub handle_graph_mouse_move {
my ( $widget, $event ) = @_;
use Data::Dumper;
print "event:\n" . Dumper( $event ) . "\n";
}
On Thu, Aug 17, 2017 at 3:35 AM, Torsten Schoenfeld <kaffeetisch gmx de> wrote:
On 16.08.2017 14:12, Daniel Kasak wrote:
I'm trying to capture mouse events in a DrawingArea ( in Gtk3 ). I'm
adapting code at http://www.perlmonks.org/?node_id=583578 ... but when
I go:
$self->{drawing_area}->set_events(
[ qw/ exposure-mask
leave-notify-mask
button-press-mask
pointer-motion-mask
pointer-motion-hint-mask
/
]
);
... I get a warning:
Gtk-CRITICAL **: gtk_widget_set_events: assertion
'!_gtk_widget_get_realized (widget)' failed
We would need to see more code to give specific advice, but the error
message suggests that you need to call set_events() earlier, because the
widget has already been realized. (Note the "!" in the assertion.)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]