FLTK 1.3:如何确定fl_line()的“上下文”?

问题描述 投票:0回答:1

正在寻找一些适用于 Linux 的简约 C++ GUI 框架,因此我在这里尝试熟悉 FLTK 1.3 / Ubuntu。编写了一些工作代码,以 30 FPS 的速度以随机颜色制作一些类似随机信号波的动画。它的工作有一些小问题:完全不知道波浪会被吸引到哪里。在窗口中、按钮上或对话框中(当出现时)。

似乎我不明白如何为

fl_line()
之类的函数定义某种“上下文”。每次调用
fl_like()
时,都会在某个不可预测的位置绘制线条。

当您将焦点放在按钮上时,线条开始在该按钮上绘制。当您调用对话框时,您会在那里看到线条,而且该对话框上的按钮也会被线条覆盖!当您关闭对话框时,这些行仅写在“关闭”按钮上。

所以,我的问题是如何预测将绘制的线条的“视觉上下文”(FLTK 中是否有这样的术语)。

我的代码:

#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/fl_message.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <cstdlib>

namespace simulator {

class Graph : public Fl_Widget {
  unsigned char color_[3] = {0, 0, 0};

public:
  Graph(int X, int Y, int W, int H)
  : Fl_Widget(X, Y, W, H) {
  }

  void draw(void) {
    this->plot();
  }

  void plot() {
    // Pick some trash color in a trash way.
    color_[0] = rand() % 256;
    color_[1] = rand() % 256;
    color_[2] = rand() % 256;
    fl_color(color_[0], color_[1], color_[2]);

    // Draw some random "audio wave"-like thing
    // Dont care about cleaning the scene before drawing.
    int old[2] = {0, 0};
    for (int i = 0; i < 400; ++i) {
      auto x = i * 2;
      auto y = rand() % 400;
      fl_line(old[0], old[1], x, y);
      old[0] = x;
      old[1] = y;
    }
  }
};

class Main_Window : public Fl_Window {
  //public Fl_Double_Window {
  Fl_Button button_ {10, 10, 75, 25, "Close"};
  Graph graph_;

public:
  Main_Window()
  //: Fl_Double_Window(200, 100, 1200, 800, "Simulator")
  : Fl_Window(200, 100, 1200, 800, "Simulator")
  , graph_(10, 100, 500, 500) {

    begin();
    Fl::visual(FL_RGB); 
    button_.align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP | FL_ALIGN_WRAP);
    // Button will invoke dialog "Want to exit?" with "yes/no" buttons.
    button_.callback([](Fl_Widget* sender, void* window) {
      printf("callback called, sender %p, window %p\n", sender, window);
      reinterpret_cast<Main_Window*>(window)->hide();
    }, this);
    
    // Maybe this is some illegal/unneeded/not-perfect widget adding code, and maybe widget adding is not needed at all; Lets forget about this for now.
    add(&button_);
    add(&graph_);

    end();
    show();
    graph_.show();
  }

  void hide() override {
    fl_message_hotspot(false);
    fl_message_title("Close window");
    if (fl_choice("Are you sure you want exit?", "No", "Yes", nullptr) == 1) {
      Fl_Window::hide();
    }
  }

  void plot() {
    graph_.plot();
  }
};
} // namespace

// 30 FPS wave animation.
void winUpdate(void *_data) {
  auto *window = reinterpret_cast<simulator::Main_Window*>(_data);
  Fl::add_timeout(1.0 / 30.0, winUpdate, window);
  window->plot();
}

int main(int argc, char *argv[]) {
  simulator::Main_Window window;
  window.show(argc, argv);
  Fl::add_timeout(1.0 / 30.0, winUpdate, &window);
  return Fl::run();
}

构建命令:

/usr/bin/x86_64-linux-gnu-g++-12 test.cpp -o test -I/usr/include/c++/12 -std=c++20 -Wuninitialized -Wall -Wextra -Werror -Wno-deprecated-declarations -Wno-sign-compare -Wno-type-limits -Wunused-function -ggdb -fno-strict-aliasing -fwrapv -fno-stack-protector -fno-strict-overflow -Wfatal-errors `fltk-config --ldflags` -lfltk -lfltk_images -ljpeg -lstdc++ -lXfixes -lXext
c++ fltk
1个回答
0
投票

找到了正确的方向。如果你想重绘一个小部件,永远不要直接调用

draw()
或一些绘图函数,如
fl_line()
。您宁愿调用
widget->redraw()
,FLTK 将安排正确重新绘制该小部件。

所以,在我的代码中,

Main_Window::plot()
必须做
graph_.redraw();
而不是
graph_.plot();

© www.soinside.com 2019 - 2024. All rights reserved.