一篇文章讲明白Fltk1.3系列教程(3)

简介: 一篇文章讲明白Fltk1.3系列教程(3)

原创,转载请注明出处。Copyright (c) 2011 DingMaotu ()

深入布局

这节课我们学习如何把Fltk的各种Widgets排列在一起,对控件大小变化做出正确的反应。这里主要学习两个类:Fl_Widget和Fl_Group,他们是继承关系,前者是所有控件的父类,不能创建(只能继承),后者是所有容器的父类,可以作为通用容器创建。

上节课学的静态布局是布局的基础,但是不能对容器大小的改变做出正确的反应。使用Fl_Group把各种控件逻辑上组织起来,然后使用resizable函数,可以实现较为高级的布局。

1. 位置与大小

首先我们讲Fl_Widget有三个改变大小和位置的函数,分别如下:

size(width, height)

position(x, y)

resize(x, y, width, height)

这三个函数分别改变一个控件的大小、位置、同时大小和位置,比较简单,就不多说了。记着调用这些函数后可能需要调用redraw()重画控件。

2. 父与子

重点在于Fl_Group,这个类包含了一个子控件的列表,可以通过一系列方法来控制这个列表,例如:

Fl_Widget array() //获得这个列表(数组)

int children() //获得列表的大小(有几个子控件)

Fl_Widget child(int n) //获得第n个子控件

int find(Fl_Widget ) //查找某子控件在列表中的位置

clear() //清空整个列表,删除所有子控件

add(Fl_Widget ) //

把控件添加到列表尾

insert(Fl_Widget , int index) or insert(Fl_Widget ,

Fl_Widget before) // 把控件添加到某个位置或控件之后

remove(Fl_Widget ) or remove(int index) // 删除某个控件

//注意添加操作会把控件从当前的父控件的列表删除,添加到另一个父控件的列表

// 删除操作并不会在内存删除控件,只是从列表中移除

相应的Fl_Widget有个方法叫parent()可以找到其父容器。因此,如果在一开始没有使用begin和end正确添加子控件,使用这些方法也可以比较方便地添加、删除、管理子控件。

3. 重头戏:resizable(Fl_Widget )

这是Fl_Group的一个方法,在上一节课中我们也看到了,把参数设为容器自己使得自己可以改变大小,而且所有的子控件会在改变大小的时候随之缩放。但是更常用的是把某一个子控件设为resizable,这样不仅容器可以改变大小,也会使得相应的子控件有较好的行为。下面这个图摘自Fltk 1.3 Manual,显示了resizable的行为:

大家可以看到,在resizable的横向范围和纵向范围内的控件都改变了大小和位置,而在四个角位置的控件没有改变大小。在横向范围内的控件只改变高度,在纵向范围内的控件只改变宽度。这样,只要使用Fl_Group和不可见的Fl_Box,就可以完成各种复杂的缩放行为。例如下面的对话框:

记住Fltk的文本输入框前面的文字标签是和输入框绑定在一起的,不用另外使用标签控件。而输入框的左上角坐标却不包含标签,也就是说左上角是输入框的左上角,而不是加上标签后的左上角。这在指定坐标的时候要注意。

上面的程序,“姓名”一行包含在一个Group中,这个Group的输入框是它的resizable,从而“检查”按钮在输入框的横向范围内,只能改变高度,但是整个Group在Multiline_Input的纵向范围内,所以只能改变宽度,于是Group内的Input可以改变宽度,而“检查”按钮大小就不能变化了。“邮件”行的实现同上。最下面的“好的”按钮,实现和上面“姓名”和“邮件”一样,只不过把Input换成了一个不可见的Fl_Box。整个源程序如下(layout.cc):

#include "FL/Fl.H"

#include "FL/Fl_Double_Window.H"

#include "FL/Fl_Group.H"

#include "FL/Fl_Button.H"

#include "FL/Fl_Input.H"

#include "FL/Fl_Multiline_Input.H"

#include "FL/Fl_Box.H"

int main(int argc, char **argv)

{

Fl_Double_Window w = new Fl_Double_Window(100, 200, 460, 320, "Fltk布局");

//size_range只可以用在顶层窗口,设置窗口resize的范围。它有7个参数,但只有前4个

//是在各个系统下都有效的。前两个是最小宽度和最小高度。后两个是最大宽度和

//最大高度。后两个设置成零,说明无限制。如果设置成和前面最小值一样,则不可变动

//大小。例如

//w->size_range(w->w(), w->h(), 0, w->h());

//设置窗口高度不变,宽度可变。

w->size_range(w->w(), w->h(), 0, 0);

Fl_Group group1 = new Fl_Group(10, 10, w->w()-20, 30);

Fl_Input input1 = new Fl_Input(50, 10, w->w()-175, 30, "姓名:");

Fl_Button b1 = new Fl_Button(w->w()-110, 10, 100, 30, "检查!");

group1->end();

group1->resizable(input1);

Fl_Group group2 = new Fl_Group(10, 50, w->w()-20, 30);

Fl_Input input2 = new Fl_Input(50, 50, w->w()-175, 30, "邮件:");

Fl_Button b2 = new Fl_Button(w->w()-110, 50, 100, 30, "检查!");

group2->end();

group2->resizable(input2);

Fl_Multiline_Input comments = new Fl_Multiline_Input(50, 100, w->w()-60, w->h()-150, "评论:");

Fl_Group group3 = new Fl_Group(10, w->h()-10-30, w->w()-20, 30);

Fl_Box b = new Fl_Box(10, w->h()-10-30, group3->w() - 100, 30); //Fl_Box是默认不可见的

Fl_Button b3 = new Fl_Button(w->w()-10-100, w->h()-10-30, 100, 30, "好的");

group3->end();

group3->resizable(b);

w->end();

w->resizable(comments);

w->show();

return Fl::run();

}//代码效果参考:http://www.ezhiqi.com/zx/art_7466.html

这个程序的大部分都是上节课讲过的,创建Widget的方式就是手工指定位置和大小,注意所有Widget的位置都相对于整个顶层Window,而不是他们的父Group,这和大多数界面库有所不同,这种指定和坐标非常不便(见我原来的日志:Fltk的奇怪之处)。但是这些是轻量级的代价,如果我们真要实际开发,设计界面还是用Fluid方便,设计好初始的大小和位置(以及父子关系),然后加入resizable的相关代码,这样就能比较方便地创建一个布局。

4. 使用Fl_Pack

Fl_Pack是Fl_Group的子类型,实现了额外的一些布局功能。Fl_Pack能自动把它的子控件按横向或纵向排列(通过方法type(Fl_Pack::HORIZONTAL或Fl_Pack::VERTICAL)来指定),这样子控件就不用再考虑位置(随便指定位置就行),但是还要指定正确的大小。这就是Fl_Pack和Fl_Group的不同之处。例如上述程序中使用Group的代码,可以用以下代码替换

Fl_Pack

pack1

=

new Fl_Pack(50, 10,

w->w()-20, 30);

pack1->type(Fl_Pack::HORIZONTAL);

pack1->spacing(10);

Fl_Input

input1

=

new Fl_Input(0,0,w->w()-175, 30,<span style="color: rgba(168, 197, 255, 1)" color="#a8

相关文章
|
JavaScript 前端开发
使用typora生成时序图
掌握生产力工具,使用typora和mermaid生成时序图
746 0
(续集)记录2分钟破解知识星球验证弹窗
那我换个思路,反正网站简单,这次直接用替换的方式
1833 0
|
搜索推荐 算法 数据挖掘
十个最全网站营销方法案例分析
本文探讨了10种网站营销策略:SEO优化提升搜索引擎排名;内容营销建立品牌信任;社交媒体营销扩大影响力;搜索引擎广告吸引目标用户;电子邮件营销促进销售;网站设计优化提升用户体验;移动端优化适应移动设备;数据分析驱动策略优化;视频营销吸引关注;合作伙伴营销扩展品牌覆盖。AokSend提供高效验证码发信服务,助力企业营销。选择合适策略,持续优化,以实现最佳营销效果。
|
Linux 开发工具 C++
技术笔记:NanoGUI使用
技术笔记:NanoGUI使用
237 0
|
存储 Java 索引
如何在 Java 中打印数组
【8月更文挑战第22天】
269 0
|
容器
一篇文章讲明白Fltk1.3系列教程(3)
一篇文章讲明白Fltk1.3系列教程(3)
183 1
|
物联网 Linux C#
一键掌控未来!用 Uno Platform 打造跨平台 IoT 应用,轻松连接你的智能设备,让生活更智能!
微软的开源跨平台框架 Uno Platform 支持使用 C# 和 XAML 一次性编写代码并部署至多个平台,如 Windows、macOS、Linux、WebAssembly 及 iOS/Android,这使其成为 IoT 设备开发的理想选择。本文通过创建控制网络 LED 灯的应用,详细介绍了 Uno Platform 的环境搭建及 MQTT 客户端配置过程,实现了 LED 状态订阅与控制指令发送功能。该案例展示了 Uno Platform 在 IoT 领域的潜力及其跨平台优势,未来可扩展至更多设备类型,构建智能家居系统。
603 58
|
Java Maven
maven子模块无法继承父模块的jar包解决方案
maven子模块无法继承父模块的jar包解决方案
387 126
|
SQL 数据库 Python
SqlAlchemy 2.0 中文文档(十一)(3)
SqlAlchemy 2.0 中文文档(十一)
163 11
|
11月前
|
缓存 JavaScript API
Flutter&鸿蒙next 状态管理框架对比分析
在 Flutter 开发中,状态管理至关重要,直接影响应用的性能和可维护性。本文对比分析了常见的状态管理框架,包括 setState()、InheritedWidget、Provider、Riverpod、Bloc 和 GetX,详细介绍了它们的优缺点及适用场景,并提供了 Provider 的示例代码。选择合适的状态管理框架需考虑应用复杂度、团队熟悉程度和性能要求。
476 0