Issue with Fl_Widget::image() - misalignment

18 views
Skip to first unread message

pvr...@btinternet.com

unread,
Apr 9, 2024, 5:30:43 PMApr 9
to fltk.general
I appear to have a problem with creating a custom image and loading it into a widget.

The image I am creating is to create an arrow indicating wind direction - see below.

The image when loaded appears to be misaligned upward by somewhere between 5 and 10 pixels. The effect can just about be seen in the attached PNG file. Look at the tab marked WX. The arrow should be centred in the widget aligned with the others (temperature, wind speed etc.). The text above should say: "clear sky" instead it says "clear skv" - the descender of the 'y' having been overwritten by the background of the image in the widget.

I will try and create a simple test case tomorrow.

Thanks Phil.

// Draw wind direction arrow in the supplied widget
void qso_wx::draw_wind_dirn(Fl_Widget* w, unsigned int dirn) {
// Find central position
int x_zero = w->w() / 2;
int y_zero = w->h() / 2;
// arrow will fill 80% widget
int radius = min(x_zero, y_zero) * 7 / 10;
float angle = dirn * DEGREE_RADIAN;
int x_disp = radius * sin(angle);
int y_disp = radius * cos(angle);
int x_start = x_zero + x_disp;
int y_start = y_zero - y_disp;
int x_end = x_zero - x_disp;
int y_end = y_zero + y_disp;
// Create the drawing surface
Fl_Image_Surface* image_surface = new Fl_Image_Surface(w->w(), w->h());
Fl_Surface_Device::push_current(image_surface);
// Draw the background
fl_color(FL_BACKGROUND_COLOR);
fl_rectf(0, 0, w->w(), w->h());
// Draw the line
fl_color(FL_FOREGROUND_COLOR);
if (dirn == -1) {
// No wind draw a circle
fl_arc(x_zero-(radius/2), y_zero-(radius/2), radius, radius , 0, 360);
} else {
fl_line(x_start, y_start, x_end, y_end);
float rad45 = 15 * DEGREE_RADIAN;
int arrow_len = radius;
float arrow_l = angle + rad45;
int x_arrow_l = x_end + (arrow_len * sin(arrow_l));
int y_arrow_l = y_end - (arrow_len * cos(arrow_l));
// fl_line(x_end, y_end, x_arrow_l, y_arrow_l);
float arrow_r = angle - rad45;
int x_arrow_r = x_end + (arrow_len * sin(arrow_r));
int y_arrow_r = y_end - (arrow_len * cos(arrow_r));
// fl_line(x_end, y_end, x_arrow_r, y_arrow_r);
fl_polygon(x_end, y_end, x_arrow_l, y_arrow_l, x_arrow_r, y_arrow_r);
}

Fl_RGB_Image* image = image_surface->image();
// Restore window before drawing widget
Fl_Surface_Device::pop_current();

// Now put the image into the widget
w->label("");
w->image(image);
}
image.png

Matthias Melcher

unread,
Apr 9, 2024, 5:34:04 PMApr 9
to fltk.general
Spontaneous and untested: You have set w->label() to an empty string which draws no characters, but it still keeps space for a line of code. Set w->label(NULL); or don't set the label at all. It's enough to set the image.

Matthias Melcher

unread,
Apr 9, 2024, 5:41:08 PMApr 9
to fltk.general
A much faster way would be to make your own wind_direction widget class, derived from Fl_Box or whatever. The override Fl_Box::draw() and draw the line and the arrow inside the wind_direction::draw() function. Something like this: (again untested)

class Wind_Direction : public Fl_Box {
  double direction_;
public:
   Wind_Direction(int x, int y, int w, int h, const char *l=NULL) 
  : Fl_Box(x, y, w, h, l), direction_(0.0) { }
  void draw() {
    Fl_Box::draw();
    fl_line(...math...);
    // alternatively, look at the "complex drawing function"
    // where you just set and angle and the draw a polygon (arrow)
    // which FLTK will rotate for you
  }
  void direction(double deg) {
    direction_ = deg;
    redraw();
  }
};

pvr...@btinternet.com

unread,
Apr 9, 2024, 6:03:12 PMApr 9
to fltk.general



From: 'Matthias Melcher' via fltk.general <fltkg...@googlegroups.com>
Sent: Tuesday, April 9, 2024 10:41 PM
To: fltk.general <fltkg...@googlegroups.com>
Subject: [fltk.general] Re: Issue with Fl_Widget::image() - misalignment
 
A much faster way would be to make your own wind_direction widget class, derived from Fl_Box or whatever. The override Fl_Box::draw() and draw the line and the arrow inside the wind_direction::draw() function. Something like this: (again untested)

Thanks Matthias, 

Not a starter for me as I use the widget to show the direction in one of several formats: degrees, cardinal (eg WNW) or an arrow.

Phil.

class Wind_Direction : public Fl_Box {
  double direction_;
public:
   Wind_Direction(int x, int y, int w, int h, const char *l=NULL) 
  : Fl_Box(x, y, w, h, l), direction_(0.0) { }
  void draw() {
    Fl_Box::draw();
    fl_line(...math...);
    // alternatively, look at the "complex drawing function"
    // where you just set and angle and the draw a polygon (arrow)
    // which FLTK will rotate for you
  }
  void direction(double deg) {
    direction_ = deg;
    redraw();
  }
};
--
You received this message because you are subscribed to a topic in the Google Groups "fltk.general" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/fltkgeneral/NNEP7HobzMg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/a194ffd9-8442-4e9b-9547-88fec8d78653n%40googlegroups.com.

pvr...@btinternet.com

unread,
Apr 9, 2024, 6:11:10 PMApr 9
to fltk.general
From: 'Matthias Melcher' via fltk.general <fltkg...@googlegroups.com>
Sent: Tuesday, April 9, 2024 10:34 PM

To: fltk.general <fltkg...@googlegroups.com>
Subject: [fltk.general] Re: Issue with Fl_Widget::image() - misalignment
Spontaneous and untested: You have set w->label() to an empty string which draws no characters, but it still keeps space for a line of code. Set w->label(NULL); or don't set the label at all. It's enough to set the image.

Spot on!.

I knew it was my misunderstanding.  

Thanks Phil.




pvr...@btinternet.com

unread,
Apr 10, 2024, 9:20:46 AMApr 10
to fltk.general
On Tuesday, April 9, 2024 at 10:41:08 PM UTC+1 Matthias Melcher wrote:

    // alternatively, look at the "complex drawing function"
    // where you just set and angle and the draw a polygon (arrow)
    // which FLTK will rotate for you
  }


Thanks Matthias,

I started to look at this in the cold light of day and yes it's definitely easier just to draw the polygon for the North wind and rotate it by the required number of degrees. I found the code in unittest_complex_shapes.cxx rather difficult to follow, but running the unit test and seeing how it worked definitely helped.

One issue: I found I had to use fl_rotate(-(double)dirn) to get it to rotate successfully, whereas fl_vertex((-)[int],(-)[int]) worked OK drawing the arrow.

So as I understood the process - to draw an arrow with the head starting 3/4 the length and +/-5 pixels wide. It looks a lot better than my trying to work out the angles and hoping I was using the trig functions correctly.

fl_push_matrix();
// Set the drawing to be centred in the widget and rotated by the wind direction
fl_translate(x_zero, y_zero);
fl_rotate(-(double)dirn);
fl_begin_complex_polygon();
// Draw an arrow down from North
fl_vertex(1, -radius);
fl_vertex(1, radius/2);
fl_vertex(5, radius/2);
fl_vertex(0, radius);
fl_vertex(-5, radius/2);
fl_vertex(-1, radius/2);
fl_vertex(-1, -radius);
//
fl_end_complex_polygon();
fl_pop_matrix();



Phil.
 

Albrecht Schlosser

unread,
Apr 10, 2024, 9:29:28 AMApr 10
to fltkg...@googlegroups.com
On 4/10/24 15:20 'pvr...@btinternet.com' via fltk.general wrote:
So as I understood the process - to draw an arrow with the head starting 3/4 the length and +/-5 pixels wide. It looks a lot better than my trying to work out the angles and hoping I was using the trig functions correctly.

fl_push_matrix();
// Set the drawing to be centred in the widget and rotated by the wind direction
fl_translate(x_zero, y_zero);
fl_rotate(-(double)dirn);
fl_begin_complex_polygon();
// Draw an arrow down from North
fl_vertex(1, -radius);
fl_vertex(1, radius/2);
fl_vertex(5, radius/2);
fl_vertex(0, radius);
fl_vertex(-5, radius/2);
fl_vertex(-1, radius/2);
fl_vertex(-1, -radius);
//
fl_end_complex_polygon();
fl_pop_matrix();


Thanks for sharing your code.

An even more simplistic approach would be to use FLTK's "symbols" if you only need the eight main directions (N, W, E, W, NW, NE, SW, SE). See the test/symbols.cxx demo, using the "symbol" '@N->' or any other appropriate symbol, e.g. '@Narrow' etc.

Of course, drawing the arrow yourself is more flexible...

pvr...@btinternet.com

unread,
Apr 10, 2024, 11:15:55 AMApr 10
to fltk.general
Thanks Albrecht,

I originally used the symbols, just wanted to get the flexibility.

Phil.

Ian MacArthur

unread,
Apr 10, 2024, 11:53:39 AMApr 10
to fltk.general
On Wednesday 10 April 2024 at 16:15:55 UTC+1 pvr...wrote:

I originally used the symbols, just wanted to get the flexibility.

For fancy widget drawing, always check in case Greg has a worked example you could take inspiration from... e.g.:


Or maybe even:


might do as starting places.

Reply all
Reply to author
Forward
0 new messages