Re: Motion events in a DrawingArea



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]