IMGUI的设计

(按:
web领域,GUI编程有着学习曲线,
琐碎,平凡的GUI,为什么需要复杂的学习呢,
我希望可以设计实现一个简单,能立即上手的GUI框架)

我曾经在预研工作中实现过一版IMGUI,作为用户扩展的GUI,
模拟器 API文档

IMGUI明显的好处是,用户不需要熟悉GUI的概念,比如html / xml / css或其它的 GUI 领域特定语言(DSL),只需要有一般脚本编程技能就可以了,

const button = Button.create({text: 'click me'});
if (button.click) {
    console.log(’i am clicked, dont stop‘)
}

一目了然,是吧

IMGUI的问题

问题来了,那为什么大多数GUI框架,未选择IMGUI?

首先,这问题不成立,在早期C编程时代,大家写的GUI都是IMGUI,因为那时,大家写UI本来就是即时绘制

// 每祯循环,所以叫做“即时”模式
void onUpdate() {
  // 绘制 button
  drawButton("click me", "thisButtonID");
  Event clickEvent;
  // 过滤是否有点击消息
  filterEvent(&clickEvent);
  if(clickEvent.valid) {
    // 是否点击在button区域中 
    if( getRec("thisButtonID").include(clickEvent.point) ) {
        printf("i am clicked")
    }
  }
}

然后,这问题很有价值,

GUI思想一直在发展,从早期绘制,到GUI编程成为一个相对独立的编程,出现了面向对象编程,将
GUI关注于 对象事件,Button作为控件对象

const btClickMe = new Button(...)  
btClickMe.on('click', ()=>{
   console.log('i am clicked')
})

更近一步地,因为GUI相当关心排版问题,即需要组织一颗GUI树,出现了GUI排版描述语言, 即一般的XML/HTML/JSON表示

const GUIDesc = {
    type: "layout", // 是排版容器节点
    direction: "vertical", // 竖直排版
    align : {
        longtitude: "begin", // 径度对齐,begin即向上对齐
        latitude: "begin", // 纬度对齐,begin即向左对齐
    },
     
    children : [
        {
            type: 'button', // 一个button组件
            text: 'click me',
            onClick: ()=>{ // 点击回调
                console.log('i am clicked');
            },
            children: [...]
        }
    ]
}
 
const gui = createGUI(GUIDesc);

这看起来有点像HTML了,是不?
这种方式对于良好组织复杂GUI有好处,但对于制作,比如说一个面板,简单的工具界面,反而显得复杂。

另外,
IMGUI一般被人认为影响效率, 它的实现经常每次事件都会有两次执行,一遍逻辑,再一遍layout输出,但也许有巧妙的设计可以避免效率上的开销;
IMGUI 混合逻辑和渲染,—— 有时是缺点,它影响大型GUI的整体设计,但在用户扩展里,经常是优点,而且,运用组件化实践,它可以做到通用化的GUI编程;

IMGUI的需求

需求来自两方面,

GUI编程的学习成本开始变高(你需要学习一个描述型语言,学习框架用法才能产生一个简单GUI),不能满足立即上手的需求(很多人不需要成为专家),这块先不表,

另一方面,现代的GUI越来越有动态性,传统上,XML/HTML擅长表达静态页面,如果兼容做动态页面,则需要和代码结合的一种表示方法,比如说 react 的 jsx文件,vue的 嵌入表达式。

如果有这样一个需求,如果上有一个按钮(打开/收起),下面是一张图,随着按钮点击,图会展开和收起,
IMGUI是这样做的

const button = Button.create({text: 'click me'});
if(button.click){
    isPicShown = !isPicShown; // toggle state       
}
let pic = null;
if(isPicShown) {
      pic = Image.create('xxx.jpg')
}

可以看到, 做高交互性的GUI,是 排版和逻辑的混合,很适合直接用代码表达,这里IMGUI是相当有价值的

IMGUI的改进

之前说过,GUI的思想在发展,而我想的是,大大加强IMGUI,让之能适应大多数情况的GUI设计,

关键的几个设计点,

  1. 每个GUI对象有构造,内部状态,外部属性
  2. 在渲染更新函数里,渲染,事件,生命周期都写在一起
GUIDefine("Button") {
  arguments:{ // 这里构造属性,比如 Button.create(...arguments) 这里的表示
      ...
  },
  states: { // 这里是内部持久状态
      ...
  },
  export: { // 这里是外部属性, 比如说 button.isClick == true
      ...
  }
  onUpdate: (event) => {
      if(event.afterAttach) { // 生命周期事件
           
      } else if (event.beforeDetach) {

      }
      rect = Rect.create(...)
      clickEvt = event.system.click
      if(rect.include(clickEvt.position) ) { // 比如这里处理系统点击事件,但真实并不会这样做,请思考为什么?
          triggerEvent(this.isClick, true) // 这样就可以if(button.isClick) 了
      }
  }
}
  1. 用样式模板+属性覆盖,做为theme方案
// theme 是UI模板
GUI.setTheme('defaultTheme');
// ...
Button.create({Theme="xxx", text:"click me", color:0x000}); // color 已经包含在

  1. 如何定义UI模板(theme)
// 对所有组件,给予一个默认的属性
UITemplate("defaultTheme") {
Button = {
 color:0xbbb;
 ...
};
panel = {
 background:...,
}
}


// 第二种方式可以在组件里,加入几种theme的本组件属性
GUIDefine("Button") {
// ...
ThemeOf("defaultTheme", {
  color:"xxx";
},
ThemeOf("deepinTheme", {
  color:"xxx";
}
}

// 第一种适合实现在UI库,整体的theme定义
// 第二种特别适合用在 用户自定义组件里
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345