投稿

[Dart]Stream.listenに2重のリスナ

DartのStreamのリスナ管理の話 Stream.listenを使ってリスナを貼るのだが、やればやるほどリスナが貼られていくよね。 new ButtonElement() ..onClick.listen( ()=> print("hoge") ) ..onClick.listen( ()=> print("hoge") ); 結果 >hoge >hoge これは、onClick呼び出し内でStream<T>がnewされるためだ。(EventStreamProvider.forTargetを内部で呼んでいる) そして、listen()でさらにStreamSubscription<T>がnewされている。 実際にリスナを持つのは、このStreamSubscriptionで、こいつはリスナを一つしか持てない。 ということは、リスナは追加ではなく差し替えにしたい場合、こいつのonDataを書き換えてやれば良いわけだ。 ちなみに、StreamSubscription.cancel()を呼び出すことで、それ以降のイベントの配信を停止できる。 下のソースは、クリックされるたびにTextを変更し、2回目のクリックでそれ以降のイベントの受信を停止するサンプルだ。 ButtonElement btn = new ButtonElement(); StreamSubscription<Event>  s = btn. onClick .listen( null ); s.onData( ( e ) {   btn. text = "first click" ;   s.onData( ( e ) { btn. text = "second click" ;s.cancel(); } ); } ); 参考: Getting Your Feet Wet with Streams

[Dart]Streamを返す関数

例えばElementのonClickなど、Streamを返す関数はDartの標準ライブラリに多数存在する。 というわけで、自分もStreamを返す関数を作りたい。 以下、サンプル。 StreamController<String> cont = new StreamController(); Stream<String> get onReceive => cont.stream; void update() { HttpRequest.request("http://...../data") .then( (HttpRequest req) { cont.add(req.responseText); if( isFinish ) // 終了フラグ cont.close(); }) .catchError( (e) { cont.addError(e); }); } キモはStreamControllerだ。 addメソッドでデータを送り、終了したらcloseメソッドでストリームを閉じる。 エラーはaddErrorメソッドで通知。 ちなみに、このサンプルでデータ取得ハンドラを貼るには下記のようにする。 a.onReceive.listen( (String data) => print(data) ); ※上記サンプルがクラスとして定義されて変数aになっているとする。

[Dart]Futureを返す関数

Dartで標準で用意されているメソッドはFutureを返すものがある。 これは遅延を伴う処理を、無駄なく行うための重要な機構だ。 というわけで自分のメソッドもFutureを返すようにしたいのだが、 そのやり方は下記の通り。 Future<chartdata> httpAccessTest() { Completer comp = new Completer(); HttpRequest.request("http://..../xxx") .then( (HttpRequest req) { // 成功した時 comp.complete(req.responseText); }) .catchError( (e) => comp.completeError(e) ); // 失敗した時 return comp.future; } これはhttpでデータを取得するサンプルだ。 Completerオブジェクトを使用するのがミソ。 っていうか、それしかないが。 正常終了の結果はcompleteメソッドで通知。 エラーは、completeErrorメソッドを使用して通知。サンプルでは元の処理でThrowされているものをそのまま転送している。 ちなみに、Completerが使えるのは一回こっきりだ。使い回しはできない。 Futureの使い方 http://www.dartlang.org/articles/using-future-based-apis/ Futureのエラーハンドリング方法 http://www.dartlang.org/articles/futures-and-error-handling/

HTML5 Canvas

直線がぼやける件 HTML5のCanvasでlineWidth=1の直線を描画した時、 ぼやけるのが嫌だったのだが、 座標に0.5を足すことでパキっとした線になることを知った。 ブラウザ上でコードをEditして動作テストする http://www.html5canvastutorials.com/tutorials/html5-canvas-line-width/ HTML5 Canvasのパフォーマンスの改善 http://www.html5rocks.com/ja/tutorials/canvas/performance/ canvasをdivにぶら下げると下側に謎のスキマが空く件 これは、canvasの下端がテキストのベースラインと揃えられているからです。 というわけで、canvas側にvertical-alignを設定しましょう。 vertical-align : bottom; ratina対応の件 Dartでの例。 つまり、canvasの属性のwidthとheightは2倍に指定し、styleのwidthとheightは普通に設定した上で、座標変換に2倍を設定しておけば、何も考えずにOK。     canvas = new CanvasElement( width:w* 2 , height:h* 2 );     canvas . style.. width = " ${w} px" .. height = " ${h} px" ;      canvas . context2D .scale( 2 , 2 ); drawImageで画像を描画するとぼやける件 非ratinaでもratina対応をすると案外キレイになるぞ。 でもまあ重いんだが。 多段階のαチャネル(半透明)の画像の描画が重い件 どのブラウザでも重いが、とくにFirefoxで重いらしい。諦めた方がよさそうだ。

nginxでlocalhostとしてアクセスをサーバーに転送する方法

Windowsにnginxをインストール 下記のDLページのstable版(Windows-1.2.7)をダウンロード http://nginx.org/en/download.html zipを展開し、適当なフォルダに置く nginxの設定ファイルの書き換え nginxの中の、nginx.confをエディタで開き、下記の記述を探す。 server {     listen       80;     server_name  localhost;     ... その最後に以下の記述を追加。これは、本物のサーバーに転送するための設定。 location /aaa {     proxy_pass http://www.xxxx.com/aaa; } ※"/aaa"は、転送したいパス名。 ※proxy_passは、転送先のURL ※上記2つのどちらも最後に"/"が無いのがミソ。 ちなみに、以下の記述で、ローカルPC内のd:\xxxxディレクトリに直結できる。 location /test {     alias d://xxxx; } nginxの開始 cmd.exeで、nginxがあるディレクトリまで行き、次のコマンドを実行 start nginx ブラウザでアクセスしてみる ブラウザを開く "http://localhost/aaa/..."というURLでアクセスし、本物のサーバーと同じレスポンスが返ってくることを確認してみよう。 nginxの終了 開始と同様にcmd.exeで、次のコマンドを実行 nginx -s stop

[Java]BufferedImageとピクセル操作

JavaのImage関連って思いの外複雑でびっくりした。 古の方法である配列によるピクセル操作をやりたいだけなのにすごく苦労したぞ。 PixelGrabberとか、MemoryImageSourceとかWritableRasterとかかなり迷走した挙句、以下のシンプルな方法に行き着いた。 public void sample() throws IOException { // PNG画像を読み込み BufferedImage img1 = ImageIO.read( new File("ebi02.png") ); int w = img1.getWidth(); int h = img1.getHeight(); // ピクセルを配列として取得 int[] px = img1.getRGB( 0,0, w, h, null, 0, w ); // グレースケール化 for( int i=0; i<px.length; i++ ) px[i] = toGray( px[i] ); // 新しいBufferedImageを作成し、ピクセルを配列でセット BufferedImage result = new BufferedImage( w, h, BufferedImage.TYPE_INT_RGB ); result.setRGB( 0,0, w, h, px, 0, w ); // BufferedImageをPNGとして保存 ImageIO.write( result, "png", new File("gray.png") ); } private int toGray( int argb ) { int a = (argb>>24) & 0xff; int r = (argb>>16) & 0xff; int g = (argb>>8 ) & 0xff; int b = (argb ) & 0xff; int avr = ( r + g + b ) / 3; int gray = avr & 0xff; return (...

Android・・・テキスト描画あれこれ, ascent(), descent()等

Androidのテキスト描画に必要なTipsをメモ。 存在に忘れがちな横方向のAlignや、意外に正解がわかりにくい縦方向のセンター合わせ等。 ascentとdescent Paint及びFontMetricsで取得可能なascentとdescent。 テキスト描画の原点となるbaselineから上方向の高さがascentで、下方向の高さがdescentとなる。 baselineを割ってdescent領域に入るのは例えば小文字の"j"等だ。 しかし理解しづらいのは、ascentが負の値であることだ。 これは、画面の座標系を思い浮かべてbaselineを(0,0)と考えるとイメージしやすい。 つまり、画面上にはみ出すascentが負、画面内に入るdescentが正、となる。 テキスト用Paintの作成 TextPaint tp = new TextPaint(); tp.setColor( Color.WHITE ); // アンチエイリアスON tp.setAntiAlias( true ); // 塗りつぶしのみ。STROKEを入れると太くなる。STROKEだけだと中抜き tp.setStyle( Style.FILL ); // テキストのフォントサイズ。Paintに直接指定する場合、Density等の考慮が必要。 tp.setTextSize( 11f * density ); 縦方向にセンター合わせ @Override protected void onDraw(Canvas canvas) { // 領域の高さ int areaHeight = getHeight(); FontMetrics fm = tp.getFontMetrics(); // フォントの高さを求める float fh = fm.descent - fm.ascent; // センター合わせにしたあと、Baselineの位置を求めるためにdescentを引く float ty = (areaHeight/2f) + (fh/2f) - fm.descent; canvas.drawText( "text", 0, ty, tp ); } 横方向に原点を右端で設定する...