FLTK:如何将图形对象置于前台?

问题描述

我在一个窗口中有两个可拖动对象:一个包含黑色方块的在背景中,而包含红色方块的一个在前景中。

Image Not Found

这种布局是由它们的绘制顺序决定的。我想在前景中放置我当前正在拖动的那个:例如,如果我拖动带有黑色方块的框,我希望它在前景中。一旦我放下它,它应该保持在前台。如果我拖动红色的,我希望它在前景中,而黑色在背景中。

我试图检查 FLTK 1.3.5 的关于 clipping 的文档,但我没有找到任何有用的东西(至少,就我所能理解的而言)。有什么方法可以实现我想要的吗?

下面列出了代码(源自 here)。

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_pixmap.H>
#include <iostream>

static char *Box1_xpm[] = {                       // XPM
"20 20 2 1","  c #000000","# c None","####################","#                  #","####################"
};

static char *Box2_xpm[] = {                       // XPM
"20 20 2 1","  c #FF0000","####################"
};

Fl_Double_Window *G_win    = NULL;
Fl_Scroll        *G_scroll = NULL;
static Fl_pixmap  G_Box1(Box1_xpm);
static Fl_pixmap  G_Box2(Box2_xpm);

#define BoxWIDTH  50
#define BoxHEIGHT 50

// A 'MOVABLE' Box
class Box : public Fl_Box {
protected:
    int handle(int e) {
        static int offset[2] = { 0,0 };
        int ret = Fl_Box::handle(e);
        switch ( e ) {
            case FL_PUSH:
                offset[0] = x() - Fl::event_x();    // save where user clicked for dragging
                offset[1] = y() - Fl::event_y();
                return(1);
            case FL_RELEASE:
                return(1);
            case FL_DRAG:
                position(offset[0]+Fl::event_x(),offset[1]+Fl::event_y());     // handle dragging
                G_win->redraw();
                return(1);
        }
        return(ret);
    }
public:
    Box(int X,int Y,int idx) : Fl_Box(X,Y,BoxWIDTH,BoxHEIGHT,0) {
        idx>0? image(G_Box1):image(G_Box2);
        Box(FL_UP_Box);
        color(FL_GRAY);
    }
};

/// MAIN
int main() {
    G_win = new Fl_Double_Window(200,200);
    new Box(20,2);
    new Box(20+BoxWIDTH,0);
    G_win->resizable(G_win);
    G_win->show();
    return(Fl::run());
}

解决方法

小部件按照它们在父级的 child() 列表中出现的顺序绘制。诀窍是确保拖动的小部件是最后绘制的小部件。改变push case如下

            case FL_PUSH:
                {
                    offset[0] = x() - Fl::event_x();    // save where user clicked for dragging
                    offset[1] = y() - Fl::event_y();

                    // Do we need to rearrange?
                    int last_ix = G_win->children() - 1;
                    Box* last = (Box*)G_win->child(last_ix);
                    if (last != this)
                    {
                        // Widgets get drawn in the order in which they were inserted.
                        // Remove this widget from the parent
                        G_win->remove(this);
                        // Re-add it at the bottom of the list
                        G_win->add(this);
                    }
                }
                return(1);