`
rubynroll
  • 浏览: 205796 次
  • 性别: Icon_minigender_1
  • 来自: Wgt
社区版块
存档分类
最新评论

300行代码你能做什么

阅读更多

我也标题党一回:300行代码你能做什么?本文介绍一个具有builder风格的RubyGnome2布局器(GtkSimpleLayout)不到300行代码,还包括几个实用的除布局之外的增强功能。

 

前言

随着RubyGnome2库越来越完善,以及ruby1.9的性能提升,用Ruby编写GUI程序渐渐从我的业余爱好转为我工作的一个重要部分。

 

用Ruby写程序确实很有乐趣,它可以让你的想法快速地以一种优雅的方式实现。本文介绍的一个gem就是一个例子,用很少的代码,实现很有趣的功能,让编写Ruby GUI程序变得轻松愉快。

 

RubyGnome2介绍

 

虽然我以前也曾经多次地介绍过RubyGnome2,但我还是想再一次地推荐RubyGnome2,它实在是使用Ruby编写GUI程序的首选。

 

RubyGnome2是GTK+库的一个ruby扩展。它对GTK+的对象模型仔细地用Ruby的方式进行封装,保留了GTK+ API命名方式和含义,因此GTK+的文档对于RubyGnome2也是适用的---尽管我认为RubyGnome2的文档已经做得非常不错了,需要回去借鉴GTK文档的地方实在不多。

 

虽然GTK本身是由C编写的,但它有一套完整的精心设计对象体系,使得它的GUI元件可以非常灵活的自由组合,以实现复杂的,功能强大的界面。

 

由于GTK非常重视它的对象体系的灵活性,因此刚开始使用GTK编程并不容易。很多时候表面上看起来很简单的一个功能,在GTK里面却要绕几个弯才能实现。例如要设置一个label的字体,要通过Pango来实现,Pango接管了GTK的所有字体渲染事务....这种“多绕几个弯”的情况很多,它确实使得编写GTK程序不那么直接了当。但换来的是整个GTK系统变得非常灵活,以较少的代价实现强大的功能,在跨平台,换肤,国际化上面都有很好的表现。

 

RubyGnome2继承了GTK的所有特点,包括优点和缺点。

 

GUI布局

GTK程序的布局很灵活,有许多种容器可选择。在布局的时候,大多数都是推荐相对位置而不是绝对位置,这样GUI程序可以更好的适应不同分辨率的屏幕,也有利于特定风格对UI的fine tune。

最常见的容器就是“盒子”,包括“水平盒子”和“垂直盒子”。将可视的UI元件放入“盒子”,不同的“盒子”互相组合叠放就可以构建出目标布局。

 

理论上用盒子就可以构建任何相对位置布局,但是为了方面,GTK还提供了像table这样的更高级的容器。

 

盒子模型对于许多刚开始GTK编程的人觉得很难适应,即使用了可视化布局工具例如Glade,初学者也往往被盒子模型困扰。可视化布局器最擅长的是固定位置布局。对于相对位置布局,很多时候用代码构建界面比用Glade反而来的快捷方便。

 

但是用代码构建界面有一个显著的缺点,那就是“不直观”,即很难从代码中看出UI布局,这样会给后期维护以及变更带来麻烦。

 

有一些GUI库如Shose,用builder风格的代码来描述UI,使得UI布局可以通过代码形象地体现出来,如以下这个例子来自shooose.net:

 

Shoes.app {
  stack(:margin => 4) {
    button "Mice"
    button "Eagles"
    button "Quail"
  }
}

 

这样,我们就可以从代码中一下子看出UI布局了。

 

builder风格的代码和HTML很类似,对于熟悉HTML的web界面设计者来说,可视化的编辑器并没有多大的必要。

 

 

RubyGnome2没有为我们提供builder方式的布局,因此UI代码写起来就像:

 

class MyWin < Gtk::Window
  def initialize
    super
    vbox = Gtk::VBox.new
    btn_mice = Gtk::Button.new 'Mice'
    vbox.pack_start btn_mice
    btn_eagles = Gtk::Button.new 'Eagles'
    vbox.pack_start btn_eagles
    btn_quail = Gtk::Button.new 'Quail'
    vbox.pack_start btn_quail
    add vbox
  end
end
  

从上面的代码中很难一下子看出UI布局。

 

如果也为RubyGnome2构建一个builder风格的布局器,那么代码就会变成:

 

class MyWin < Gtk::Window

  def initialize
    super
    add my_layout
  end

  def my_layout
    vbox do
      button 'Mice'
      button 'Eagles'
      button 'Quail'
    end
  end

end
 

 

嗯,这个代码就和Shose差不多了,可以从代码中一眼看出UI布局。

 

本文所介绍的GtkSimpleLayout其功能之一就是为RubyGnome2提供builder风格的布局器。

 

GtkSimpleLayout布局器

这个简单的布局器原先只有200行不到的代码,我经常是直接拷贝到项目中使用。后来逐渐添了些功能,觉得它变得更有用了,于是便发布到github生成gem,方便感兴趣者使用。

 

Source: git://github.com/rickyzheng/GtkSimpleLayout.git

or:

gem source -a http://gems.github.com && gem install rickyzheng-GtkSimpleLayout

 

以下是主要功能介绍以及简单例子。

 

提供Builder风格布局

正如上面的例子中所介绍的,GtkSimpleLayout为RubyGnome2带来了builder风格的布局功能,只需要为布局的类扩展GtkSimpleLayout::Base即可,一个完整的例子:

 

require 'gtk2'
require 'simple_layout'

class MyWin < Gtk::Window
  include SimpleLayout::Base
  def initialize
    super
    add my_layout
    signal_connect('destroy') do
      Gtk.main_quit
    end
  end

  def my_layout
    hbox do
        label 'Hello, '
        button 'World !'
      end
  end
end

MyWin.new.show_all
Gtk.main

 

 

从上面的例子中可以看出,GtkSimpleLayout并没有改变RubyGnome2程序的主框架,它只是一个扩充。

 

 

属性设置

在放置UI元件的时候,往往需要设置初始属性,或者要指定布局参数。GtkSimpleLayout用Hash来传递这些属性与参数,例如:

 

vbox do
  button 'sensitive = false', :sensitive => false  # 初始为disable状态
  button 'expand space', :layout => [true, true]  # 指定这个button填充剩余空间
end

 

 

上面这个例子中,第一个button的初始状态为disable。 ":sensitive => false"这个参数最终被转换成属性设置:Gtk::Button#sensitive=false,至于Gtk::Button有那些属性可以设置,请参阅RubyGnome2 API文档或GTK文档。GtkSimpleLayout在这里只是作一个简单参数的转换而已。

 

第二个button的":layout => [true, true]"有点特殊。":layout" 参数是GtkSimpleLayout的保留参数,它会被转换成当这个UI被放入容器时候的参数。这个例子中,容器是vbox(Gtk::VBox),默认的加入方法是Gtk::VBox#pack_start,这个例子中的[true, true] 最终会被传递到pack_start,因此这个button在被加入vbox的时候调用的方法以及参数是:"Gtk::VBox#pack_start( button, true, true)"。

 

因此,要使用GtkSimpleLayout,就首先要熟悉RubyGnome2的各个元件,容器的用法,以及参数。当你熟悉了RubyGnome2以后,用GtkSimpleLayout就会非常简单。

 

批量属性设置

在UI布局的时候,经常碰到要对一组UI元件设置相同的属性的情况,例如:

hbox do
    button 'C', :layout => [false, false, 5]
    button 'D', :layout => [false, false, 5]
    button 'E', :layout => [false, false, 5]
end


 这个时候,可以用"with_attr"来简化:

hbox  do
  with_attr :layout => [false, false, 5] do
    button 'C'
    button 'D'
    button 'E'
  end
end 

 

特殊容器

有些容器的放置子元件的时候有 特殊要求,例如Gtk::HPaned,左边子窗口要用Gtk::HPaned#add1()来添加,右边的用Gtk::HPaned#add2()。对于这种容器,GtkSimpleLayout要特别对待,就以hpaned为例:

hpaned do
  area_first do
    frame 'first area'
  end
  area_second do
    frame 'second area'
  end
end


  

需要特殊对待的容器有:

  • hpaned/vpaned : 用area_first和area_second来添加子窗口。
  • table : 用grid来填充格子。
  • nodebook : 用page来添加子页。

 

标识UI元件

GtkSimpleLayout用":id => ??"这个参数为UI元件进行标识,例如:

hbox do
  button 'first', :id => :btn_first
  button 'second', :id => :btn_second
end
 

之后,可以用component()函数取得这个UI元件:

my_first_button = component(:btn_first)
my_second_button = component(:btn_second)

...
my_first_button.signal_connect('clicked') do
  puts "first button clicked"
end

my_second_button.signal_connect('clicked') do
  puts "second button clicked"
end

 

如果嫌麻烦,GtkSimpleLayout还提供了expose_components()用于自动将所有已标识的元件添加为实例读属性(getter):

expose_components() # 将自动添加btn_first和btn_second这两个读属性(getter)。
...
btn_first.signal_connect('clicked') do
  puts "first button clicked"
end

btn_second.signal_connect('clicked') do
  puts "second button clicked"
end

 

 

自动事件响应映射

如果你嫌显式调用signal_connect来注册事件麻烦,那么GtkSimpleLayout为你提供了自动事件响应映射的功能:

require 'gtk2'
require 'simple_layout'

class MyWin < Gtk::Window
  include SimpleLayout::Base
  def initialize
    super
    add my_layout
    register_auto_events()  # 注册自动事件响应映射
  end

  def my_layout
    hbox do
      button "First', :btn_first
      button "Second", :btn_second
    end
  end

  # 事件响应函数
  def btn_first_on_clicked(*_)
    puts "First button clicked"
  end

  # 事件响应函数
  def btn_second_on_clicked(*_)
    puts "Second button clicked"
  end

  # 退出事件响应函数
  def self_on_destroy(*_)
    Gtk.main_quit
  end
end

 

最后那个'self‘是指宿主容器。

 

UI分组

有时候你希望对UI元件进行分组,这样就可以对同一组的UI元件进行控制,如使能或禁止整个组。GtkSimpleLayout允许你在布局的时候指定UI组。

GtkSimpleLayout的UI分组规则如下:

  • 默认情况下,已命名的容器(即传入了:id参数)自动对自己所属的子元件建立一个组,组名就是容器明。
  • 如果容器传入:gid=>??参数,则以此名称为所属子元件建立组。
  • 允许多个容器的:gid名字相同,这种情况下所属子元件将归为同一个组。
  • 可以用“group”来显式对UI分组,group可以看作是一个虚拟的容器。

用component_children(group_name)来获取UI组。

 

由于UI分组的例子比较长不在此列出,请参阅源码中的examples/group.rb文件

 

 

UI与逻辑代码分离

由于GtkSimpleLayout潜在地迫使使用者分离界面代码和逻辑处理(或事件响应)代码,使得整个程序的层次结构更加清晰。对于界面元件比较多的程序,可以很方便的分区进行layout,因为layout的结果还是容器,这个容器又可以放入其他容器组合成更复杂的界面。

 

由于GtkSimpleLayout并不改变RubyGnome2的程序结构,你可以选择在你的程序中部分或全部使用GtkSimpleLayout。虽然本文所提供的例子都是静态布局,但由于GtkSimpleLayout是存代码构建UI,因此你完全可以在布局的时候传入变量,进行动态布局和动态生成UI,而仍然保持UI代码的“可视化”。

 

 

有兴趣者可以看看GtkSimpleLayout实现的代码,不过300行而已,这就是Ruby的魅力。

 

最后,贴上一个计算器的界面部分的代码例子,你能从代码中看出UI布局么?

require 'gtk2'
require 'simple_layout'

class MyWin < Gtk::Window
  include SimpleLayout::Base
  def initialize
    super
    add my_layout
    signal_connect('destroy') do
      Gtk.main_quit
    end
  end

  def my_layout
    vbox do
      with_attr :border_width => 3 do
        hbox do
          entry :id => :ent_input, :layout => [true, true, 5]
        end
        hbox do
          frame do
            label 'M', :set_size_request => [20, 20]
          end
          hbutton_box do
            button 'Backspace'
            button 'CE'
            button 'C'
          end
        end
        hbox do
          vbutton_box do
            button 'MC'
            button 'MR'
            button 'MS'
            button 'M+'
          end
          with_attr :layout => [true, true] do
            number_and_operators_layout
          end
        end
      end
    end
  end

  def number_and_operators_layout
    vbox do
      [ ['7', '8', '9', '/', 'sqt'],
        ['4', '5', '6', '*', '%'],
        ['1', '2', '3', '-', '1/x'],
        ['0', '+/=', '.', '+', '=']].each do |cols|
        hbox :layout => [true, true] do
          cols.each do |txt|
            button txt, :set_size_request => [20, 20], :layout => [true, true]
          end
        end
      end
    end
  end

end

MyWin.new.show_all
Gtk.main

 

 

 

Enjoy it :-)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 大小: 5.1 KB
  • 大小: 7.5 KB
  • 大小: 4.6 KB
  • 大小: 6 KB
  • 大小: 13.6 KB
分享到:
评论
30 楼 rubynroll 2009-09-07  
subwayline13 写道
UI设计和开发分离是多少人的梦想,虽然还没有实现,你完全本末倒置了。

虽然"UI设计和开发分离"是好事,但是“本”的高度也未免太高了吧

subwayline13 写道

首先是要需要“可视化”,因为早期技术不是很成熟,在妥协的情况下才在外联UI设计的资源文件,不然还费些事干嘛?从VB/VC Delphi Winform WPF随着技术进步才慢慢发展到XAML这样的技术,所以并不是可视化依赖程度下降,而是更好用的“可视化”,

可视化依赖程度和更好用的“可视化”不排斥,我认为XAML是两方面同时提高,而不是此消彼长。

subwayline13 写道
WPF/Silverlight设计人员可以在Blend设计,程序员在VS上开发(虽然我觉得目前这个版本还不太你好用)。而且我不认为“问题是逆向(即:从可读性很好的代码转化为可视化编辑界面)比较困难。”这是个问题,起码VS应该不是简单的逆行解析,而是执行,因为不太可能解析到数据库里去吧,如果这样的话,RubyGnome2出可视化工具也不是大问题了,起码MS的技术能做到。
...

是运行,从VB开始就是运行而不是解析。但这里要提供一个“容器”环境让它运行,而且要考虑“设计时”的一些特殊性,我所说的困难在这里。XAML由于是把UI部分分开了,所以技术上反而更容易实现。

RubyGnome2还未成熟到可以让微软为之开发可视化工具的地步:)

subwayline13 写道

你指望设计人员写DSL吗?XML不算一种DSL?RUBY才是DSL?VS上IronPython也是可以做WinForm和WPF的,IronPython有没有DSL能力?

XML不是DSL,ruby也不是DSL。为了特定领域(表达UI)而提供一系列方法以后才是DSL。从这个意义上来说,XAML是外部DSL。我上面说的DSL是指内部DSL。

subwayline13 写道

你现在也无法看到你的问题,首先因为你相当热爱RUBY,所以连目前RubyGnome2的不足也认为优点,

不对,我是首先是看到了RubyGnome2的不足才着手GtkSimpleLayout。RubyGnome2还有很多不足,相信我看到的比你多。我只是认为“可视化”UI设计对RubyGnome2不重要。

subwayline13 写道
目前还没有优秀可视化开发工具,以后加上就好了,我相信优秀开发设计工具更能提高效率,工作也更有乐趣。

好的开发工具可以提供效率也更有乐趣这个我赞成,NetBeans就不错。

subwayline13 写道
起码我看你的回帖,就会发现,别人提出目前不足,你的反驳都相当蹩脚,比如不能DIFF,不能动态“可视化”之类。


不是不能diff,是diff的结果是否能很好地反映UI的变化的问题。我承认XAML在这个问题上可以满足基本要求。

你举的所有“动态”的例子,均是后台代码的功劳,“可视化”的UI编辑器只是起到一个展现结果的功能吧,“可视化”到底在什么地方帮助你“动态”了?。你的代码把生成界面的工作了都做了,再把它放到可视化的toolbox上面然后拖到你的UI设计器上有何必要?把你的代码封装成函数或类,在需要的地方调用还不是一样的么?



29 楼 lichuan 2009-09-07  
一个大型团队,一个拥有重型界面的软件,都会要求一种分离界面和逻辑的开发方式,把图形设计师和程序员放在一张桌子前是不现实的。

图形设计师应该和产品设计师进行沟通,让程序员浪费时间找出应该把按钮放在什么位置是愚蠢的。

28 楼 ray_linn 2009-09-07  
rubynroll 写道

menu_bar do
  menu 'File', :item => ['Open', 'Close', '_', 'Quit']
  menu 'View', :item => ['Copy', 'Edit']
  menu :item => ['About'], :layout => :last
end



这样的菜单是简单又简单的,一个真正意义上的菜单,有快捷键,有图片,有子菜单,有enable/disable的属性,你在代码里敲敲看吧,看不出有什么必要开历史的倒车。

通过XML生成.NET form的界面,早在XAML之前,就有人发明了,首先这种生成需求到底有多少,其次扯上生成界面和DSL完全没必要,这主要原因是ruby是动态语言而已,.NET如果真要生成,也可以通过CodeDOM一行行, 也可以通过一个Form的模板生成后编译,甚至可以采用别人的经验,从XML把整个过程自动化。
27 楼 quix 2009-09-07  
rubynroll 写道

最后,我也没说RUBY开发GUI不好,那么我偏见的观点是,现在还没有可视化开发工具,开发效率不够高。你偏见的观点是可视化本来就没啥用。我没有说RUBY不好,要有可视化工具就更好了,并且WPF的例子证明完全是可以实现的,你的观点是因为RUBY已经很好了,所以不需要可视化工具,土鳖不土鳖你自己琢磨吧。


赞成~ 可以的话人人都想偷懒用自动生成的代码 ~ 不是不想要可视化设计,而是现在的可视化工具没有或者不够好~不能让我们达到预期目的,仅此而已

仅仅以部分技术的情况,来评判整个可视化开发方式的好坏有点太过笼统了~

咱应该具体问题具体分析啦~
26 楼 rubynroll 2009-09-07  
subwayline13 写道
我所说经验带来的偏见是双方面的,我的目前编码经验实在不能从builder-style直接想想到UI到底是什么样子,我不会觉得自己敲代码比可视化工具更有效率,因为我不是RUBY开发者,我是存在偏见的。

除了god以外,没有人什么都懂,注意用词就是了,一个良好的讨论氛围尊重是基础。

subwayline13 写道
另外,是buider-style可读性好还是XAML可读性好完全是主观看法,

注意我的原文,我说的是“不过WPF XAML的可读性如何,以及是否优于代码(特别是动态语言)值得探讨“,我不是拿XAML和builder-style比较,他们没有可比性。builder-style只是一种表达方法而已,它的作用是体现层次。XAML基于XML,已经体现了层次。关于XML和代码相比,其优劣点相信已经有很多讨论了。

subwayline13 写道

就像法国人说法语是世界上最美语言一样土鳖,但是朱德跟着说法语是世界上最优美语言就是更土鳖的了,所以你说的“关于“可视化”不能动态生成界面的观点”不是很土鳖吗?虽然你在我的例子面前你马上承认错误。

清再仔细阅读我所说的,注意我的用词。
VS/WFP是让生成的界面在设计时“可视”了,但是生成界面的是后面代码所作的工作。所以我说“不完全正确”。

其实关于这个问题真的无须再讨论了。


subwayline13 写道
这个地方MS开发人员很少,充满了偏见,我的那个例子非常简单,会点WPF人基本都做得出来,我水平很一般,我也不是开发WPF的,你所谓的亲自尝试一下你做到了吗?另外,VS既然能生成XAML,当然也能生成buider-style的代码,所以我说这完全是空谈,只是一个风格问题,只是流行和更流行问题。

1. 这里的人在工作中只使用MS工具开发的人可能真的不多,熟悉MS开发的人员却是不少,因此说”充满了偏见“是不公平的。

2. 我的确“亲自尝试”了,举手之劳而已,为什么不做?同样我也强烈建议你尝试一下RubyGnome2,花不了多长时间。

3. 只要MS认为有必要,我认为VS生成可读性很好的UI代码完全可以。问题是逆向(即:从可读性很好的代码转化为可视化编辑界面)比较困难。XAML应该是在“可读性”和“逆向方便性”之间取得了一个很好的平衡。
从早期的VB完全隐藏UI部分的代码,到.net winform允许你修改UI代码(不过要小心),到现在WPF用单独用XAML作为UI描述分离出来,MS在保持可视化的同时也在不断使对可视化的依赖程度下降。

由于目前VS支持的主流语言尚不能用来构建合适的DSL来描述UI,因此XAML是好选择。如果MS有更好的语言可以构建合适的DSL来描述UI,它替代XAML,大大弱化可视化也不是不可能的。

subwayline13 写道
最后,我也没说RUBY开发GUI不好,那么我偏见的观点是,现在还没有可视化开发工具,开发效率不够高。你偏见的观点是可视化本来就没啥用。我没有说RUBY不好,要有可视化工具就更好了,并且WPF的例子证明完全是可以实现的,你的观点是因为RUBY已经很好了,所以不需要可视化工具,土鳖不土鳖你自己琢磨吧。


你完全没有理解我的观点,连重复我的观点都不会,只会用攻击性的语言,这样的讨论没有意义了。

管理员请锁了这贴吧。


25 楼 rainchen 2009-09-06  
我喜欢这小工具,既然我拿了红宝石做锤子,自然想希望能敲多些钉子
24 楼 rubynroll 2009-09-06  
subwayline13 写道
rubynroll 写道

你举的WPF的例子(1)既不能说明“可视化”如何优于代码生成界面,(2)也没有反驳代码可以动态生成界面而“可视化”不能(实际上你的例子反而是支持了代码生成界面的做法,只不过C#没有builder-style方式而已)。(3)WPF使用XAML表述UI,由于XAML体现UI层次而且是文本,因此在UI变化后是可以在diff上看出来,这是一个进步。不过WPF XAML的可读性如何,以及是否优于代码(特别是动态语言)值得探讨。

本文起由于RubyGnome2的代码体现不出UI的实际样子,因此有了GtkSimpleLayout,可以让代码和UI高度一致,从而使大部分情况下不用Glade。由此再延伸到关于代码生成界面和“可视化”编辑界面的讨论...RubyGnome2的案例并不一定是适用于其他情况,但应该有参考价值。我的观点只是抛砖引玉,大家接着来。


这种讨论是空谈,解决不了任何问题,没有实际意义,经验会带来偏见,最终程序员会用脚投票的。


我不是期望这个几百行代码的东西能够替代VS或者和微软WPF叫板,但是作为程序员不要把眼光仅仅限于人家为你设定好的路线上,应该勇于尝试勇于思考。

如果你是程序员,请继续用代码说话,或者你至少要对这里所讨论的东西亲自尝试一下。

讨论问题的一个基本前提就是尊重别人的观点,有不同意见就有理有据的反驳,而不是马上论起大棒子。如果你没有讨论问题的心态的话,对你而言确实是空谈。


23 楼 rubynroll 2009-09-05  
超过300行,内容已删除,另起一贴。











22 楼 rubynroll 2009-09-04  
我的关于“可视化”不能动态生成界面的观点在VS/WPF面前不完全正确,subwayline13提供的例子中,WPF的定制控件确实是在代码的支持下“可视化”地生成了界面!这的确是个好主意,well done MS !
21 楼 rubynroll 2009-09-04  
subwayline13 写道


田忌赛马的范例,为啥不和WPF对比?

不知道你所说的可视化的生成界面是不是这个意思?

1新建一个用户控件

....

简单的例子,如果你自己写的控件够强大,可视化生成界面也没啥问题。


WPF果然很好很强大,不过这些好像和我始终表述的观点没有什么关系啊,你要是从头开始看这个贴你就可以看到我的观点是:

1. 一个合适的布局器使代码编写界面很直观,不乏味,大大弱化“可视化”在编写UI程序的重要性,很多时候“可视化”根本不需要。
例如我反驳
ray_linn 写道
基本上没什么用,UI还是需要可视化的,而且UI原件远比这个复杂多了


我反驳
jinleileiking 写道
为什么要写?还是喜欢拖。。。。。


我反驳
ray_linn 写道

比如普通一点的界面,至少有个menu bar有menu item,有menu event,用代码写起来是很乏味的。



2. 代码可以动态生成界面,而“可视化”缺少这样的灵活性。
3. 代码生成界面可以用普通的代码版本管理工具就可以跟踪变化记录,并且具有良好的可读性。

你举的WPF的例子(1)既不能说明“可视化”如何优于代码生成界面,(2)也没有反驳代码可以动态生成界面而“可视化”不能(实际上你的例子反而是支持了代码生成界面的做法,只不过C#没有builder-style方式而已)。(3)WPF使用XAML表述UI,由于XAML体现UI层次而且是文本,因此在UI变化后是可以在diff上看出来,这是一个进步。不过WPF XAML的可读性如何,以及是否优于代码(特别是动态语言)值得探讨。

本文起由于RubyGnome2的代码体现不出UI的实际样子,因此有了GtkSimpleLayout,可以让代码和UI高度一致,从而使大部分情况下不用Glade。由此再延伸到关于代码生成界面和“可视化”编辑界面的讨论...RubyGnome2的案例并不一定是适用于其他情况,但应该有参考价值。我的观点只是抛砖引玉,大家接着来。






20 楼 rubynroll 2009-09-04  
ray_linn 写道
编写界面一个很重要的就是component复用,把事件。属性封在component的边界里。同时要兼顾美观、通用。
比如普通一点的界面,至少有个menu bar有menu item,有menu event,用代码写起来是很乏味的。

这一点说得有道理,但这正是代码生成界面的潜力所在。一个精心设计的框架可以使它变得不乏味。
例如:
menu_bar do
  menu 'File', :item => ['Open', 'Close', '_', 'Quit']
  menu 'View', :item => ['Copy', 'Edit']
  menu :item => ['About'], :layout => :last
end


我不认为上面的代码会比可视化编辑菜单更乏味。

(注:GtkSimpleLayout目前还不支持以上代码,它还是v0.1.x呢)


ray_linn 写道

其实是就是象.NET FORM,动态生成界面也是很简单的,以上说的什么用代码编写可以存数据库是毫无关联的。


我说的可以从数据库中生成界面不是针对.NET FORM或任何一种语言,而是针对“可视化”。如果可以“可视化”地动态生成界面,那么用代码生成界面就没有这个优势了。



19 楼 rubynroll 2009-09-04  
subwayline13 写道


另外你这两点好处基本上不成立,或者说现在的开发工具已经完全实现了,你装个VS20008就知道了。


用MFC的话,rc文件可读性不算好,你能从rc文件中看出UI? 而即使是.NET, VS生成的代码由于没有象builder-style那样体现UI的层次,因此当你从SCM结果中观察diff时也不能很好地看出真正变化了什么。

至于动态界面,VS2008可视化似乎帮不上什么忙。

18 楼 ray_linn 2009-09-04  
编写界面一个很重要的就是component复用,把事件。属性封在component的边界里。同时要兼顾美观、通用。
比如普通一点的界面,至少有个menu bar有menu item,有menu event,用代码写起来是很乏味的。


其实是就是象.NET FORM,动态生成界面也是很简单的,以上说的什么用代码编写可以存数据库是毫无关联的。
17 楼 poshboytl 2009-09-04  
好文,收藏了.....
我写桌面的机会不多, 偶尔玩玩更喜欢Shoes
16 楼 RednaxelaFX 2009-09-04  
rubynroll 写道
代码生成界面有两个好处:
1. 动态界面,例如你可以从数据库中生成界面,根据不同数据类型提供不同的界面等。
2. 用普通的代码版本管理工具就可以跟踪变化记录,并且具有良好的可读性。

另外,和HTML类似,为什么要用文本编辑器写HTML?(可视化工具多了是...)

嗯支持一下~我也是比较喜欢用代码写界面。
以前写页面的时候用过一段时间AceHTML Pro,感觉还不错。虽说是“敲代码”但能够被自动补全的地方也很多
现在用WPF我也还是经常手写XAML……顺手些而且容易控制版本一些 =v=
15 楼 night_stalker 2009-09-04  
建议 ls 用 dreamweaver 敲标签 ……
不关门不是什么大事,用 tidy 刷一遍就全关上了,有些不关上的浏览器也能认,节约带宽,保护环境 ……

ps:现在的 XUL 可读性太差了。
14 楼 rubynroll 2009-09-03  
jinleileiking 写道
为什么要写?还是喜欢拖。。。。。



代码生成界面有两个好处:
1. 动态界面,例如你可以从数据库中生成界面,根据不同数据类型提供不同的界面等。
2. 用普通的代码版本管理工具就可以跟踪变化记录,并且具有良好的可读性。

另外,和HTML类似,为什么要用文本编辑器写HTML?(可视化工具多了是...)
13 楼 jinleileiking 2009-09-03  
为什么要写?还是喜欢拖。。。。。

12 楼 少女杀手 2009-09-03  
不错不错,现在是没有时间学这个!看以后吧
11 楼 rubynroll 2009-09-03  
依样画葫芦:
require 'gtk2'
require 'simple_layout'

class MyWin < Gtk::Window
  include SimpleLayout::Base
  def initialize
    super('添加新客户')
    add my_layout
    signal_connect('destroy') do
      Gtk.main_quit
    end
  end

  def my_layout
    frame ' 请填写 ', :border_width => 5 do
      vbox do
        with_attr :border_width => 5 do
          vbox do
            hbox{ label '客户种类:'}
            combobox
          end
          hbox do
            with_attr :set_size_request => [200, -1], :border_width => 5 do
              vbox do
                hbox{ label '合作标记:' }
                combobox
              end
              vbox do
                hbox{ label '客户类别:' }
                combobox
              end
              vbox do
                hbox{ label '客户级别:' }
                combobox
              end
            end
          end
          vbox do
            hbox{ label '公司名称:' }
            entry :layout => [true, true]
          end
          vbox do
            hbox{ label '集团名称:' }
            entry :layout => [true, true]
          end
          hbox do
            with_attr :set_size_request => [200, -1], :border_width => 5 do
              vbox do
                hbox{ label '公司电话:' }
                entry :layout => [true, true]
              end
              vbox do
                hbox{ label '传真号码:' }
                entry :layout => [true, true]
              end
              vbox do
                hbox{ label '公司邮编:' }
                entry :layout => [true, true]
              end
            end
          end
          vbox do
            hbox{ label '公司邮编:'}
            entry :layout => [true, true]
          end
          vbox do
            hbox{ label '公司网站:' }
            entry :layout => [true, true]
          end
          vbox do
            hbox{ label '概况'}
            frame :border_width => 3 do
              scrolled_window do
                text_view :set_size_request => [-1, 100]
              end
            end
          end
        end
        hbox do
          hbox :layout => [true, true]
          hbutton_box :border_width => 5 do
            button '保存'
            button '重置'
          end
          hbox :layout => [true, true]
        end
      end
    end
  end
end

MyWin.new.show_all
Gtk.main




相关推荐

    win32 sdk版 贪吃蛇 300行代码

    【标题】"win32 sdk版 贪吃蛇 300行代码"是一个基于Windows API(Win32 SDK)开发的经典游戏“贪吃蛇”的小型实现,它使用了不到300行的源代码。这样的项目通常用于教学目的,帮助初学者理解如何在Windows环境下使用...

    用300行代码手写Spring V1.0版本

    本文将通过分析标题"用300行代码手写Spring V1.0版本"和描述,探讨Spring的基本设计理念和实现机制。 首先,Spring的核心是IoC容器,它负责管理对象的生命周期和依赖关系。在300行代码的简化版本中,我们将看到如何...

    Python-PyBlockchainCLI300行Python代码实现的区块链命令行工具

    PyBlockchainCLI:300 行 Python 代码实现的区块链命令行工具

    300行代码实现的智能五子棋人机对战

    标题 "300行代码实现的智能五子棋人机对战" 提示我们这是一个关于编程的项目,其中开发者用相对较短的代码量创建了一个功能完整的五子棋游戏,允许玩家与计算机进行对战。这样的项目通常涉及到算法设计、游戏逻辑...

    java 版连连看(300行代码)

    【标题】:“java 版连连看(300行代码)”是基于Java编程语言实现的一款经典游戏连连看的简化版本。这款程序展示了如何利用Java来设计一个简单的游戏逻辑,特别适合初学者学习和理解面向对象编程思想。 【描述】:在...

    Java经典编程300例源代码

    在这个压缩包中,你将找到300个不同的Java代码实例,每个实例都针对特定的编程问题或技术。 首先,我们来探讨一些基本的Java编程概念。Java是一种面向对象的编程语言,它的核心概念包括类、对象、封装、继承和多态...

    小型GPT模型:用300行PyTorch代码实现的小型GPT语言模型库

    特斯拉AI总监Andrej Karpathy用300行PyTorch代码实现的小型GPT语言模型库,适用于自然语言生成和文本分类任务。

    300行小游戏-推箱子

    纯oc的小游戏,代码限制在300行内,纯属个人坑爹。 无图片,无音效,仅实现主要功能。 ----------------------------------------- 推箱子: 支持自定义地图大小,自定义关卡数等

    java贪食蛇源代码(300多行)

    【标题】"java贪食蛇源代码(300多行)"揭示了这是一个基于Java编程语言实现的贪食蛇游戏项目。贪食蛇游戏是一种经典的像素级游戏,玩家通过控制一条不断移动的蛇来捕食食物,每吃掉一个食物,蛇的身体就会增长一段,...

    python大作业-300行代码函数.zip

    "python大作业-300行代码函数.zip" 提供的资源显然是一份包含300行代码的Python函数集合,可能是为了帮助学习者深入理解函数的编写、模块化编程以及问题解决策略。这个压缩包"ljg_resource"可能包含了相关的代码文件...

    300个C语言程序范例

    《300个C语言程序范例》是一个包含丰富C语言编程实践的资源集合,它不仅提供了基础的语法示例,还涵盖了网络通信系统、学生信息管理系统和小游戏等多个实际应用场景的程序设计。这个压缩包旨在帮助学习者深入理解和...

    300行代码(Tensorflow 2)完全复制了Transformer模型,并用于神经机器翻译任务和聊天机器人. 3

    300行代码(Tensorflow 2)完全复制了Transformer模型,并用于神经机器翻译任务和聊天机器人. 300行代码(Tensorflow 2)完整复现了Transformer模型,并且应用在神经机器翻译任务和聊天机器人上。_Transformer_...

    python贪吃蛇游戏,仅不到300行代码

    python贪吃蛇游戏,仅不到300行代码

    300行人脸识别代码运行

    标题 "300行人脸识别代码运行" 暗示我们正在处理一个涉及人脸识别的项目,其中可能包含针对大量行人(300个)的识别算法。描述中的内容简洁,但我们可以推测这是一个关于如何运行该代码的教程或者实现。标签 "python...

    C语言期末大作业参考代码

    在本资源中,"C语言期末大作业参考代码"提供了两个关键的学习材料,分别是17届抽学号和18届抽学号的C语言源程序。这些代码旨在帮助学生理解如何利用C语言来实现类似的功能,同时也为他们的期末大作业提供了一些灵感...

    Python小游戏之300行代码实现俄罗斯方块

    但是想到旋转,停靠,消除等操作,感觉好像很难啊,等真正写完了发现,一共也就 300 行代码,并没有什么难的。 先来看一个游戏截图,有点丑,好吧,我没啥美术细胞,但是主体功能都实现了,可以玩起来。 现在来看...

    不到300行的Turboc下面的俄罗斯方块源码实现

    本文将深入探讨使用Turboc编译器实现的不到300行的俄罗斯方块源码,通过对代码的详细解读,揭示其中蕴含的编程技巧和知识。 Turboc是Borland公司推出的C编译器,以其小巧高效的特点在早期Windows环境下广受欢迎。在...

    代码行数统计工具

    在实际应用中,代码行数统计工具通常会区分空行、注释行和实际包含逻辑的代码行。例如,SourceCounter这个工具可能具备以下功能: 1. **多语言支持**:SourceCounter可能支持多种编程语言,如C、C++、Java、Python...

    300多种加密解密算法(C++)源代码

    300多种加密解密算法(C++)源代码 300多种加密解密算法(C++)源代码

Global site tag (gtag.js) - Google Analytics