下面的代码,这两行按此顺序
tab1.add(glWindow2);
window->show();
产生这个图像:
但是如果我将添加调用放在 window->show 之后:
window->show();
tab1.add(glWindow2);
它会产生这个:
并且任何用户挑衅(切换选项卡、最小化和取消最小化窗口)都不会导致看到第二个球体。然而,在调试器中检查这一行的输出:
Fl_Widget * const *kids = tab1.array();
显示 tab1 确实有两个孩子。
那么add什么时候起作用,它是如何起作用的,以及可能还需要哪些其他操作才能使其真正生效?这到底是怎么回事,我正在恢复一些 20 年前的代码,这些代码曾经可以工作,但大约 10 年前它恰恰在这一点上崩溃了。我很想知道发生了什么变化。
节目:
#include <FL/Fl.H>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/gl.h>
#include <OpenGL/glu.h>
void glutWireSphere (GLdouble radius, GLint slices, GLint stacks);
class MyGlWindow : public Fl_Gl_Window {
private:
float blue;
public:
MyGlWindow(int x, int y, int w, int h, float bblue = 0.0f,
const char* l = 0) : Fl_Gl_Window(x, y, w, h, l) {
blue = bblue;
}
void draw() override {
if (!valid()) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w(), h());
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 5.0);
glEnable(GL_DEPTH_TEST);
valid(1);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set up the camera
gluLookAt(0.0, 0.0, 4.5, // eye position
0.0, 0.0, 0.0, // look-at position
0.0, 1.0, 0.0); // up direction
// Draw a sphere
glColor3f(0.5, 1.0, blue);
glutWireSphere(0.8, 20, 20);
glFlush();
}
};
int main() {
Fl_Window* window = new Fl_Window(400, 800, "FLTK Sphere Example");
Fl_Tabs mainTabs(0,5,window->w(),window->h()-32);
Fl_Group tab1(0,20,window->w(),window->h()-32, "Tab 1");
MyGlWindow* glWindow = new MyGlWindow(10, 60, window->w() - 20, 400 - 20, 0.0);
tab1.end();
MyGlWindow* glWindow2 = new MyGlWindow(10, 450, window->w() - 20, 400 - 20, 1.0);
Fl_Group tab2(0,64,window->w(),window->h()-32, "Tab2");
MyGlWindow* glWindow3 = new MyGlWindow(10, 100, window->w() - 20, 400 - 20, 0.5);
tab2.end();
mainTabs.end();
window->resizable(window);
window->end();
tab1.add(glWindow2);
window->show();
Fl_Widget * const *kids = tab1.array();
return Fl::run();
}
问:“添加什么时候起作用”? 答:基本上/总是/。 A->add(B) 将小部件 B 添加到小部件 A 的子项列表中。如果 B 已经是某个组(包括 A)的子项,则首先将其从该组中删除,然后添加到 A 组中。
问:“它是如何工作的”? 答:上面已经部分回答了。 FLTK 有一个“当前组”
Fl_Group::current()
,每当 Fl_Group
小部件的构造函数被调用时,就会通过组构造函数中的隐式 begin()
进行设置。除非当前组为 NULL,否则所有新小部件都会成为当前组的子级。调用 end() 使当前组的父窗口小部件成为新的当前组,该组可能为 NULL,例如用于主窗口。
示例程序的问题只是与这些问题间接相关。目前,
glWindow2
成为 mainTabs
的直接子级,因为 tab1.end()
在构造之前被调用。 Fl_Tabs
的子代受到特殊对待:任何时候都只能看到一个直系子代。因此 glWindow2
在程序开始时被隐藏 - 至少在 FLTK 1.4(开发)中。
该问题有两种(甚至更多)解决方案:
MyGlWindow* glWindow2 = new MyGlWindow(...)
移到 tab1.end()
之前。
2a.在 glWindow2->set_visible();
之后添加 tab1.add(glWindow2);
或
2b.在 glWindow2->show()
之后添加 window->show();
。我很想知道发生了什么变化。
这个很难说清楚。请注意,处理子窗口部分取决于平台(根据您在 macOS 上的屏幕截图)。 FLTK 开发仍在继续,您的旧程序可能使用了一种“未定义”行为。在任何人都能说出“发生了什么变化”之前,我们需要知道涉及哪些 FLTK 版本。 “一些 20 年前的代码”和“一些 10 年前”并不是很精确。 ;-)
我建议现在专注于 FLTK 1.4,因为这是当前的开发。如果您还有其他问题,我建议您在官方 FLTK“论坛”(Google 群组)fltk.general 中提问。 HTH