読者です 読者をやめる 読者になる 読者になる

Groovyistからのステキなクリスマスプレセントだ #advent2011

groovy GroovyFX Grezi

みなさんクリスマスプレゼントはもらえた?
もらえた人も、もらえなかった人も、ここにいいモノがあるよ。


アイディアと情熱をもったGroovyistからのステキなクリスマスプレゼント。
ブログを読んだら、Groovyを読試したくなること間違いなし。


【Day 01】プログラミングGROOVYに書いてないけど、便利なGroovyプロダクト【Day 02】G*と言えば猫、ということで子猫Tube作りました【Day 03】LupinFX【Day 04】Groovyを野良ビルドしてみよう【Day 05】Spockでデータドリブンなテスト【Day 06】GrailsのプラグインリポジトリとしてGithubを使う【Day 07】Handy Gradle startup script【Day 08】Groovy Eclipse Pluginのあれこれ【Day 09】Gradleビルドランゲージリファレンス【Day 10】GroovyでVert.x【Day 11】resolveStrategy の基礎【Day 12】私がGroovyを好きな9つの理由 2011年版【Day 13】G5、それはGroovy使いの為のスライドショーツール【Day 14】grailsでwebアプリをつくってみる(つくってみた(手直しした))。【Day 15】Grailsをインタラクティブに使う!【Day 16】GroovyとQuartzとTwitter APIとTwitter4Jの甘い関係【Day 17】自分のPCにある写真をPicasa webに丸ごとアップ【Day 18】G*アドベンドカレンダー JGRの文法比較【Day 19】ドメインを取得しました【Day 20】groovyコマンドオプション一巡り【Day 21】恥ずかしくて今さら聞けない、GMongo講座 2【Day 22】Groovyの疑似デバッガgdb【Day 23】Grettyで割り勘計算機【Day 24】MerryChristmas!!【Day 25】groovyでTestNGのテストコードを書いてみよう



Groovyのイベントでは恒例(?)のイラストも

画:@



画:@ ]
うわっ、本家からも出た。





たぶん、明日も勝手に延長戦が始まったりするだろうけど、一旦まとめ。


JavaFXは、webkitベースの内蔵ブラウザがあるので、Greziを使って表示してみた。
来年の技評のAdvent Calendarの例に載るような綺麗な「まとめ」は、
Grails、Griffon、GwebGebとかを使って、きっとあの人たちから出るだろう。(/ω・\)チラッ @
epub化はきっとあの人だな。

動画

注意事項

  • 音声はなし。(クリスマスソングでも流せばよかった・・・)
  • 全体的に長い。(全文表示じゃなくて、さわりだけにしておけばよかった・・・)
  • 遅い(動作が遅いのは、6年前のPCで、録画までしてるので・・・)

「【Day 02】G*と言えば猫、ということで子猫Tube作りました」でGistのソースを表示するのに30秒ぐらいかかる。



最大化状態でズームアウトすると、ぬるぽで操作不能になるので、
Day 25 の表示後を、サイズを変えて撮り直した。。。




ソース

Greziに添付されてるサンプルの「Slideshows.grezi.groovy」ベースに作成した。

import javafx.scene.web.WebView


showGreziLogo = false



gAdeventCalednar = [
    'day01':['url':'http://d.hatena.ne.jp/kyon_mm/20111201/1322745407'
             ,'title':'【Day 01】\nプログラミングGROOVYに書いてないけど、\n便利なGroovyプロダクト'
             ,'twitterId':'@kyon_mm'
             ,'x':1600
             ,'y':400
             ]
             
   ,'day02':['url':'http://d.hatena.ne.jp/nobusue/20111201/1322755210'
            ,'title':'【Day 02】\nG*と言えば猫、\nということで子猫Tube作りました'
            ,'twitterId':'@nobusue'
            ,'x':1400
            ,'y':200
            ]
             
   ,'day03':['url':'http://d.hatena.ne.jp/ksky/20111203'
            ,'title':'【Day 03】\nLupinFX'
            ,'twitterId':'@kazuchika'
            ,'x':1000
            ,'y':200
            ]
            
   ,'day04':['url':'http://d.hatena.ne.jp/nobeans/20111204/1322990018'
             ,'title':'【Day 04】\nGroovyを野良ビルドしてみよう'
             ,'twitterId':'@nobeans'
             ,'x':400
             ,'y':400
             ]
             
   ,'day05':['url':'http://d.hatena.ne.jp/kiy0taka/20111205/1323096586'
             ,'title':'【Day 05】\nSpockでデータドリブンなテスト'
             ,'twitterId':'@kiy0taka'
             ,'x':200
             ,'y':600
             ]
             
   ,'day06':['url':'http://monochromeroad.blogspot.com/2011/12/grailsgithub.html'
             ,'title':'【Day 06】\nGrailsのプラグインリポジトリ\nとしてGithubを使う'
             ,'twitterId':'@literalice'
             ,'x':200
             ,'y':800
             ]
             
   ,'day07':['url':'http://d.hatena.ne.jp/masanobuimai/20111207#1323184521'
             ,'title':'【Day 07】\nHandy Gradle startup script'
             ,'twitterId':'@masanobuimai'
             ,'x':400
             ,'y':1000
             ]
             
   ,'day08':['url':'http://d.hatena.ne.jp/ikikko/20111208/1323355440'
             ,'title':'【Day 08】\nGroovy Eclipse \nPluginのあれこれ'
             ,'twitterId':'@ikikko'
             ,'x':600
             ,'y':1200
             ]
             
   ,'day09':['url':'http://d.hatena.ne.jp/nightmare_tim/20111208/1323377316'
             ,'title':'【Day 09】\nGradleビルド\nランゲージリファレンス'
             ,'twitterId':'@nightmare_tim'
             ,'x':1000
             ,'y':1200
             ]
             
   ,'day10':['url':'http://d.hatena.ne.jp/touchez_du_bois/20111210/1323514015'
             ,'title':'【Day 10】\nGroovyでVert.x'
             ,'twitterId':'@touchez_du_bois'
             ,'x':1400
             ,'y':1200
             ]
             
   ,'day11':['url':'http://d.hatena.ne.jp/bikisuke/20111211/1323615558'
             ,'title':'【Day 11】\nresolveStrategy の基礎'
             ,'twitterId':'@bikisuke'
             ,'x':1400
             ,'y':1000
             ]
             
   ,'day12':['url':'http://d.hatena.ne.jp/fumokmm/20111212/1323641207'
             ,'title':'【Day 12】\n私がGroovyを\n好きな9つの理由 2011年版'
             ,'twitterId':'@fumokmm'
             ,'x':1000
             ,'y':800
             ]
             
   ,'day13':['url':'http://nagaimasato-ja.blogspot.com/2011/12/g-advent-calendar121313-groovyg5-new-g5.html'
             ,'title':'【Day 13】\nG5、それはGroovy使いの為の\nスライドショーツール'
             ,'twitterId':'@nagai_masato'
             ,'x':1400
             ,'y':800
             ]
             
   ,'day14':['url':'http://tamata.xmldo.com/2011/12/214.html'
             ,'title':'【Day 14】\ngrailsでwebアプリを\nつくってみる(つくってみた(手直しした))。'
             ,'twitterId':'@tamatamatamata'
             ,'x':1800
             ,'y':800
             ]
             
   ,'day15':['url':'http://d.hatena.ne.jp/mottsnite/20111215/1323924066'
             ,'title':'【Day 15】\nGrailsを\nインタラクティブに使う!'
             ,'twitterId':'@tyama'
             ,'x':3400
             ,'y':400
             ]
             
   ,'day16':['url':'http://samuraism.jp/diary/2011/12/16/1323962040000.html'
             ,'title':'【Day 16】\nGroovyとQuartzと\nTwitter APIと\nTwitter4Jの甘い関係'
             ,'twitterId':'@yusukey'
             ,'x':2600
             ,'y':600
             ]
             
   ,'day17':['url':'http://d.hatena.ne.jp/nemo_kaz/20111216'
             ,'title':'【Day 17】\n自分のPCにある写真を\nPicasa webに丸ごとアップ'
             ,'twitterId':'@nemo_kaz'
             ,'x':3400
             ,'y':600
             ]
             
   ,'day18':['url':'http://blog.livedoor.jp/bbcafe_yuja/archives/1184436.html'
             ,'title':'【Day 18】\nJGRの文法比較'
             ,'twitterId':'@Boc963proguram'
             ,'x':4200
             ,'y':600
             ]
             
   ,'day19':['url':'http://d.hatena.ne.jp/ko1kun/20111219/1324306744'
             ,'title':'【Day 19】\nドメインを取得しました'
             ,'twitterId':'@ko1kun'
             ,'x':2800
             ,'y':800
             ]
             
   ,'day20':['url':'http://d.hatena.ne.jp/irof/20111220/p1'
             ,'title':'【Day 20】\ngroovyコマンドオプション一巡り'
             ,'twitterId':'@irof'
             ,'x':3400
             ,'y':800
             ]
             
   ,'day21':['url':'http://mikeneck.blogspot.com/2011/12/gmongo-2_21.html'
             ,'title':'【Day 21】\n恥ずかしくて\n今さら聞けない、GMongo講座 2'
             ,'twitterId':'@mike_neck'
             ,'x':4000
             ,'y':800
             ]
             
   ,'day22':['url':'http://d.hatena.ne.jp/uehaj/20111222'
             ,'title':'【Day 22】\nGroovyの疑似デバッガgdb'
             ,'twitterId':'@uehaj'
             ,'x':2600
             ,'y':1000
             ]
             
   ,'day23':['url':'http://d.hatena.ne.jp/toby55kij/20111223/1324568112'
             ,'title':'【Day 23】\nGrettyで割り勘計算機'
             ,'twitterId':'@toby55kij'
             ,'x':3400
             ,'y':1000
             ]
             
   ,'day24':['url':'http://d.hatena.ne.jp/orangeclover/20111224/1324715531'
             ,'title':'【Day 24】\nMerryChristmas!!'
             ,'twitterId':'@orange_clover'
             ,'x':4200
             ,'y':1000
             ]
             
   ,'day25':['url':'http://d.hatena.ne.jp/kimukou_26/20111225'
             ,'title':'【Day 25】\ngroovyでTestNGの\nテストコードを書いてみよう'
             ,'twitterId':'@kimukou_26'
             ,'x':3400
             ,'y':1200
             ]
]

def view = new WebView(layoutX: 30, layoutY: 30, visible: false, opacity: 0.0)

def switchWebWiew

map = {
    switchWebWiew = { event ->
        if (view.opacity == 0) {
            mapGroup.effect = boxBlur(width: 10, height: 10, iterations: 3)
            

            view.engine.load(gAdeventCalednar[event.source.id].url)

            view.visible = true
            view.requestFocus()
            
            timeline {
                at(900.ms) {
                    change(view, 'opacity') { to 0.8 }
                }
            }.play()
        } else {
            map.effect = null
            view.opacity = 0.0
            view.visible = false
            mapGroup.effect = boxBlur(width: 0, height:0, iterations: 0)
        }
    }

    gAdeventCalednar.each { k, v ->
        path << hbox(layoutX: v.x, layoutY: v.y, onMousePressed: focusOnNode) {
            label(font: '30pt', v.title + '\n' + v.twitterId)
            label(id: k, styleClass: 'start-label', 'ブログ', onMousePressed: switchWebWiew)
        }
    }


}

withScene = { scene ->
    scene.stylesheets.add("file:///${System.getProperty('user.dir')}/presentations/Slideshows/style.css".toString())

    scene.root.children.add(view)
    view.prefWidthProperty().bind(scene.widthProperty().subtract(60))
    view.prefHeightProperty().bind(scene.heightProperty().subtract(60))

    def label = label(styleClass: 'exit-label', 'exit', visible: bind { view.visible }, onMousePressed: switchWebWiew)
    scene.root.children.add(label)
}

実行方法

C:\usr\opt\grezi>gradle grezi -Ppresentation=.\presentations\gadvent2011\present2you\Present2you.grezi.groovy

問題点

ブログを表示してから、戻ったときに、ピントが合わない。
どうすればいいんだろうか。
あと、Slidshareの埋め込みHTMLは表示できたけど、Youtubeの埋め込みHTMLは表示できないようだ。
goovyist.jpのドメインは、(録画したときには)HTMLにcharsetが指定されてないから文字化けしてた。(これはしゃーないな)



JavaFXもGroovyFXも分からないまま、すっ飛ばして、Greziをいじってるので、
ハマると対処のしようがなかったりする。
それでも、Greziを使うと、最小限のコードで遊べてしまうので楽しい。




本編よりも作るのに時間がかったのだが、自分のブログが鬼門だった。
ソースコードの箇所を表示しようとすると、ぬるぽ・・・><。

java.lang.NullPointerException
        at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:116)
        at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:103)
        at com.sun.webpane.sg.prism.WCImageImpl.getTexture(WCImageImpl.java:120)
        at com.sun.webpane.sg.prism.WCGraphicsPrismContext.drawImage(WCGraphicsPrismContext.java:621)
        at com.sun.webpane.platform.graphics.GraphicsDecoder.drawImage(GraphicsDecoder.java:428)
        at com.sun.webpane.platform.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:171)
        at com.sun.webpane.platform.graphics.WCRenderQueue.decode(WCRenderQueue.java:72)
        at com.sun.webpane.platform.WebPage.paint2GC(WebPage.java:678)
        at com.sun.webpane.platform.WebPage.paint(WebPage.java:658)
        at com.sun.javafx.sg.prism.NGWebView.renderContent(NGWebView.java:71)
        at com.sun.javafx.sg.prism.NGNode.renderOpacity(NGNode.java:439)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:182)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:42)
        at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1131)
        at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:205)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:188)
        at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:42)
        at com.sun.javafx.sg.BaseNode.render(BaseNode.java:1131)
        at com.sun.javafx.tk.quantum.PaintRunnable.doPaint(PaintRunnable.java:217)
        at com.sun.javafx.tk.quantum.PaintRunnable.paintImpl(PaintRunnable.java:148)
        at com.sun.javafx.tk.quantum.PaintRunnable.run(PaintRunnable.java:329)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
        at com.sun.prism.render.RenderJob.run(RenderJob.java:29)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at com.sun.javafx.tk.quantum.QuantumRenderer$dRunnable.run(QuantumRenderer.java:67)
        at java.lang.Thread.run(Thread.java:722)

なんの設定がダメなんだろう。。。





添削歓迎

ここ間違ってるよ
こうした方がよくないか?
こういうことなんじゃないかな。
この環境だとこうなるよ
などなど
方法は、コメント、トラックバックはてブTwitter @orange_clover宛 で、お願いします。

















関谷 和愛、上原 潤二、須江 信洋、中野 靖治
価格: ¥ 3,360
価格は記載時点のものです。購入前にAmazonでご確認ください。





「プログラミングGROOVY」正誤表