テーブルにデータを表示する

ここでは、Interface Builder で作ったテーブルにデータを表示するスクリプトについて書いていく。テーブルの設定などについては、Table view を Xcode と Interface Builder で設定するを参照。

あと、Array Controller を使ってテーブルに表示するデータを扱いたい場合は、Array Controller にある項目を参照してください。時間があれば、ここに書いてあるようなことを Array Controller を使ってやる方法をまとめてみたいと思ってますが、いまのところは、Array Controller の項目として分散しています。

さて、RubyCocoa でテーブルにデータを表示するには少なくとも次の2つにメソッドが必要になる。

numberOfRowsInTableView(tableView) (numberOfRowsInTableView:)

tableView_objectValueForTableColumn_row(tableView, col, row) (tableView:objectValueForTableColumn:row:)

numberOfRowsInTableView で表示する列の数を指定して、tableView_objectValueForTableColumn_row で表示するデータを指定していく。

試しに、Table view の項目で作ったテーブルにデータを表示する、一番簡単なスクリプト。

require 'osx/cocoa'

class AppController < OSX::NSObject

include OSX

ib_outlets :window, :table

def numberOfRowsInTableView(tableView)

3

end

def tableView_objectValueForTableColumn_row(tableView,col,row)

'test'

end

end

これを Command + R で Xcode から実行すると、次のように表示されるはず。

上のスクリプトで何をしているかというと、numberOfRowsInTableView というメソッドで表示する列を指定している。この場合は3。括弧の中の tableView は他の変数とかち合って困るような事がなければどんな名前でもいいはず。tableView_objectValueForTableColumn_row では、指定した3行目までテーブルにある2列の両方、全部で6つのセルに test と表示する。これは、どこの行、列に何を表示するかという指定がしていないので、すべてに同じものが表示される。

ここで、もう一歩進めて、コラムによって表示する内容を変えてみる。

上のスクリプトの tableView_objectValueForTableColumn_row のメソッドの内容を変えてみる。括弧の中の (tablveView, col, row) には、それぞれ、アプリケーションにあるテーブル、行、列の情報が入る。テーブルを作るときに、2つの列それぞれに col1 と col2 という Identifier をつけたので、それを使って col.to_s がそれぞれの行のときに異なる表示内容を指定すればいい。ここでは、どの行か、というのを知るために tableColumnWithIdentifier(id) というメソッドを使う。table の col1 の時は、@table.tableColumnWithIdentifier('col1').to_s と書く。if ~ でもいいけど、case ~ when の方がすっきりするので、次のように書いてみた。

def tableView_objectValueForTableColumn_row(tableView, col, row)

case col.to_s

when @table.tableColumnWithIdentifier('col1').to_s

'column 1'

when @table.tableColumnWithIdentifier('col2').to_s

'column 2'

end

end

さらに、配列を使って、すべてのセルに異なる値を入れてみる。initialize というメソッドの中に、@output という配列を作って、そこに値を入れる。たとえば、次のような3行2列の配列を作る。

@output = [[0,1],[2,3],[4,5]]

次に、numberOfRowsInTableView には、列の長さとして、この配列の長さを入れればいいので、@output.length といれる。

最後に、tableView_objectValueForTableColumn_row では、それぞれの行と列で配列のそれぞれの値が入るようにする。何列目かという情報は、row に入っているので、@output[row][0] と @output[row][1] をそれぞれ col1 と col2 に当てる。これをまとめると、次のようになる。ここでは、col と @table.tableColumnWithIdentifier(col) に to_s がついているけど、他でもわかるように、なくても平気

注意:.to_s がなくても平気、と書いたんだけど、どうやら、場合によっては問題があることがわかった。必ずそうなるようでもないし、なぜだかよくわからないんだけど、.to_s がない場合に、一行目の一列目のセルが描画されないことがある。というわけで、.to_s を付けておいた方が無難なようだ。

def initialize

@output = [[0,1],[2,3],[4,5]]

end

def numberOfRowsInTableView(tableView(tableView)

@output.length

end

def tableView_objectValueForTableColumn_row(tableView, col, row)

case col.to_s

when @table.tableColumnWithIdentifier('col1').to_s

@output[row][0]

when @table.tableColumnWithIdentifier('col2').to_s

@output[row][1]

end

end

これを実行させて、次のような表示が得られるはず。

おしまいに、何かを実行させて値を得て、それをもとにテーブルのデータを表示、更新するスクリプトを書いてみる。後々応用できるように、テーブルが表示させたいテーブルと一致したときにだけ表示できるように、というのと、配列が定義されてなかった場合にエラーが出ないように、あと、ボタン押したときに、毎回内容を更新できる、と、そのくらいのことをしている。

require 'osx/cocoa'

include OSX

class AppController < OSX::NSObject

def initialize

@output = []

end

def numberOfRowsInTableView(tableView(tableView)

case tableView.to_s

when @table.to_s

@output ? @output.length : 0

end

end

def tableView_objectValueForTableColumn_row(tableView, col, row)

case col.to_s

when @table.tableColumnWithIdentifier('col1').to_s

@output[row][0]

when @table.tableColumnWithIdentifier('col2').to_s

@output[row][1]

end

end

def tableFill(sender)

@output = []

5.times do

@output << [(rand()*100.to_i,(rand()*100).to_i]

end

@table.reloadData

end

ib_action :tableFill

end

まず、numberOfRowsInTableView では、tableView.to_s と @table.to_s で比べて、@table の列の長さを指定するようにしている。これは、to_s をつけないと id は同じでも一致しないから。to_s で Ruby の String オブジェクトにすると、<NSTableView: id>(id はテーブルの id)っていう感じになるから、これだとうまくいく。

つぎに、@output ? @output.length : 0 で @output があるときは @output.length で、配列がないとき nil だと0になる。これは、Ruby な書き方で、

a = (condition) ? (true) : (false)

てな感じで、condition(条件)が true(真)のときは、A が代入されて、false(偽)のときは B が代入される。

tableView_objectValueForTableColumn_row でも同様に表示したいテーブルのときだけ表示させるようにしてる。テーブルが複数あるときは、別のテーブルのを when で加えていく。

最後に、tableFill のメソッドで、テーブルの内容を書き換えてる。@table.reloadData ってのでテーブルの内容を更新してる。ib_action にこのメソッドを追加すると、それが Interface Builder で Received Action として現れるので、ウィンドウにボタンを追加して結びつける。

これですべて保存して、実行すると、ボタンを押すごとにテーブルの内容が変わるはず。