Skip to main content
The Kai Way

FxRuby Part3

之前的:FxRuby初体验Part1Part2

这个V0.3的PictureBook添加了相册视图,也就是把相片都放到其中。看看下面的代码吧,我把每次都贴上完整的代码,方便大家复制粘帖:-)

#photo.rb class Photo attr_reader :path def initialize(path) @path = path end end

#album.rb class Album attr_reader :title def initialize(title) @title = title @photos = [] end def add_photo(photo) @photos << photo end def each_photo @photos.each { |photo| yield photo } end end

#album_list.rb class AlbumList def initialize @albums = [] end

def add_album(album) @albums << album end def remove_album(album) @albums.delete(album) end def each_album @albums.each { |album| yield album } end end

#photo_view.rb class PhotoView < FXImageFrame MAX_WIDTH = 200 MAX_HEIGHT = 200 def initialize(p, photo) super(p, nil) load_image(photo.path) end def load_image(path) File.open(path, "rb" ) do |io| self.image = FXJPGImage.new(app, io.read) scale_to_thumbnail end end def scaled_width(width) [width, MAX_WIDTH].min end def scaled_height(height) [height, MAX_HEIGHT].min end def scale_to_thumbnail aspect_ratio = image.width.to_f/image.height if image.width > image.height image.scale( scaled_width(image.width), scaled_width(image.width)/aspect_ratio, 1 ) else image.scale( aspect_ratio*scaled_height(image.height), scaled_height(image.height), 1 ) end end end

#album_view.rb require 'photo_view' class AlbumView < FXMatrix attr_reader :album def initialize(p, album) super(p, :opts => LAYOUT_FILL|MATRIX_BY_COLUMNS) @album = album @album.each_photo { |photo| add_photo(photo) } end def add_photo(photo) PhotoView.new(self, photo) end def layout self.numColumns = [width/PhotoView::MAX_WIDTH, 1].max super end end

#picture_book.rb require 'fox16' include Fox require 'album' require 'album_view' require 'photo' class PictureBook < FXMainWindow def initialize(app) super(app, "Picture Book" , :width => 600, :height => 400) add_menu_bar @album = Album.new("My Photos" ) @album_view = AlbumView.new(self, @album) end def add_menu_bar menu_bar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X) file_menu = FXMenuPane.new(self) FXMenuTitle.new(menu_bar, "File" , :popupMenu => file_menu) import_cmd = FXMenuCommand.new(file_menu, "Import..." ) import_cmd.connect(SEL_COMMAND) do dialog = FXFileDialog.new(self, "Import Photos" ) dialog.selectMode = SELECTFILE_MULTIPLE dialog.patternList = ["JPEG Images (*.jpg, *.jpeg)" ] if dialog.execute != 0 import_photos(dialog.filenames) end end exit_cmd = FXMenuCommand.new(file_menu, "Exit" ) exit_cmd.connect(SEL_COMMAND) do exit end end def import_photos(filenames) filenames.each do |filename| photo = Photo.new(filename) @album.add_photo(photo) @album_view.add_photo(photo) end @album_view.create end def create super show(PLACEMENT_SCREEN) end end

if FILE == $0 FXApp.new do |app| PictureBook.new(app) app.create app.run end end

这里相对于上个版本的改动的地方有,PictureBook增加了菜单栏,增加了一个视图AlbumView,PhotoView实例的创建放在了AlbumView中,PhotoView中增加了图片的缩略图操作。

菜单栏的创建也听挺麻烦的,先创建FXMenuBar的实例,然后是创建FXMenuTitleFXMenuPane的实例,FXMenuTitle是FXMenuBar的下级元素,就是菜单栏的每一段,FXMenuPane是FXMenuTitle的弹出菜单。然后要创建FXMenuCommand,它是FXMenuPane的下级元素,实例化后就要用connect方法给出的代码块将其绑定到一定的行为上。

File>Importd这个动作是打开一个文件对话框FXFileDialog让你选择文件,然后用filenames方法获得选择得到的文件的数组。退出的菜单项很简单,就是一个exit方法。

在PhotoView中的图片操作功能是从FXImageFrame继承得到的,这个能力和接口很像RMagic。 AlbumView 是FXMatrix的实例,FXMatrix是一种布局管理器,它以行列的方式来对组件进行布局。好像布局管理器的基类就是FXPacker ,可以通过重写它的Layout方法来改变布局流。像这里就改变了FXMatrix的行数。

接着书中作者又改了一下,因为FXMatrix不能够在图片太多的情况下全部显示,会产生因为图片过多导致产生很多行,然后让超出主窗体的图片行无法看见,所以作者又对AlbumView换了一个布局管理器。

#album_view.rb require 'photo_view' class AlbumView < FXScrollWindow attr_reader :album def initialize(p, album) super(p, :opts => LAYOUT_FILL) @album = album FXMatrix.new(self, :opts => LAYOUT_FILL|MATRIX_BY_COLUMNS) @album.each_photo { |photo| add_photo(photo) } end def layout contentWindow.numColumns = [width/PhotoView::MAX_WIDTH, 1].max super end def add_photo(photo) PhotoView.new(contentWindow, photo) end end

FXScrollWindow是另一种布局管理器,它只是多了滚动条。其中还是包含了一个FXMatrix。