FLTK的UI设计工具FLUID使用方法总结

article/2025/9/1 13:15:32

tags: FLTK C++ GUI

写在前面

终于又捡起来FLTK了, 先来看看怎么通过FLUID创建一个图形界面并完成回调函数的创建, 参考的是官方教程中关于创建一个CubeView程序的例子, 教程里面很多都与最新版本的FLTK界面不太一致, 但是通过我的摸索还是找出了方法. 下面来分享一下.

创建类

直接点New新建各种类型即可, 一些注意事项在官方文档中给出了, 一些类或者组件的名称都用粗体标出来了(如下图), 需要对应, 不然后面回调函数连接不上.

CubeViewUI类中主要实现了构造函数以及一个show方法, 用于显示窗体.

截屏2022-12-26 17.30.09

最后的结果如下, 这里其实主要是要看清楚是水平组件还是垂直组件, 这个很重要, 其次就是主窗体的大小, 配比要合适.

截屏2022-12-26 17.30.40

回调函数

其实就是两行, 主要用于五个主要组件中, 分为两组:

slider

  1. Zoom:

    cube->size=((Fl_Value_Slider *)o)->value();
    cube->redraw();
    
  2. ypan:

    cube->pany(((Fl_Value_Slider *)o)->value()); 
    cube->redraw();
    
  3. xpan:

    cube->panx(((Fl_Value_Slider *)o)->value()); 
    cube->redraw();
    

roller

  1. vrot:

    cube->v_angle(((Fl_Roller *)o)->value()); 
    cube->redraw();
    
  2. hrot

    cube->h_angle(((Fl_Roller *)o)->value()); 
    cube->redraw();
    

CubeView类(显示图形)

最后是主要的显示窗体的类, 这需要在extra Code部分添加头文件声明:

#include "CubeView.h"

这部分代码如下:

// CubeView.h
#include <FL/gl.h>
#include <FL/Fl_Gl_Window.H>
#include <math.h>class CubeView : public Fl_Gl_Window {
public:CubeView(int x, int y, int w, int h, const char *l = 0);// this value determines the scaling factor used to draw the cube.double size;/* Set the rotation about the vertical (y ) axis.** This function is called by the horizontal roller in CubeViewUI* and the initialize button in CubeViewUI.*/void v_angle(float angle) { vAng = angle; };// Return the rotation about the vertical (y ) axis.float v_angle() { return vAng; };/* Set the rotation about the horizontal (x ) axis.** This function is called by the vertical roller in CubeViewUIand the* initialize button in CubeViewUI.*/void h_angle(float angle) { hAng = angle; };// the rotation about the horizontal (x ) axis.float h_angle() { return hAng; };/* Sets the x shift of the cube view camera.** This function is called by the slider in CubeViewUI and the* initialize button in CubeViewUI.*/void panx(float x) { xshift = x; };/* Sets the y shift of the cube view camera.** This function is called by the slider in CubeViewUI and the* initialize button in CubeViewUI.*/void pany(float y) { yshift = y; };/* The widget class draw() override.* The draw() function initialize Gl for another round of* drawing then calls specialized functions for drawing each* of the entities displayed in the cube view.*/void draw();private:/* Draw the cube boundaries* Draw the faces of the cube using the boxv[] vertices, using* GL_LINE_LOOP for the faces. The color is #defined by* CUBECOLOR.*/void drawCube();float vAng, hAng;float xshift, yshift;float boxv0[3];float boxv1[3];float boxv2[3];float boxv3[3];float boxv4[3];float boxv5[3];float boxv6[3];float boxv7[3];
};
// CubeView.cxx
#include "CubeView.h"CubeView::CubeView(int x, int y, int w, int h, const char *l): Fl_Gl_Window(x, y, w, h, l) {vAng = 0.0;hAng = 0.0;size = 10.0;/* The cube definition. These are the vertices of a unit cube* centered on the origin.*/boxv0[0] = -0.5;boxv0[1] = -0.5;boxv0[2] = -0.5;boxv1[0] = 0.5;boxv1[1] = -0.5;boxv1[2] = -0.5;boxv2[0] = 0.5;boxv2[1] = 0.5;boxv2[2] = -0.5;boxv3[0] = -0.5;boxv3[1] = 0.5;boxv3[2] = -0.5;boxv4[0] = -0.5;boxv4[1] = -0.5;boxv4[2] = 0.5;boxv5[0] = 0.5;boxv5[1] = -0.5;boxv5[2] = 0.5;boxv6[0] = 0.5;boxv6[1] = 0.5;boxv6[2] = 0.5;boxv7[0] = -0.5;boxv7[1] = 0.5;boxv7[2] = 0.5;
};
// The color used for the edges of the bounding cube.
#define CUBECOLOR 255, 255, 255, 255
void CubeView::drawCube() {/* Draw a colored cube */
#define ALPHA 0.5glShadeModel(GL_FLAT);glBegin(GL_QUADS);glColor4f(0.0, 0.0, 1.0, ALPHA);glVertex3fv(boxv0);glVertex3fv(boxv1);glVertex3fv(boxv2);glVertex3fv(boxv3);glColor4f(1.0, 1.0, 0.0, ALPHA);glVertex3fv(boxv0);glVertex3fv(boxv4);glVertex3fv(boxv5);glVertex3fv(boxv1);glColor4f(0.0, 1.0, 1.0, ALPHA);glVertex3fv(boxv2);glVertex3fv(boxv6);glVertex3fv(boxv7);glVertex3fv(boxv3);glColor4f(1.0, 0.0, 0.0, ALPHA);glVertex3fv(boxv4);glVertex3fv(boxv5);glVertex3fv(boxv6);glVertex3fv(boxv7);glColor4f(1.0, 0.0, 1.0, ALPHA);glVertex3fv(boxv0);glVertex3fv(boxv3);glVertex3fv(boxv7);glVertex3fv(boxv4);glColor4f(0.0, 1.0, 0.0, ALPHA);glVertex3fv(boxv1);glVertex3fv(boxv5);glVertex3fv(boxv6);glVertex3fv(boxv2);glEnd();glColor3f(1.0, 1.0, 1.0);glBegin(GL_LINES);glVertex3fv(boxv0);glVertex3fv(boxv1);glVertex3fv(boxv1);glVertex3fv(boxv2);glVertex3fv(boxv2);glVertex3fv(boxv3);glVertex3fv(boxv3);glVertex3fv(boxv0);glVertex3fv(boxv4);glVertex3fv(boxv5);glVertex3fv(boxv5);glVertex3fv(boxv6);glVertex3fv(boxv6);glVertex3fv(boxv7);glVertex3fv(boxv7);glVertex3fv(boxv4);glVertex3fv(boxv0);glVertex3fv(boxv4);glVertex3fv(boxv1);glVertex3fv(boxv5);glVertex3fv(boxv2);glVertex3fv(boxv6);glVertex3fv(boxv3);glVertex3fv(boxv7);glEnd();
}; // drawCube
void CubeView::draw() {if (!valid()) {glLoadIdentity();glViewport(0, 0, w(), h());glOrtho(-10, 10, -10, 10, -20000, 10000);glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);}glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPushMatrix();glTranslatef(xshift, yshift, 0);glRotatef(hAng, 0, 1, 0);glRotatef(vAng, 1, 0, 0);glScalef(float(size), float(size), float(size));drawCube();glPopMatrix();
};

主文件(main)

#include "CubeViewUI.h"static int my_handler(int event) {if (event == FL_SHORTCUT) return 1;// eat all shortcut keysreturn 0;
}int main(int argc, char **argv) {CubeViewUI ui;Fl::add_handler(my_handler);ui.show(argc, argv);return Fl::run();
}

这里我加上了句柄函数, 这个函数用来使esc键失效, 否则在窗体中按下esc会直接关闭窗口.

编译链接

重点要说一下编译链接这块.

官方Makefile

先给出官方文档1中的Makefile, 其实用Cmake要方便一些, 但是Makefile也要会写才行.

CXX      = $(shell fltk-config --cxx)
DEBUG    = -g
CXXFLAGS = $(shell fltk-config --use-gl --use-images --cxxflags ) -I.
LDFLAGS  = $(shell fltk-config --use-gl --use-images --ldflags )
LDSTATIC = $(shell fltk-config --use-gl --use-images --ldstaticflags )
LINK     = $(CXX)TARGET = cube
OBJS =  CubeMain.o CubeView.o CubeViewUI.o
SRCS =  CubeView.cxx CubeViewUI.cxx.SUFFIXES: .o .cxx
%.o: %.cxx$(CXX) $(CXXFLAGS) $(DEBUG) -c $<all: $(TARGET)$(LINK) -o $(TARGET) $(OBJS) $(LDSTATIC)$(TARGET): $(OBJS)
CubeMain.o: CubeMain.cxx CubeViewUI.h
CubeView.o: CubeView.cxx CubeView.h CubeViewUI.h
CubeViewUI.o: CubeViewUI.cxx CubeView.hclean: $(TARGET) $(OBJS)rm -f *.o 2> /dev/nullrm -f $(TARGET) 2> /dev/null

CmakeLists

再给出Cmake文件(之前其实就介绍过)

cmake_minimum_required(VERSION 3.24)
project(fltk_proj)set(CMAKE_CXX_STANDARD 17)FIND_PACKAGE(FLTK REQUIRED)# 相当于gcc `-I`参数
include_directories("/opt/homebrew/include")
# 相当于gcc `-L`参数
link_directories("/opt/homebrew/lib")# 相当于gcc `-l`参数
link_libraries("fltk")
link_libraries("Xext")
link_libraries("X11")
link_libraries("m")# 添加可执行程序
add_executable(test1 CubeMain.cxx CubeViewUI.cxx CubeView.cxx)# MESSAGE(${FLTK_LIBRARIES})
TARGET_LINK_LIBRARIES(test1 ${FLTK_LIBRARIES})

最后如果想生成MacOS下的test.app目录, 那么只需要在命令行中输入:

fltk-config --post <前面生成的可执行文件名>

就会在同级目录下生成xxx.app了, 还是相当方便的.

部署.app目录的Shell脚本

后来我发现这个步骤可以通过Shell脚本来完成(fltk-config本质是就是一个可执行的脚本文件)

具体参考了fltk-config源码, 以及2. 脚本如下:

#!/bin/shcompile=$1
case "$compile" in
*.cxx)prog=$(basename "$compile" .cxx);;
*.cpp)prog=$(basename "$compile" .cpp);;
*.cc)prog=$(basename "$compile" .cc);;
*.C)prog=$(basename "$compile" .C);;
*)echo "ERROR: Unknown/bad C++ soure file extension on \"$compile\"!"exit 1;;
esacpost=$prog
echo Creating "$post.app" bundle for desktop...id=$(echo $post | tr ' ' '_')
echo $id# Make the bundle directory and move the executable there
rm -rf "$post.app/Contents/MacOS"
mkdir -p "$post.app/Contents/MacOS"
mv "$post" "$post.app/Contents/MacOS"# Make a shell script that runs the bundled executable
echo "#!/bin/sh" >"$post"
echo 'dir="`dirname \"$0\"`"' >>"$post"
echo 'exec "$dir/'"$post.app/Contents/MacOS/$post"'" "$@"' >>"$post"
chmod +x "$post"# Make the simplest Info.plist needed for an application
cat >"$post.app/Contents/Info.plist" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<plist version="0.9"><dict><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>CFBundleExecutable</key><string>$post</string><key>CFBundleIdentifier</key><string>org.fltk.$id</string><key>CFBundleName</key><string>$post</string><key>CFBundlePackageType</key><string>APPL</string><key>NSHighResolutionCapable</key><true/></dict>
</plist>
EOFecho "done!"

用法为:(保存为gen_app.sh)

./gen_app.sh test.cpp

终极版Makefile(集合编译链接与部署)

但是不够简洁, 于是想着把Shell集成在Makefile里面, 于是就有: (部分较官方文档有改动)

CXX      = $(shell fltk-config --cxx)
DEBUG    = -g
CXXFLAGS = $(shell fltk-config --use-gl --use-images --cxxflags ) -I.
LDFLAGS  = $(shell fltk-config --use-gl --use-images --ldflags )
LDSTATIC = $(shell fltk-config --use-gl --use-images --ldstaticflags )
LINK     = $(CXX)TARGET = cube
OBJS =  CubeMain.o CubeView.o CubeViewUI.o
SRCS =  CubeMain.cxx CubeView.cxx CubeViewUI.cxxAPP_NAME= $(TARGET)define info_plist
<?xml version="1.0" encoding="UTF-8"?> \
<plist version="0.9"> \<dict> \<key>CFBundleInfoDictionaryVersion</key> \<string>6.0</string> \<key>CFBundleExecutable</key> \<string>APP_NAME</string> \<key>CFBundleIdentifier</key> \<string>org.fltk.APP_NAME</string> \<key>CFBundleName</key> \<string>APP_NAME</string> \<key>CFBundlePackageType</key> \<string>APPL</string> \<key>NSHighResolutionCapable</key> \<true/> \</dict> \
</plist>
endef.SUFFIXES: .o .cxx
compile: $(SRCS)@echo "compiling..."@$(CXX) $(CXXFLAGS) $(DEBUG) -c $^all: compile link runbundle_app: clean_app package_apprun: compile link $(TARGET)./$(TARGET)package_app: compile link@echo "bundling..."@mkdir -p $(APP_NAME).app/Contents/{MacOS,Resources}@echo '$(info_plist)' > "$(APP_NAME).app/Contents/Info.plist"@sed -e "s/APP_NAME/$(APP_NAME)/g" -i "" "$(APP_NAME).app/Contents/Info.plist"@cp $(TARGET) "$(APP_NAME).app/Contents/MacOS/$(APP_NAME)"
#	cp -R "$(FRAMEWORK_PATH)/SDL2.framework" "$(APP_NAME).app/Contents/Resources/"link: $(OBJS)@echo "linking..."@$(LINK) -o $(TARGET) $(OBJS) $(LDSTATIC)clean: clean_app@echo "Delete *.o $(TARGET)..."@rm -f *.o 2> /dev/null@rm -f $(TARGET) 2> /dev/nullclean_app:@echo "Delete $(APP_NAME).app..."@rm -rf $(APP_NAME).app

用这套Makefile, 配合clion, 简直无敌!

效果

bb

几点注意

  1. Makefile缩进需要用制表符, 如果要用空格需要在开头加上.RECIPEPREFIX := $(.RECIPEPREFIX)<space>, 其中<space>是一个空格.
  2. FLUID界面也会被esc关闭, 注意保存, 可以通过快捷键⌘+S保存, 然后⌘+⇧+C生成头文件和源码.
  3. 控件通过拖放完成布局, 需要调整部分控件的范围与step, 例如roller和slider.
  4. 布局应该和回调函数分离, 便于维护, 后续会写相关文章.

ref


  1. FLTK 1.3.8: FLTK Basics; ↩︎

  2. 带有生成文件的应用程序捆绑包 - Joseph Long (joseph-long.com); ↩︎


http://chatgpt.dhexx.cn/article/dTbbBSAW.shtml

相关文章

fltk和glog在mac下的安装与编译

glog 根据官方文档安装即可 https://github.com/google/glog % git clone https://github.com/google/glog.git % cd glog % cmake -S . -B build -G "Unix Makefiles" //这句含义未知 % cmake --build build安装完后可以去/usr/local目录下查看是否有对应的头文件…

c语言fltk图形库,FLTK编程模型

2003 年 5 月 10 日 FLTK(Fast Light Tool Kit 发音为fulltick) 是一种使用C++开发的GUI工具包,它可以应用于Unix,Linux,MS-Windows95/98/NT/2000和MacOS操作系统平台,相对于其它的许多图形接口开发工具包(如MFC、GTK、QT等),它具有体积很小、速度比较快,且有着更好的移植性…

FLTK-Rs

终于还是到这一步了&#xff0c;可视化&#xff0c;我的超人&#xff01; FLTK是一个跨平台的轻量级 gui 库。该库本身是用 C98 编写的&#xff0c;具有很高的可移植性。fltk crate 是用 Rust 编写的&#xff0c;并使用 FFI 调用 FLTK 包装器cfltk&#xff0c;它是用 C89 和 C…

Visual Studio 安装 FLTK

Visual Studio 安装 FLTK 环境介绍 Windows 10Visual Studio Community 2019 (2021-11-29补充2022版)FLTK-1.3.7 下载与解压 ​ 进入FLTK官网-Download下载最新版本。 ​ 解压到D:\Program Files\fltk(解压路径任意都行)&#xff0c;推荐使用Bandzip免费解压工具。 编译 …

FLTK--轻量级C++跨平台GUI库

FLTK FLTK&#xff08;Fast Light Toolkit&#xff09;是一个跨平台的CGUI工具集&#xff0c;用在UNIX/Linux&#xff08;X11&#xff09;、微软Windows和Mac OS X上。FLTK提供现代的GUI功能&#xff0c;除却膨胀&#xff0c;通过OpenGL和内建的GLUT模拟器提供3D图形支持。最初…

浅谈如何fltk项目编译和实现显示中文

目录 一、编译 二、中文显示如何处理&#xff1a; 2.1在发文2天前突然发现&#xff0c;我这个界面显示英文出现问题了&#xff0c;开始我的搜索之旅&#xff0c;一些参考页面有碰到问题也可以看看&#xff1a; 2.2、 那就开始翻翻官方自带的例程吧&#xff0c;看看他如何显…

FLTK 学习一:简介和安装

文章目录 FLTK 简介FLTK 安装FLTK Windows安装FLTK Linux 安装 FLTK 简单示例参考资料 FLTK 简介 从网上引用的一段 FLTK 的介绍 FLTK (Fast Light Tool Kit 发音为fulltick) 是一种使用 C 开发的 GUI 工具包&#xff0c;它可以应用于 Unix, Linux, MS-Windows95/98/NT/2000 和…

安装使用FLTK图形库

FLTK是Fast Light Toolkit的简称&#xff0c;是一个跨平台的C GUI包&#xff0c;FLTK提供xiandai GUI功能&#xff0c;而且通过OpenGL支持3D图像。 下载FLTK安转包fltk-1.3.4-1-source.tar.gz&#xff1a; http://www.fltk.org/software.php?VERSION1.3.4&FILEfltk/1.3.…

BOBCAT: 基于双层优化的计算机化自适应测验(超硬核解读论文+阅读论文技巧)

文章目录 前言AbstractIntroductionCAT 介绍传统的认知诊断模型传统的CAT选题策略传统方法局限性 ContributionsBOBCAT框架双层优化问题BOBCAT框架BOBCAT 训练过程 OptimizationExperiments能力评估问题暴露和内容重叠问题选择 Conclusions 前言 大家好&#xff0c;我是小曾&a…

项目管理理论与实践(3)——如何进行有效的项目管理

对于具有成功并有效的项目管理经验的项目经理&#xff0c;还是非常难得的。因为项目管理并不是一件很简单的事情。虽然自己对于项目管理的理解还是处于初级阶段&#xff0c;但是利用自己学习到的理论知识&#xff0c;还是想做一次归纳&#xff0c;希望对大家能够受用。那么就开…

计算机自适应考试技巧,计算机自适应题库实现

在软件的开发中,基于题库的计算机自适应考试已成为一个重要的发展方向,而计算机自适应题库的建立就显得尤为重要。计算机自适应测验(Computerized Adaptive Testing,简称CAT)是近年来发展起来的一种新的测验形式。这种测验以项目反应理论为基础,以计算机技术为手段,在题库…

项目经理都会面临什么问题?

最近手里一个项目接近尾声&#xff0c;还有一个项目正在初期调研&#xff0c;无缝衔接&#xff0c;原定结项之后的3天假期也泡汤了&#xff0c;每一个环节都出问题我真的会心累&#xff0c;再加上最近组里人事变动&#xff0c;也没有及时做好复盘&#xff0c;客户又出现了临时需…

反应-扩散方程(Reaction-diffusion system)

文章目录 1. 单组分反应-扩散方程2. 双组分反应-扩散方程3. 三组分和更多组分的反应-扩散方程4. Fishers equation4.1 KPP方程 5. Belousov–Zhabotinsky reaction5.1 历史5.2 化学机理5.2.1 变体 5.3 Noise-induced order5.3.1 数学背景 6. Briggs–Rauscher reaction7. ZFK e…

项目延期的因素有哪些?项目经理应该如何应对

项目延期是项目管理中常见的问题之一&#xff0c;也是管理者最头疼的问题。项目延期的出现可能是由于以下原因&#xff1a; 1、工作中突发事件多&#xff1a;在评估工作量时&#xff0c;通常会基于过往的经验来进行评估&#xff0c;但由于信息社会中各种信息随处可见&#xf…

项目管理中影响项目进度的原因及解决方法

项目管理中对工期的控制主要是进度控制&#xff0c;在项目进行过程中&#xff0c;由于项目时间跨度长&#xff0c;人员繁杂&#xff0c;如果管理不规范&#xff0c;就容易导致项目进度滞后&#xff0c;如何管理好施工进度是管理者需要解决的问题之一。 1、项目计划缺乏执行力…

图解PMP项目管理马斯洛需求层次理论在公司管理中的应用!

马斯洛的需求层次结构是心理学中的激励理论&#xff0c;包括人类需求的五级模型&#xff0c;通常被描绘成金字塔内的等级。 从层次结构的底部向上&#xff0c;需求分别为&#xff1a;生理&#xff08;食物和衣服&#xff09;&#xff0c;安全&#xff08;工作保障&#xff09;…

php 项目反应理论,科学网—好文 | 纽约石溪大学:机器学习中基于项目反应理论的集成学习 - 陈培颖的博文...

机器学习中&#xff0c;研究者们对分类集成的关注与日俱增&#xff0c;尤其关注分类精度的提升。IJAC近期发表了来自纽约石溪大学研究者的最新成果&#xff0c;该研究基于项目反应理论&#xff0c;提出一种加权投票方法---基于IRT理论的集成学习算法&#xff0c;该方法可正确处…

项目反应理论 EM估计

项目反应理论参数的EM估计 写在前面&#xff1a; 本文主要描述了整个IRT使用EM算法参数的估计过程&#xff0c;其中涉及大量公式&#xff0c;如只是需要了解IRT相关基础知识&#xff0c;请转战wiki&#xff5e;&#xff5e; 预警&#xff1a; 大量公式来袭&#xff5e;&#…

项目反应理论

项目反应理论(item response theory)是属于心理学中认知诊断常用的一种理论,即根据被测试者针对某个问题的答案来对被测者的认知状况进行估计。“项目”实质就是测试题,“反应”就是被测者的答案。也有学者称项目反应理论也是机器学习中的一个类别,即根据被测者对测试题的…

密码校验密码正则校验,密码表单校验总结

一.前言&#xff0c;日常开发中&#xff0c;表单校验是出现率非常高的一个需求&#xff0c;特别是密码校验。本文就针对常见的几种密码校验&#xff08;含正则&#xff09;做个总结&#xff0c;做个共享。 二. 密码必须包含数字&#xff0c;字母和特殊符号。 写法&#xff1a;…