【问题标题】:FLTK: Clearing a graph when drawing anotherFLTK:绘制另一个图形时清除一个图形
【发布时间】:2021-12-16 00:26:59
【问题描述】:

我编写了一个简单的 FLTK 程序,在单击“画圆”按钮时画一个圆,并在单击“画线”按钮时画一条线。我应该只有一张图。但是我在面板中有两个图表。我只想要一个显示而另一个消失。以下是代码:

#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Box.H>

using namespace std;

int flag = 0;
class Drawing : public Fl_Box {
    void draw() {
        fl_color(255, 0, 0);
        int x, y, x1, y1;
        if (flag == 1) {
            
            double radius = 100;
            x = (int)(w() / 2);
            y = (int)(h() / 2);
            fl_circle(x, y, radius);
        }
        else if (flag == -1) {
            
            x = (int)(w() / 4);
            y = (int)(h() / 4);
            x1 = (int)(w() *3/ 4);
            y1 = (int)(h() *3/ 4);
            fl_line(x, y, x1, y1);
        }
    }
public:
    Drawing(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H) {}
};

Drawing* d;

void circle_cb(Fl_Widget*, void*) {
    flag = 1;
    fl_overlay_clear();
    d->redraw();
} // end sumbit_cb

void line_cb(Fl_Widget*, void*) {
    flag = -1;
    fl_overlay_clear();
    d->redraw();
} // end clear_cb

int main(int argc, char** argv) {
    Fl_Window* window = new Fl_Window(600, 550); // create a window, originally(400,400)

    Drawing dr(0, 0, 600, 600);
    d = &dr;

    Fl_Button *b, *c;

    b = new Fl_Button(150, 80, 100, 25, "&Draw Circle");
    b->callback(circle_cb);

    c = new Fl_Button(350, 80, 100, 25, "&Draw Line");
    c->callback(line_cb);

    window->end(); //show the window 
    window->show(argc, argv);
    return Fl::run();
}

我使用 fl_overlay_clear() 来清除图形。但是它不起作用。任何帮助将不胜感激。

【问题讨论】:

    标签: c++ fltk


    【解决方案1】:

    只是对 Albrecht 完美表述的快速补充:FLTK 绘图坐标是相对于窗口的,而不是相对于小部件的。您可能希望通过小部件的x()y() 坐标来偏移绘图。

    【讨论】:

    • 好收获。我一定错过了。
    【解决方案2】:

    你的程序有几个问题需要修复,但首先像你做的那样使用draw()方法基本上是正确的。但是,使用 fl_overlay_clear();没用,你可以去掉。

    我的解决方案:您的小部件没有纯色背景(boxtype),即您的 draw 方法一遍又一遍地在背景上绘制而不清除它。有几种方法可以解决这个问题,但如果你想了解会发生什么,请先试试这个:在window-&gt;show(argc, argv); 之前添加window-&gt;resizable(window);,再次运行程序并调整窗口大小。您会注意到上一张图消失了,只留下一张图。那是因为当您调整小部件的大小时,背景会被清除。

    下一步:添加一个solid boxtype:

      d = &dr;
      d->box(FL_DOWN_BOX);
    

    并在 draw() 方法的开头添加 Fl_Box::draw();

    如果您这样做,您可能会注意到当您单击其中一个按钮时按钮会消失 - 因为您的按钮您的Drawing 区域内。我修复的最后一件事是更正按钮的坐标并放大窗口(无论如何它太小而无法覆盖整个Drawing)。这是我的完整结果:

    #include <FL/Fl.H>
    #include <FL/Fl_Button.H>
    #include <FL/Fl_Double_Window.H>
    #include <FL/fl_draw.H>
    #include <FL/Fl_Box.H>
    
    using namespace std;
    
    int flag = 0;
    class Drawing : public Fl_Box {
      void draw() {
        Fl_Box::draw();
        fl_color(255, 0, 0);
        int x, y, x1, y1;
        if (flag == 1) {
    
          double radius = 100;
          x = (int)(w() / 2);
          y = (int)(h() / 2);
          fl_circle(x, y, radius);
        } else if (flag == -1) {
    
          x = (int)(w() / 4);
          y = (int)(h() / 4);
          x1 = (int)(w() * 3 / 4);
          y1 = (int)(h() * 3 / 4);
          fl_line(x, y, x1, y1);
        }
      }
    
    public:
      Drawing(int X, int Y, int W, int H)
        : Fl_Box(X, Y, W, H) {}
    };
    
    Drawing *d;
    
    void circle_cb(Fl_Widget *, void *) {
      flag = 1;
      // fl_overlay_clear();                       // not useful
      d->redraw();
    } // end sumbit_cb
    
    void line_cb(Fl_Widget *, void *) {
      flag = -1;
      // fl_overlay_clear();                       // not useful
      d->redraw();
    } // end clear_cb
    
    int main(int argc, char **argv) {
      Fl_Window *window = new Fl_Window(600, 660); // create a window, originally(400,400)
    
      Drawing dr(0, 60, 600, 600);                        // FIXED
      d = &dr;
      d->box(FL_DOWN_BOX);                                // ADDED
    
      Fl_Button *b, *c;
    
      b = new Fl_Button(150, 20, 100, 25, "&Draw Circle"); // FIXED
      b->callback(circle_cb);
    
      c = new Fl_Button(350, 20, 100, 25, "&Draw Line");   // FIXED
      c->callback(line_cb);
    
      window->end(); // show the window
      window->resizable(window);              // ADDED
      window->show(argc, argv);
      return Fl::run();
    }
    

    我相信这可以满足您的需求。

    PS:官方 FLTK 支持论坛可以在我们的网站https://www.fltk.org/ 上找到,用户论坛(Google Groups)的直接链接是https://groups.google.com/g/fltkgeneral

    【讨论】:

    • 非常感谢。这就是我想要的。
    【解决方案3】:

    在您的 handle() 方法中,line_cb()circle_cb() 应该在 FL_DRAG 事件之后调用 window()-&gt;make_current()fl_overlay_rect(),并且应该在 FL_RELEASE event 之后调用 fl_overlay_clear()Refer了解更多详情

    【讨论】:

    • 感谢您回答我的问题。你能说得更详细些吗?
    • 嗯,我认为这个答案没有帮助,因为 OP 正确使用了类的虚拟 draw() 方法。我会发布另一个答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多