Archive for 2009/5/22
DataGridを使ってリストをカラムがうまく変更されないので、その調整をするようなクラスを作成しました。
具体的には、拡大、縮小すると一部のフィールドだけ拡大、縮小してしまうのです。
この再現方法がわからないのですが、たまに発生するのです。
あとはminWidthを設定していても、縮小するとたまに、その指定以下になってしまうと気があります。
さらに、私はその部分にresiable=”false”を指定しているので、そうなってしまうともう拡大することができないのです。
なので、この部分を強制的に再度、サイズを調整するクラスを作成しました。
動きとしては、拡大、縮小するときにそれまでの比率を保ったまま拡大、縮小されるのですが、その調整が終わった後にminWidthの指定があるものに関しては、そのサイズに再度調整しています。
実際にこの処理が行われるのは、サイズがユーザにより変更されたときと、全体のサイズ(更新が必要な時)の変更があったときのイベントを利用しています。
DataGridのカラムのサイズがユーザにより変更された時のイベントは
dataGrid.addEventListener(DataGridEvent.COLUMN_STRETCH,changeColumnWidth);
です。
はじめ、DataGridColumnのソースを見たらset width()でイベントを発行していたので、それを使えばと思いましたが、あっ、widthを変えているのだからそれじゃ、どうすれば・・とDataGridのソースを見ました。
そしたら、DataGridEvent.COLUMN_STRETCHがあったので、おお、それだと。
そして、とりあえずこんな感じ。
package com.coltware.cise.ui.helper
{
import flash.utils.Dictionary;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.events.DataGridEvent;
import mx.events.FlexEvent;
public class DataGridResizeController
{
private var dataGrid:DataGrid = null;
private var oldWidth:Number = -1;
private var oldColNum:Number = -1;
private var invalidateDisplayList:Boolean = false;
private var cols:Dictionary;
private var _enable:Boolean = true;
public function DataGridResizeController(dg:DataGrid)
{
cols = new Dictionary();
dataGrid = dg;
enable = true;
}
public function get enable():Boolean{
return _enable;
}
public function set enable(b:Boolean):void{
if(b){
_enable = true;
dataGrid.addEventListener(FlexEvent.CREATION_COMPLETE,create);
dataGrid.addEventListener(FlexEvent.UPDATE_COMPLETE,update);
dataGrid.addEventListener(DataGridEvent.COLUMN_STRETCH,changeColumnWidth);
}
else{
_enable = false;
dataGrid.removeEventListener(FlexEvent.CREATION_COMPLETE,create);
dataGrid.removeEventListener(FlexEvent.UPDATE_COMPLETE,update);
dataGrid.removeEventListener(DataGridEvent.COLUMN_STRETCH,changeColumnWidth);
}
}
private function create(e:FlexEvent):void{
oldWidth = dataGrid.width;
}
private function update(e:FlexEvent):void{
trace("update ...");
if(oldWidth != dataGrid.width){
invalidateDisplayList = true;
}
if(invalidateDisplayList){
oldWidth = dataGrid.width;
for(var key:Object in cols){
var p:Number = cols[key] as Number;
var w:Number = Math.floor(oldWidth * p);
var c:DataGridColumn = key as DataGridColumn;
if(c && c.minWidth > w){
trace("no resize col " + c.minWidth + ">" + w );
}
else{
c.width = w;
}
}
// 最後に小さくなりすぎた resize = false のオブジェクトを戻す
for each(var col:DataGridColumn in dataGrid.columns){
if(!col.resizable && col.minWidth){
col.width = col.minWidth;
}
}
invalidateDisplayList = false;
}
else{
}
}
/**
* カラムのサイズがユーザにより変更された時の処理
*
*/
private function changeColumnWidth(e:DataGridEvent):void{
computePercent();
}
private function computePercent():void{
var w:Number = dataGrid.width;
cols = new Dictionary();
var arr:Array = new Array();
for each(var col:DataGridColumn in dataGrid.columns){
if(col.visible){
if(col.resizable){
arr.push(col);
}
else{
w = w - col.width;
}
}
}
for each(var col2:DataGridColumn in arr){
var p:Number = col2.width / w;
cols[col2] = p;
}
}
}
}
結構、ASDocの結果ってわかりにくいなーと思いますね。
というか、プロパティやらイベントやら、1つのクラスに多すぎるのかもしれません。
最近、見えるんだったらソースを見てしまえと、見てしまいます。
余談ですが、ここで、Flex Builderの「定義へ移動」のメニューはいいですね。
でも、それでもある程度見当が付いているときには、だらだらとみているのは面倒なのでFlex Linux版をインストールして、それで、grepを使って思いの処理がありそうか調べています。
ただ、おおよそうまくいくようになったのですが、それでもたまに最後のカラムだけが拡大・縮小してもサイズ変更されない場合があるのです。
これまた、なぜ発生するのはわからないのです。
こんな問題も、サイズ固定にしてしまえば問題ないのですが・・・
それでは使い勝手が悪いので。
でも、よくVBとかでできた製品でサイズ変更してしまうとレイアウトが崩れるのがありますが、かっこ悪いですよね。大変なのはわかりますが・・・
(と言うと、今後自分の首もしめることに・・・)
この問題はEclipseのプラグインでアプリケーションを作成していたときにはあまり遭遇しなかったのですが・・
よりUIを自由にやろうとすると、このあたりの制御がプログラマに戻ってしまい大変ですね。
さらにFlexも、ActionScriptもはじめて半年もたっていない私には基本部分の理解不足を思い知らされます。

