Suggestion for Point selector widget Fl_Point

21 views
Skip to first unread message

anmol....@gmail.com

unread,
Oct 19, 2021, 2:00:30 PM10/19/21
to fltk.general
I am trying to create a widget that can be pointed into a box to select the pixel co-ordinates within. It has a click box next to it to activate the point selection crosshairs, and then the point co-ordinates inside the box will be selected.

Any suggestions ?

Greg Ercolano

unread,
Oct 19, 2021, 2:16:33 PM10/19/21
to fltkg...@googlegroups.com


On 10/19/21 11:00 AM, anmol....@gmail.com wrote:
I am trying to create a widget that can be pointed into a box to select the pixel co-ordinates within. It has a click box next to it to activate the point selection crosshairs, and then the point co-ordinates inside the box will be selected.

Any suggestions ?


    I'd suggest deriving a widget from Fl_Group that implements this pixel coordinate picking
    behavior, handle() to track the mouse movement. If I remember correctly, in response to
    FL_ENTER, return 1 so your widget gets FL_MOVE events, which gives tells you where the
    mouse is whenever it moves. Save the x/y coords from FL_MOVE in your widget and trigger
    a redraw() so that your draw() routine can draw() the crosshairs over the child widget.

    Then your app can create this widget as the parent, and make the widget with the
    visual elements to be picked a child of that. (e.g. an Fl_Box with an image() assigned to it)

    For flexibility, you'd probably want to implement this Fl_Group oriented widget
    so that a callback can be set to get the 'picking' events, so your app knows what to
    do when something is "picked".

    For drawing the cursor, you could try using the overlay plane stuff, but these days
    most machines are fast enough you can redraw the image/visual element and draw
    the cursor over that, redrawing each time the mouse FL_MOVE events are received.
    Just be sure to use an Fl_Double_Window so there's no flicker.

anmol....@gmail.com

unread,
Oct 20, 2021, 4:18:38 AM10/20/21
to fltk.general
Is there also an example for Fl_Counter widget or related without the arrows ? The user can simply click and re-enter value or click and move mouse for the value to increase - depending on whether the movement is to the right or left ?
Kind of like Fl_Scroller with an invisible scroll and just the value visible.

anmol....@gmail.com

unread,
Oct 20, 2021, 4:29:49 AM10/20/21
to fltk.general
I meant Fl_Roller with the invisible roller.

Ian MacArthur

unread,
Oct 20, 2021, 5:43:15 AM10/20/21
to fltk.general
On Wednesday, 20 October 2021 at 09:18:38 UTC+1 anmol wrote:
Is there also an example for Fl_Counter widget or related without the arrows ? The user can simply click and re-enter value or click and move mouse for the value to increase - depending on whether the movement is to the right or left ?
Kind of like Fl_Scroller with an invisible scroll and just the value visible.


Unless I have misunderstood your question, is that not just the behaviour of Fl_Value_Input ?
It has no scroller or adjuster widgets, you can enter a value directly, and if you click in the widget and drag you can adjust the value.
Which sounds like what you were asking for.


As an aside, some administrative issues: Please do not top post in this forum, it breaks the threading, and Please Do start a new topic for unrelated questions - asking this question in this thread (and indeed me answering it here!) will (again) mess up the threading...


Ian MacArthur

unread,
Oct 20, 2021, 6:51:18 AM10/20/21
to fltk.general
On Tuesday, 19 October 2021 at 19:16:33 UTC+1 erco wrote:

On 10/19/21 11:00 AM, anmol wrote:

I am trying to create a widget that can be pointed into a box to select the pixel co-ordinates within. It has a click box next to it to activate the point selection crosshairs, and then the point co-ordinates inside the box will be selected.

Any suggestions ?


    I'd suggest deriving a widget from Fl_Group that implements this pixel coordinate picking
    behavior, handle() to track the mouse movement. If I remember correctly, in response to
    FL_ENTER, return 1 so your widget gets FL_MOVE events, which gives tells you where the
    mouse is whenever it moves. Save the x/y coords from FL_MOVE in your widget and trigger
    a redraw() so that your draw() routine can draw() the crosshairs over the child widget.


Or you can probably use ::belowmouse() to figure out the co-ordinates even relative to non-child widgets too, I think.
Hmm, testing 
OK, example follows. Seems to work.

/*
 * fltk-config --compile track-cursor.cxx
 */

/* Standard headers */
#include <stdlib.h>

/* Fltk headers */
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/platform.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Output.H>
#include <FL/fl_draw.H>

// constants to define the view etc.
static const int win_size = 512;
// Output the mouse (x,y)
static Fl_Value_Output *valx = NULL;
static Fl_Value_Output *valy = NULL;

/*****************************************************************************/
class tracker_win : public Fl_Double_Window
{
public:
  tracker_win (int W, int H, const char *L = 0)
    : Fl_Double_Window(W, H, L) {
  }

private:
  int handle(int event);
};

// Event handling
int tracker_win::handle(int ev) {
  int res = Fl_Double_Window::handle(ev);
  switch (ev) {
    case FL_MOVE:
    {
      int X = Fl::event_x();
      int Y = Fl::event_y();
      Fl_Widget *tgt_widget = Fl::belowmouse ();
      int xw = tgt_widget->x();
      int yw = tgt_widget->y();
      int dx = X - xw;
      int dy = Y - yw;
      if (this == tgt_widget) {
        dx = X;
        dy = Y;
      }
      valx->value(dx);
      valy->value(dy);
    }
      res = 1;
      break;

    default:
      break;
  }
  return res;
} /* end of handle() method */
/*****************************************************************************/
static tracker_win *main_window = 0;

/*****************************************************************************/
// Quit button callback (closes the window)
void quit_cb(Fl_Button *b, void *) {
  main_window->hide();
}
/*****************************************************************************/
int main(int argc, char **argv)
{
  main_window = new tracker_win(win_size, win_size, "Mouse tracking demo");
  main_window->begin();
  main_window->box (FL_FLAT_BOX);

  Fl_Box *dummy_box = new Fl_Box (10, 10, 100, 100);
  dummy_box->box (FL_BORDER_BOX);

  Fl_Box *other_box = new Fl_Box (220, 220, 100, 100);
  other_box->box (FL_DOWN_BOX);

  valx = new Fl_Value_Output (130, 10, 40, 20, "X");
  valx->box (FL_THIN_DOWN_BOX);

  valy = new Fl_Value_Output (190, 10, 40, 20, "Y");
  valy->box (FL_THIN_DOWN_BOX);

  Fl_Button *quit_bt = new Fl_Button (10, 472, 60, 30, "Quit");
  quit_bt->box(FL_THIN_UP_BOX);
  quit_bt->callback((Fl_Callback *)quit_cb);

  main_window->end();
  main_window->resizable(main_window);

  main_window->show(argc, argv);

  return Fl::run();
} // main




Reply all
Reply to author
Forward
0 new messages