• ベストアンサー

DataGridで特定の行のスタイルを変更したい

お世話になります。 DataGridコンポーネントに商品データを表示しています。 表示するデータは、「商品名」、「販売数」、「在庫数」です。 「在庫数」が20以下になった場合に行の背景色、テキストの色を変更したいのですが、方法が見つかりません。 ヘルプやWebで調べたところ、DataGrid全体の色を変更する、または1行おきに変更できることは分かったのですが、 特定の行に対してのスタイル指定方法が分かりませんでした。 解決方法をご存知の方がいらっしゃいましたら、ご教授宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • DPE
  • ベストアンサー率85% (666/776)
回答No.2

リストタイプのコンポーネントには、セルを描画するためのスクリプト(セルレンダラー)が最初から組み込まれています。 このセルレンダラーは、自分でセル描画用のクラスを作って独自の描画処理に取り替えることもできます。 DataGrid の行は、塗りだけの四角形が描かれたムービークリップの上に文字を表示するテキストフィールドなどを重ねている、という構成です。 背景色を指定したり、選択した時やカーソルを合わせた時に行の背景色が変わるのは、背景であるムービークリップの色が変化しているためです。 デフォルトの DataGrid のセルレンダラーでは、背景のないテキストフィールドを作ってムービークリップに重ねているので、下にあるムービークリップの色が透けて行の背景色が変化して見えるというわけです。 行の背景そのものである、テキストフィールドの下にあるムービークリップの色を変えようとすると難しくなります。 背景色と文字色を変えるだけでいいのでしたら、ある条件の時(ご質問の例ですと、在庫数が 20 以下の時)にセルであるテキストフィールドの背景をありにして、この背景色と文字色を変えるというセルレンダラーを作成してはいかがでしょう。 セルのテキストフィールドを行の大きさとほぼ同じ大きさで作ると、行の背景色が変化しているように見えるかと思います。 ------------------------------------------------------------------- セルの描画に使うクラスにはいくつかの条件があります。 資料が殆どありませんので、ヘルプの「コンポーネントリファレンスガイド」→「 CellRenderer API 」の項目をご一読なさってください。 主な流れは、「コンポーネントリファレンスガイド」→「 CellRenderer API の使用」にある通りです。  ・Flashドキュメンテーション:CellRenderer API の使用   http://livedocs.macromedia.com/flash/8_jp/main/00003130.html まず、セルレンダラーにするクラスを定義します。 できたクラスをムービークリップシンボルに関連付け、ムービーに書き出します。 コンポーネントが持っている cellRenderer プロパティにこのムービークリップのリンケージ名を指定すると、指定のクラスの機能でセルが描画されるようになります。 ActionScript 2.0 では、クラスは外部 as ファイルとして作成します。 クラスを定義する時はパス(クラスパス)が大切です。 今回はとりあえず、クラスの再利用や汎用性については考慮しません。as ファイルは制作中の fla ファイルと同じフォルダ内に置いてください。 クラスの名前は” ColoringCell ”とします。 「ファイル」メニュー→「新規」で” ActionScript(AS)ファイル”を選択し、as ファイルを作成してください。 as ファイルの編集中は専用の画面になりますが、基本的な使い方は「アクション」パネルと同じです。 クラス定義の一例です。 このスクリプトは as ファイルに記述してください。 (↓各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください)  class ColoringCell extends mx.core.UIComponent  {   ////////////////////////////////////////////   //各種宣言   ////////////////////////////////////////////   //Listクラスから提供される関数とプロパティ   private var getCellIndex:Function;   private var owner;   private var listOwner;   //セル自身の参照を保持   private var cell_obj;   ////////////////////////////////////////////   //コンストラクタ:初期処理は何も行わない   ////////////////////////////////////////////   public function ColoringCell()   {   }   ////////////////////////////////////////////   //セルの作成   ////////////////////////////////////////////   public function createChildren()   {    var cell_w , cell_h;    //セルとして使うテキストフィールドを作成    //大きさは行自身より一回り小さくする    cell_w = owner.__width - 2;    cell_h = owner.__height - 2;    cell_obj = this.createTextField( "coloring_cell" , 1 , 0 , 0 , cell_w , cell_h );    //セルの初期設定    //さしあたって、境界線/背景なし・単一行・折り返しなし・選択不可    cell_obj.border = false;    cell_obj.background = false;    cell_obj.multiline = false;    cell_obj.wordWrap = false;    cell_obj.selectable = false;   }   ////////////////////////////////////////////   //セルの大きさを調整する関数   ////////////////////////////////////////////   //推奨されるセルの高さを返す関数   public function getPreferredHeight()   {    //行自身の大きさよりも一回り小さい高さを返す    return( owner.__height - 2 );   }   //セルの大きさを調整する関数   public function size()   {    //行自身よりも一回り小さくする    cell_obj.setSize( owner.__width - 2 , owner.__height - 2 );   }   ////////////////////////////////////////////   //セルの描画   ////////////////////////////////////////////   public function setValue( str , item , select_status )   {    var stock_cnt , index , clr;    //itemが未定義(=セルが空っぽ)の場合はセルを非表示にする    if( item == undefined )    {     cell_obj._visible = false;    }    //表示する内容がある場合、在庫数(列名”stock”の値)に応じて    //背景色と文字色を変更する    else    {     //描画対象のセルの番号をもとに、”在庫数”の値を取得する     index = getCellIndex();     stock_cnt = listOwner.getItemAt( index.itemIndex ).stock;     //在庫数が20以下のものは、背景を濃いグレー・文字色を白にする     if( stock_cnt <= 20 )     {      cell_obj.background = true;      cell_obj.backgroundColor = 0xbbbbbb;      cell_obj.textColor = 0xffffff;      cell_obj.text = str;      cell_obj._visible = true;     }     //それ以外は背景をなしに、文字色を黒またはグリッド指定の色にする     else     {      //グリッド全体の文字色を取得      //定義されていれば指定の色に、未定義の場合は黒に設定する      clr = listOwner.getStyle( "color" );      if( clr == undefined )      {       clr = 0x000000;      }      cell_obj.background = false;      cell_obj.textColor = clr;      cell_obj.text = str;      cell_obj._visible = true;     }    }   }  } クラス定義ファイルはクラス名と同じ名前で保存する必要があります。 制作中の fla ファイルと同じフォルダ内に、” ColoringCell.as ”の名前で保存してください。 セルは createTextField メソッドで空っぽのテキストフィールドを作ります。 ヘルプのサンプルでは、UIObject クラスが持っている createLabel メソッドで拡張テキストフィールドを作っています。 しかし、この方法ですと1度スクロールアウトして再描画しないと指定が反映されないことがあるなど扱いが面倒でしたので、上記のクラスでは簡単なところで普通のテキストフィールドを作っています。 できたセルの参照は cell_obj という変数に保存しています。 書式などの変更は、一般的なテキストフィールドの操作と全く同じです。 細かいことはさておき、このクラスの肝は setValue 関数です。 描画しようとしているセルの番号は getCellIndex というメソッドで取得できます。 このメソッドでセルの番号を取得し、これをもとにグリッドで扱っているデータから在庫数を取得して、在庫数に応じたセルの書式を決めます。 グリッドのデータについては次で説明いたします。 次は、fla ファイルに、このセルレンダラーを実際に DataGrid に適用するスクリプトを書きます。 ******************************** クラスを定義した as ファイルは、何もしなければムービー内で利用することはできません。 今回はムービークリップに関連付ける方法でムービーに組み込みます。 まず、ムービークリップシンボルを作ってください。絵は何も描かなくても構いません。 「ライブラリ」にできたこのシンボルを選び、右クリック( Mac では control +クリック)で出すメニューから「リンケージ...」を選択してください。「リンケージプロパティ」パネルが開きます。 「 ActionScript に書き出し」と「最初のフレームに書き出し」にチェックを入れると、「識別子」と「 AS 2.0 クラス」の項目が編集できるようになります。 「 AS 2.0 クラス」には先ほど作ったクラスの名前(厳密に言うとクラスパスですが)を、識別子には何か分かりやすい名前を入力してください。 さしあたって、両方とも” ColoringCell ”と入力したものとします。 ステージに DataGrid コンポーネントのインスタンスを配置し、インスタンス名を付けてください。 ここでは仮に” grid ”とします。 列は左から順に、「商品名」「販売数」「在庫数」とします。 「在庫数」だけは、先ほどの ColoringCell クラスを使って描画するように変更します。 スクリプトにしますと、大体、次のようになります。 このスクリプトはメインのタイムラインに設定してください。 (↓各行頭に全角のスペースが入っています。コピーする際はご注意ください)  //仮の在庫データ  stock_data = new Array();  stock_data =  [   { item_name : "ポーション" , sold : 25 , stock : 55 } ,   { item_name : "エーテル" , sold : 2 , stock : 20 } ,   { item_name : "毒消し" , sold : 6 , stock : 54 } ,   { item_name : "目薬" , sold : 5 , stock : 25 } ,   { item_name : "やまびこえんまく" , sold : 30 , stock : 12 } ,   { item_name : "うちでのこづち" , sold : 10 , stock : 25 } ,   { item_name : "金の針" , sold : 30 , stock : 28 } ,   { item_name : "フェニックスの尾" , sold : 3 , stock : 37 } ,   { item_name : "万能薬" , sold : 0 , stock : 5 } ,   { item_name : "エリクサー" , sold : 0 , stock : 0 }  ];  //グリッドにデータを表示  grid.dataProvider = stock_data;  //ヘッダとスタイルの定義  //文字色を紺に、背景をピンクと黄色のストライプにする  grid.getColumnAt( 0 ).headerText = "商品名";  grid.getColumnAt( 1 ).headerText = "販売数";  grid.getColumnAt( 2 ).headerText = "在庫数";  grid.setStyle( "color" , 0x000066 );  grid.setStyle( "alternatingRowColors" , [ 0xffefef , 0xffffdd ] );  //在庫数の列のみ、独自のセルレンダラーを使う  grid.getColumnAt( 2 ).cellRenderer = "ColoringCell"; 上記の DataGrid では、stock_data という配列変数に格納されたデータを扱います。 この配列変数には item_name ・ sold ・ stock という3つの識別子があり、これがグリッドの各列に対応します。 先の ColoringCell.as の setValue 関数で、在庫数を判断して書式を変えるためには、まずは該当する行に表示される在庫数を把握しなければなりません。 描画しようとしているセルの番号を getCellIndex メソッドで取得し、取得した番号をもとにグリッドで扱っている配列変数の stock 識別子で管理されているデータを見て、在庫数を取得します。 取得した数(在庫数)が 20 以下であればセルであるテキストフィールドに背景を付けて背景色をグレーにし、それ以外の時は背景をなしに設定します。 セルの描画に使うクラスは、cellRenderer というプロパティで登録します。 登録するものは、セル描画用のクラスを関連付けたムービークリップシンボルの”リンケージ名”です。この作例ではどちらも同じ名前を付けましたが、「識別子」に違う名前を付けた場合は識別子の方を指定してください。 DataGrid では cellRenderer プロパティを持っているのはグリッド全体ではなく各列ですから、列単位でセルレンダラーを定義します。 この例では3番目(列の番号は 0 から始まるので、スクリプトでは2番目)の在庫数の列だけに独自のセルレンダラーを適用していますけれど、同じ要領で  grid.getColumnAt( 0 ).cellRenderer = "ColoringCell";  grid.getColumnAt( 1 ).cellRenderer = "ColoringCell"; を追加すると、全ての列で同じように描画されるようになります。 ------------------------------------------------------------------- 他にも、例えば売上数を見て色を分けたり、別のセルレンダラーを作って列ごとに表示を変えるといったこともできます。 変更のポイントは ColoringCell.as の setValue 関数内の、グリッドで扱っているデータを見るところと書式を変える処理です。 今回は描画クラスに背景色や書式を決める際に評価する項目(在庫数=” stock ”の列)を見る処理を直接組み込んでしまったため、汎用性がありません。 色や評価する項目などを変更したい時は、ColoringCell.as クラスの内容を書き換えてください。 setStyle メソッドを駆使してこれらを外から指定できるように改良すると、クラスファイルを書き換えることなく fla ファイルから変更できるようになるかと思います。 CellRenderer やクラスについては私も研究中で、その場しのぎの設計のクラスではありますが、よろしければご参考までに。

nobnobnobnob
質問者

お礼

詳しい回答、ありがとうございます。 また、お礼が遅くなってしまい申し訳ありませんでした。 少し敷居が高いかなと思いましたが、CellRenderer API を利用してみます。

その他の回答 (1)

  • mahny
  • ベストアンサー率74% (57/77)
回答No.1

FlexのDataGridでしたら、itemRendererを使って変更可能です。 参考URLの例では、Labelを継承していますが TextFieldなんかでもできるので、適所使い分けで見てください。

参考URL:
http://d.hatena.ne.jp/chisa-to/20060824/1156426502
nobnobnobnob
質問者

お礼

回答、ありがとうございます。 環境を書き忘れていました。 Flash8 Professionalです。 Flash8ではitemRendererのようなものは無いのですかね? 調べてみます。

関連するQ&A