我正在制作一个处理平面图的应用程序,因此希望有一个图层对话框,允许用户打开/关闭平面图中的不同图层。
我想有一个弹出窗口,因此在运行时加载的平面图中的每一层都有一个复选框。每个复选框都是一个独立的小部件,我只有在编译时指定/创建的经验。但是,在这里我不知道在加载特定平面图之前我需要多少个复选框。
我的问题是如何在FLTK(我正在使用的)中创建这样的功能。我可以设想在启动图层对话时在回调中创建一个循环复选框小部件(每个都拥有一个通用的回调函数),但我不知道如何指示FLTK放置复选框小部件的位置。即我如何在运行时指示FLTK层对话窗口应该是父窗口小部件?或者我可以动态创建整个窗口,但是我担心窗口在被隐藏时被销毁(删除)。
N.B。我想在窗口关闭(隐藏)时删除小部件。在这一点上我也不清楚:我是否以通常的新/删除c ++方式删除小部件,还是使用Fl :: delete_widget()对话框(http://www.fltk.org/doc-1.3/group__fl__del__widget.html#ga609413ac47ba433d1e7da8678a27164f)
或者:有没有更好的方法来完成所有这些问题,哪一方可以解决所有这些问题?
答案 0 :(得分:1)
这是一个基于层数进行大小调整的简单示例。需要注意的主要事项是,如果使用向量,它会随着向量的增长而重新分配,因此保持指向向量中显示数据的指针可能会导致屏幕上出现垃圾。
如果您在某个const文件中设置小部件的大小,可以使用它来进行大小调整。
#include <FL/Fl.h>
#include <FL/fl_draw.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Check_Button.H>
#include <iostream>
#include <sstream>
#include <string>
#include <list>
#include <vector>
const int hsep = 10, vsep = 10, btnwid = 100, btnhgt = 20;
// The canvas layer
class Canvas : public Fl_Box
{
Fl_Offscreen& m_buffer;
public:
Canvas(int x, int y, int w, int h, Fl_Offscreen& buffer)
: Fl_Box(x, y, w, h)
, m_buffer(buffer)
{
}
void Clear()
{
fl_begin_offscreen(m_buffer);
fl_color(FL_WHITE);
fl_rectf(0, 0, w(), h());
fl_end_offscreen();
}
void draw()
{
fl_copy_offscreen(x(), y(), w(), h(), m_buffer, 0, 0);
}
};
// This structure exists because there is no callback that takes
// two client parameters. Also, the tag must exist for the life of
// the dialog.
class LayerWin;
class LayerCheck
{
public:
int m_layer;
std::string m_tag;
LayerWin* m_parent;
};
// The layer window
class LayerWin
{
int m_layers;
Fl_Window* m_dlg;
std::string m_title;
std::list<LayerCheck> m_tag;
Canvas* m_canvas;
Fl_Offscreen m_buffer;
std::vector<bool> m_layer;
public:
LayerWin(int layers)
: m_layers(layers)
, m_dlg(0)
{
}
~LayerWin()
{
delete m_dlg;
}
void Create()
{
int dlgwid = 400, dlghgt = 300;
std::ostringstream oss;
oss << m_layers << " Layers";
m_title = oss.str();
m_dlg = new Fl_Window(dlgwid, dlghgt, m_title.c_str());
m_dlg->set_modal();
int x = hsep, y = vsep;
for (int ll = 0; ll < m_layers; ++ll)
{
oss.str("");
oss << "Layer " << ll + 1;
LayerCheck dummy;
m_tag.push_back(dummy);
LayerCheck& actual = m_tag.back();
actual.m_tag = oss.str();
actual.m_layer = ll;
actual.m_parent = this;
Fl_Check_Button* btnCheck = new Fl_Check_Button(x, y, btnwid, btnhgt, actual.m_tag.c_str());
btnCheck->callback(_LayerCB, &actual);
m_layer.push_back(false);
y += vsep + btnhgt;
}
x = hsep + btnwid + hsep;
y = vsep;
int canw = dlgwid - x - 2 * hsep;
int canh = dlghgt - 3 * vsep;
m_buffer = fl_create_offscreen(canw, canh);
m_canvas = new Canvas(x, y, canw, canh, m_buffer);
m_canvas->Clear();
Fl_Button* btnClose = new Fl_Button(hsep, dlghgt - vsep - btnhgt, btnwid, btnhgt, "Close");
btnClose->callback(_CloseCB, this);
m_dlg->end();
m_dlg->show();
Fl::wait();
}
static void _CloseCB(Fl_Widget* w, void* client)
{
LayerWin* self = (LayerWin*)client;
delete self;
}
static void _LayerCB(Fl_Widget* w, void* client)
{
Fl_Check_Button* btn = (Fl_Check_Button*)w;
LayerCheck* check = (LayerCheck*)client;
check->m_parent->LayerCB(check->m_layer, !!btn->value());
}
void LayerCB(int layer, bool set)
{
std::cout << "Layer " << layer+1 << "=" << set << std::endl;
m_layer[layer] = set;
// Redo the canvas
m_canvas->Clear();
fl_begin_offscreen(m_buffer);
for (int ll = 0; ll < m_layer.size(); ++ll)
{
if (m_layer[ll])
{
switch (ll)
{
case 0:
fl_color(FL_RED);
fl_circle(20, 40, 100);
break;
case 1:
fl_color(FL_DARK_GREEN);
fl_rectf(50, 70, 20, 40);
break;
case 2:
fl_color(FL_BLUE);
fl_circle(100, 100, 50);
break;
case 3:
fl_color(FL_DARK_MAGENTA);
fl_circle(200, 200, 70);
break;
case 4:
fl_color(FL_DARK_CYAN);
fl_rectf(100, 200, 60, 90);
break;
default:
std::cout << "Don't know what to do for layer " << ll + 1;
break;
}
}
}
fl_end_offscreen();
m_canvas->redraw();
}
};
void LayerCB(Fl_Widget* w, long layers)
{
// Create a modal dialog with layers checkbuttons
LayerWin* dlg = new LayerWin(layers);
dlg->Create();
}
int main()
{
// Work out the sizes
int scrwid = btnwid + 2 * hsep, scrhgt = 2 * vsep + 3 * (vsep + btnhgt);
// Create the main dialog
Fl_Window mainwin(scrwid, scrhgt, "Layers");
int x = hsep;
int y = vsep;
Fl_Button* button = new Fl_Button(x, y, btnwid, btnhgt, "3 layers");
button->callback(LayerCB, 3);
y += vsep + btnhgt;
button = new Fl_Button(x, y, btnwid, btnhgt, "4 layers");
button->callback(LayerCB, 4);
y += vsep + btnhgt;
button = new Fl_Button(x, y, btnwid, btnhgt, "5 layers");
button->callback(LayerCB, 5);
mainwin.end();
mainwin.show();
return Fl::run();
}