2013年04月01日

女性の働き方とキャリアパスについて思うこと

かずひこさんのfacebookの投稿で知ったのですが、日本が先進国の中で女性の働きやすさワースト2になったそうです。まぁそうだよね、というのは色々なところから実感できます。@fumiさんのサムスンの話も読んで、考えさせられたのですが、日本は女性の労働力を生かしていないだけでなく、その影響で男性の労働力もぜんぜん活用できてなくて、どんどん弱体化していっているなぁ、というのを感じます。今まで漠然と考えてきたことをまとめてみました。

下積みを積んで管理職になるというキャリアパスについて

日本では、島耕作シリーズを読むまでもなく、平社員→課長→部長→・・・のようにステップアップして管理職になっていくのが当たり前のように言われています。でも、それって本当は不自然なんだろうな、と思います。プログラミングみたいな仕事を考えても、集中して勉強して知識を蓄えて・・・で、管理職になると仕事ががらっと変わります。プログラミングが得意な人でも、マネジメントが得意とは限りません。ただでさえ組織では無能な人で溢れかえるというのがピーターの法則ですが、あえて組織の武器になるものを放棄している状態です。戦士でレベル20にしたのにあえて商人に転職、みたいな。IT系とか大手でも「プログラミングで手を動かし続けるのは30代前半」「管理職を捨てて給料アップを放棄する以外に道はない」みたいな話をたまに聞きますし、僕が転職したのも生涯現役プログラマーでいたかったからです。

いつまでもエンジニアとしてスペシャリストの技能を磨きたいと思っていた時に、はっとさせられたことが2つありました。

ディレクターとマネージャー

僕が勝手に師匠と呼んでいるほりうち師匠が以前勉強会で発表されたという資料に、ディレクター(リーダー)とマネージャーという表現がありました。ディレクターはチームを「こっちを目指そう」と先導する人です。何にフォーカスすべきか、何をやらないかを決め、なにか余計なものがあれば「それはいらない」と捨てるのが仕事です。マネージャーは細かい仕事の取りこぼしがないか目を配るのが仕事です。タスクを減らす(余計なものを)、増やす(見落としていたのを追加する)という意味ではまったく正反対です。

日本では、これらの役割の違いを意識することはありません。今時な役職名をつけようとしているところでも適当にマネージャーと名乗っていてディレクションの仕事をしていたり、リーダーだけどマネジメントが仕事だったり、謎の和製英語のプロデューサーがあったり、謎です。

日本の女性に多いタイプ

もうひとつがめんたねで教えてもらった、岡田斗司夫さんの人生のトリセツです。人間にはいくつかのタイプがあり、得意なスキル、何が好きか、嫌いか、どういう価値が理解できないか、というのがあるというものです。「どういう価値が理解できないのか」というのには衝撃を受けました。頭では分かっても理解できないものがあるというのを意識したことがなかったからです。理解できないからこそ意識もしなかったのですが。岡田さんは自分で発想されたとのことでしたが、数千人だか数万人の人間のアンケートをとって作ったと言われている正確分析手法(名前忘れたけど)とほぼ同じ分類だったので、何かしらの参考にはされたのかな、と思っていますし、これに書かれている分析手法にはそれなりに信ぴょう性を感じています。

めんたねでは、オリジナルのSMマトリックスという性格分析手法を作っていて(それなりの人数の日本人をサンプリングしていて、日本人に特化した分類を作っています。日本人と欧米人では分散が大幅にことなっていて、日本人全体が1つのカテゴリーに入ってしまい、差が分析できないというのはよくきく話です。めんたねの分類では女性は「魅力ライン」という空気を読んだり、自分の願望を空気に含ませて伝えるようなことが得意な人が比較的多いとのこと。人生のトリセツで言うと王様タイプにまとまりますが、SMマトリックスでは、支配Mと服従Sの2パターンになります。もちろん、多いとはいっても100%ではないですし、男性でもこのタイプの人はいます。これについては後で触れます。

魅力ラインじゃないラインは、というと能力ラインです。比較可能な能力の差、チカラの差が人間の差であると考えるタイプです。僕もここです。現状のキャリアパスはどちらかというと能力ライン的な、能力の差や下積みの量(キャリア年数)を重視する傾向がありそうです。これは日本女性に多い魅力ラインの人たちにとっては不利ですし、さらに出産などでキャリアの中断がありえる女性からすると不公平とも言えます。

マネジメントが得意なのは女性?

続きを読む
posted by @shibukawa at 16:23 | TrackBack(0) | 日記 はてなブックマーク - 女性の働き方とキャリアパスについて思うこと

コミュニティに参加する上で最低限持っておくと良いもの

DSP 147: Thank You! 2007-10-11
taken by Bern Hart under CC BY-NC-SA

だいぶ前に「たのしい開発 スタートアップRuby」と「Pythonプロフェッショナルプログラミング」の献本をいただいておりました。ブログとか色々書くのが遅くなってすみません。4/1で、ちょうどスタートアップには良い時期だと思いますので、ブログエントリーを書きます。とは言え、細かい言語のことは書きません。あと、コミュニティ運営についても書きません。

これら本の良いところ

プログラムを書くということにはとても多くの活動が関わっています。具体的なモノの方が考えやすいと思うので、家を建てることに例えて考えてみると、どこに立てるか?家族構成は変化しそうか?どんな間取りにすればいいのか?予算はどうか?どこの会社に頼もうか?とかを考える必要があります。業務用の建造物なら、ビジネスとして成り立つか?採算は合いそうか?が大事です。

ソフトウェア開発も同じです。プログラムのソースコードを書くだけがソフトウェア開発ではありません。プログラミング言語を何にするか、データベースを何にするかなど、どれが最適かを選ぶ必要があります。より良い(性能とか修正のしやすさとかバグの少なさ)コードを書くのが大切ですし、そのためには勉強も必要です。仕事であれば、作る手間ができあがった成果よりも大きいとビジネスになりませんし、さまざまな人が関わってきてプロジェクトになっていくでしょう。趣味でも、時間が潤沢に使えるわけではないので、ある程度目標を定めて、フォーカスを集中する必要があるでしょう。

この2冊は双子のような本で「コードを書く」だけの部分だけではなく、貪欲にソフトウェアに関わる多くの項目を取り込んでいます。テストの仕方や継続的インテグレーションツールの導入などは共通しています。また、スタートアップRubyでは最後の章で、Pythonプロフェッショナルプログラミングでは最初のまえがきの企業の行動規範(著者はみな同じ会社なので)で「たのしさ」について語っています。

とは言え、一方は「スタートアップ」でもう一方は「プロフェッショナル」なので扱っている対象は微妙に違っていたりします。スタートアップRubyの方は、Rubyの基本文法から始まって、Railsを通じてコードの書き方を紹介しつつ、会社にどうやって働きかけて採用させていこうか?とか、勉強会を通じた勉強方法などを紹介しています。またRubyの文化やアジャイル開発についてもページをさいて説明しています。ゆるふわな雰囲気です。個人的にはRubyでは昔から咳プロダクツのファンなのでそっちの紹介もあればうれしかったですが、Rubyとは何かを学ぶ人には刺激が強すぎるかもしれませんね。

プロフェッショナルプログラミングの方は、.vimrcと.emacsの設定の仕方から始まり、Flask/Django/Google App Engineなどの開発を紹介しつつ、ドキュメンテーションや、分散バージョン管理、課題管理などを紹介しつつ、デプロイの自動化、パッケージ管理サーバを独自に立ててパッケージ管理みたいな、他の本で紹介されたのを見たことがないようなネタまで満載です。Python業界の専門用語ではこういうのを「毛深い」と言います。褒め言葉です。

もちろん、ページ数が無限につかえて、著者の時間が無限で、読者数と読者の財布と時間も無限であれば、全世界のソフトウェアのすべてのネタを100%網羅することはできるでしょうが、そういうわけにはいきません。どちらも、読者のステージにあったベストなものをピックアップして選んでくれています。どちらも学習していく上では良いマイルストーンとなってくれると思います。

このような本の著者になるために必要なこと

続きを読む
posted by @shibukawa at 13:45 | TrackBack(0) | 日記 はてなブックマーク - コミュニティに参加する上で最低限持っておくと良いもの

2013年03月30日

ゲーム用画像最適化ツール lightpng 1.0リリース

lenna_32i

昨年からちょこちょこコードを書いていて、たまに思い立ったように機能を追加していた画像最適化ツールのlightpngに1.0のタグを打ちました。だいたいやりたい機能は入ったかな、ということで。時間的にはこんな感じで進化してきました。

  • 2012/5/17: ファーストバージョン。pngを読み込んで16ビットに減色機能
  • 2012/6/14: クロスコンパイルでWindowsバイナリ生成
  • 2012/6/16: jpeg読み込み。
  • 2012/6/18: PVRTC/ATITCの生成。
  • 2012/7/30: libpng/zlibの圧縮オプションをブルートフォースで最適化
  • 2012/11/5: プレビューモード追加
  • 2012/11/28: Mac OS 10.8上でも10.6から動くバイナリが作れるようにビルドオプション変更
  • 2012/1/28: png最適化スキップ機能を追加
  • 2012/3/18: pngnqの256色化コード+パレット最適化のインデックスカラー画像生成機能追加
  • 2012/3/23: 16bitかつ256色コード生成機能を追加
  • 2012/3/24: Zopfli圧縮オプションを追加
  • 2012/3/25: 256色化をpngnqから生成後のサイズの小さいpngquantに変更
  • 2012/3/28: ドキュメントを修正して1.0タグを打った

なぜこのコマンドを作ったのか?

ngCoreというゲームエンジンがありまして、16ビット画像を使って使用するテクスチャメモリ半減!みたいな機能があったり、ATC/PVRの圧縮テクスチャが使えたりします。16ビットはpngとかjpegファイルを読み込んで末尾のビットを削って1ピクセル4バイトの情報を2バイトに押し込めます。当然そのまま削るとグラデーションがガタガタになったりうれしくないので、ディザリングをかけて見た目がおかしくならないようにする必要があります。

ATCの圧縮テクスチャ生成も、Windows用のコマンドラインツールはあるんですが、Mac用が見当たらなかったというのもあります。PVRも、Macのtexturetoolと同じ形式(古いPVR v2形式)で画像を出力するコマンドラインツールがWindowsで見つからなかったり。Android/iOSの両対応のゲームを開発する&WindowsでもMacでも!という場合は、それぞれ足りないツールを補完する必要がありますよね。まだ試してませんが(たぶん動く)、Linuxでも動けば、Jenkinsで継続的インテグレーションで画像ファイル変換とかもできるようになるはず。

圧縮テクスチャはメモリサイズが1/4になったり1/8になったりパフォーマンスも向上したりといいことが多いのですが、圧縮のしすぎで細部のディティールが悪化したりします。特に圧縮率の高いPVRTC。PVRTCがVQと呼ばれていたDreamcastで使われていたPowerVR2時代でも、キャラクタの顔に使うのをデザイナーさんが嫌がったり、ということがあったとか。エッジがはっきりしたUI画像とか文字とかもPVRTCは厳しいです(特にアルファ値を使うケース)。そういう時には16ビットのpngは有力な選択肢になります。

このあたりは最初の1〜2ヶ月で完了し、後はファイルサイズ縮小の追求ですね。pngはマニア向けなフォーマットで、圧縮オプションしだいでファイルサイズが微妙に変わったりします。最適化してもzlibの内部の辞書情報の最適化なので展開速度は全然変わらないはず(展開時のメモリ使用料は制御可能)。クオリティが微妙に変わっても良ければさらに大胆にファイルサイズを削れます。

10%でもファイルサイズが減れば、ブラウザゲームのレスポンスは上がるし、apkとかappファイルにそれだけ多くのコンテンツを入れられるようになります。何かをしながら過ぎている10分よりも、何もしない10分の方が苦痛が数倍だったりすることを考えれば、Google PlayとかAppStoreからのダウンロードは他のことをしながらバックグラウンドでできるけど、ゲーム起動後の追加ダウンロードで待たせるのは、ユーザさんからすれば何もできない待ち時間なので苦痛が数倍です。このツールを使って、少しでもインターネットを通じて世界をより良くしよう、ズッ友だよ!ということです。

フィードバックもpull-requestも評判も反応もまったくないけど、地味で誰もやりたがらないことを地道にやるのが大事ですよね。

現状の結果

続きを読む
posted by @shibukawa at 01:51 | TrackBack(0) | 日記 はてなブックマーク - ゲーム用画像最適化ツール lightpng 1.0リリース

2013年02月22日

PythonのPyPIのパッケージ数がPerlのCPANを抜いた日

Screen shot 2011-02-20 at 7.52.00

2011年2月ごろのスクリーンショットです。

いつの間にかPythonの方がパッケージ数が多くなってました。荒い結果ですが、archive.orgを見ると、2012年12月23日のPyPIの記録が26444で、2012年12月22日のCPANの記録が26438なので、12月中に抜いたっぽいですね。過去のエントリーでは2014年ぐらいかな、と思っていましたが、1年ほど早かったです。

大雑把な経緯はこんな感じ。Perlはmodulesとdistributionsという2つの数字が書いてあって、distributionsの数が配布物の数っぽいのですが、過去のページにはmodulesしか書かれてないので、昔の状況は不明です。

日時PyPICPAN
2007年12月3200不明
2010年6月10000不明
2011年2月1330019300
2012年12月2640026400
2013年2月2820026800

抜かれたとはいっても、Perlも過去2年で7000ぐらい数を増やしてきているわけだし、まだまだアクティブです。僕もお世話になりましたが、アップロードされているソースコードを読んでアルゴリズムの勉強をさせてもらったり、価値の高さは健在です。歴史がある分、ハッカーな人も多くてレベルが高いイメージです。ちょっと前に「エンジニアならgithubのアカウントでソーシャルコーディングで」みたいなバズワードが流行ってましたが、20世紀からsourceforge.netのアカウント持っている人の方が断然オーラを感じるぜ、的な。

そして、PythonもPerlを抜いたとはいえ、その立場すでに脅かされています。node.jsのパッケージのnpmです。Google Trendsで見ると、2010年8月ぐらいにできたばかりかな、というところですが、すでに23300。ここ1ヶ月でも1500ぐらい数を伸ばしていますし、ペースはPythonの倍近いです。僕もいくつかnpmに載せようかな、と思っているものがあるので、何個か貢献はしますが、それとは関係なく今年中にPythonを超える勢いです。emscriptenで、Qtがブラウザ上で動いたらしいと会社で噂話をしていたのを小耳に挟んだりもしましたが、JavaScriptの勢いは凄まじいですね。CoffeeScriptみたいなJS系言語もnpmを使っていたりしているのも他の言語よりも有利かな、とも思いますが、想像以上でした。

posted by @shibukawa at 16:39 | TrackBack(0) | 日記 はてなブックマーク - PythonのPyPIのパッケージ数がPerlのCPANを抜いた日

[JSX][FM-index]httpstatus コマンドで、HTTP のステータスコードをすばやくしらべる!

一般的な Web Programmer ならば、HTTP Status code はすべて暗記していると聞きました。

しかし、僕は初心者なので、なかなか覚えきれていないので、HTTPのステータスコードをさがすのに便利なツールを用意しました。httpstatusです。インストールはJSX(npm install jsx)とgitが使える環境で:

    $ git clone https://github.com/shibukawa/oktavia
    $ cd oktavia
    $ make

です。使い方はコマンドの後ろに検索ワードを書けばいいのですが、Googleの検索と同じようなクエリーも少しだけサポートしています。本当はダブルクオーテーションでくくるとそのフレーズを完全に含む検索もいれたかったのですが、JSXにパラメータが渡ってくる時点でダブルクオーテーションが消えてしまうので判別が不能・・・

    $ ./httpstatus ok           #okを含む行
    200: OK
    $ ./httpstatus 40 -not   #40を含むけどnotを含まないステータス
    400: Bad Request
    401: Unauthorized
    402: Payment Required
    403: Forbidden
    407: Proxy Authentication Required
    408: Request Timeout
    409: Conflict
    $ ./httpstatus ok OR not # okかnotのどちらかを含むステータス
    200: OK
    406: Not Acceptable
    405: Method Not Allowed
    510: Not Extended
    404: Not Found
    501: Not Implemented
    304: Not Modified
    416: Request Range Not Satisfiable
    505: HTTP Version Not Supported

オプションなしで実行すると、すべてのステータスの一覧とともに、今日のあなたの運勢にピッタリなステータスコードを1つピックアップして表示してくれます。僕の今日の運勢は「Today's status: 503: Service Unavailable」でした。

JSXというエラーを見つけてくれて、JavaScriptよりもデバッグがラクな言語で書きました。JSも生成できます。ちょっとソースコードは長くなっちゃったので、割愛しますが(github参照)、言い訳をすると、もともとJSXでFM-indexを使った全文検索エンジンを作っていまして、これもそれを内部で利用しています。

FM-indexは日本に出張中に買ってみた高速文字列解析の世界という本で紹介されていた検索のアルゴリズムです。圧縮インデックスを使った全文検索です。転置インデックスを使う方式と違って、検索するだけならキーワードに分割しておく必要がありません。そもそもキーワード分割の難易度が高く、10MBだかの辞書を装備したMeCabさんに協力してもらわないと満足に分割もできない日本語だと、ブラウザ上でちょろっと精度よく分割というのは難しかったりします。それをしなくてもよい!しかも2-gram, 3-gramとかと違ってインデックスが圧縮されていて小さいですし、一文字でもマッチさせられます。また、圧縮されているインデックスから元の文章を復元できます。ドキュメントツールのSphinxだと、検索後のページサンプル表示に、元のソースのテキスト(.txtとしてアップされている)を利用します。これだと、翻訳機能と相性が悪い(元のソースは別言語)し、ソースをエクスポートする機能を有効にしないと検索機能が弱くなるという欠点があります。FM-indexならその部分も解消できる!まさに、Sphinxのブラウザ上で動く検索エンジンのためのアルゴリズムといえます。FM-indexに関してウェブで読める記事としては@echizen_tmさんこの解説が分かりやすいですが、ちょっとまだ完全に理解できてない部分もあってまだまだコードを書きながら勉強中です。

現在は@echizen_tmさんのShellinfordをベースにいろいろ改造中です。Shellinfordの場合は、ドキュメントという区切りの情報を持てて、検索結果ではドキュメントのインデックスを返したり、インデックスを使って元のドキュメントのコンテンツを復元できるようになっていましたが、Oktaviaではこの部分をいろいろなケースに対応できるように自由に情報を付与できるように拡張しています。以下の4パターンを実装しています。Table以外は組み合わせて利用できます。今回はSplitterを利用して、行ごとに検索結果をマージして出すようにしています。

  • Section: 名前付きのセクション。ドキュメント、タイトルの入ったセクションで利用することを想定
  • Splitter: 名前なしのセクション。行番号、パラグラフ、分かち書きの単語区切りなどで利用することを想定
  • Block: 名前つきのブロック。サンプルコードの箇所など、特定の範囲(スタートとエンドがある)を表すのを想定
  • Table: CSVとかTSVみたいなデータで使うのを想定。row/column情報を返すことができる

現在はJSX実装のみですが、Sphinxに組み込んで使えたらいいな、ということでPython版も作りたいと思っています。

検索エンジンの作業の進捗としては、FM-indexのコア部分は動くようになっていて(@echizen_tmさんのFM-index紹介記事で書かれている線形探索な問題は今後修正が必要)、Snowballという由緒正しきステミングアルゴリズムに関連するツールのソースコードジェネレータを改造して、JSX版Python版をそれぞれ生成できるようにしたのと、HTMLのパース用にJSのSAXParserをJSXに移植したり、node.js用のgetoptをJSXに移植したり、といった段階です。今はインデックス生成ツールをぼちぼち作成している段階です。クエリーのパーサ、スコア計算部分も追加して、最終的には、ブラウザで動く全文検索エンジンとして、Webサイトに簡単に組み込める部品っぽい形式でリリースしようと思っています。あとはインデックスを中間形式でSQLiteか何かにいれて、部分的なインデックスの更新をできるようにして、ExpressとかDjangoとかからサーバサイドの簡易全文検索ツールとしても使えるようにしてもいいな、とか。今回はhttpstatusというビッグウェーブに乗っかるために、急遽クエリーの簡易パーサだけ作って動くようにしたものです。最終形とはいろいろ異なると思います。まだまだアルファ版です。

posted by @shibukawa at 01:54 | TrackBack(0) | 日記 はてなブックマーク - [JSX][FM-index]httpstatus コマンドで、HTTP のステータスコードをすばやくしらべる!

2013年01月02日

メディアの使い分け

Screen Shot 2013-01-01 at 9.11.46 AM

嫁によくいろいろ使えるね、と言われたので、飲みながらGoogle Driveで作った図がこれ。子供写真を喜んでLikeしてくれる人は主にPathとFacebookにいるので、子供写真はなるべくiPhoneで撮って、Path経由でFacebookに。TOLOTも試しで2冊ほどつくってみたので(日本国内に発送したので実物は見てない)、よさそうなら、D3100→TOLOTという経路もできる予定。

英語の情報発信を足したいところ。blog.shibu.jpは日本語で大分記事を書いているので、違うURLが欲しいかな。どこかの渋谷さん、shibu.com解放してくれないかな・・・

posted by @shibukawa at 02:19 | TrackBack(0) | 日記 はてなブックマーク - メディアの使い分け

2012年12月31日

魔法少女まどか☆マギカと英語

Untitled

なぜか子供の出産祝いということでまどか☆マギカのリミテッド・エディションの1が送られてきて(@ytakeuchさんありがとうございます!)、見たら勢いで2、3と全部買って、1年9ヶ月遅れでシブカワ家にもまどか☆マギカブームが来ました。日本と違って、1本に4話入り、BDとDVDが両方+サントラも付いてきて$80。日本だと5〜6000円ぐらいで6本(1本に2話入り)なので、アメリカの方が安いかな。オーディオコメンタリーはついてないです。魔法少女同士が日常生活的に仲良くしている絵のポスター(本編では存在しない、嫁曰く妄想ポスター)とか、ポストカードとかおまけもいろいろ付いてました。

ちょっと前にウェブで見た記事「「魔法少女まどか☆マギカ」なぜ避けて来たのだろう」は非常によく理解できます。個人的には萌えはあるけど中身はないものには興味がないので、見た目でちょっと敬遠してました。でも、その後文化庁のメディア芸術祭で大賞をとったりしていたので、ちょっと興味を持ちました。

昔、「CMでボディーブレードが出てたよ!見に行こう!」と大学のサークルの後輩と一緒にしょーもない理由でクレヨンしんちゃんの映画を見に行って(当時部室でボディーブレードがちょっと流行っていた)、おもいがけずにいい話でびっくりしたら、その後その映画も文化庁の賞を受賞した、ということもありました。メディア芸術祭で戦闘妖精雪風のOVAを見て、その後はまって小説を買えるだけ買って読んだり、その賞が選ぶものと、自分の感性と合いそうな感じがしたのがその理由です。ただ、その後は渡米準備とかもろもろがあって、日本にいる時にはまどか☆マギカを見るチャンスがありませんでした。

今年は映画とかを映画館で見たり、BDやDVDを買ったりといろいろしているけど、これが一番良かったです。シリアスなファンタジー。これと比べるとダークナイトもダークじゃないですね。 嫁と一緒に2周見て、今3周目ですが、想像以上に良かったです。主人公が5人組というガンダムWを思い出すけど、こちらは4クールで、5人の全組み合わせ(10組)でペアの場面があって、見せ場をがんばっていっぱい作っている感があったけど、まどか☆マギカはストーリーに一切贅肉がない。とらドラ!もパズルのようだ、と思ったけど(当時はとらドラ!は数学と呼ばれていた)こちらは1クール作品ということもあって、さらにシンプルで化学式みたいでした。 すでに色々情報が出きっているので今更ネタバレがどうのというのは心配することもないかもしれないけど、まぁ詳細についてはぜひご覧ください、ということにしておきます。

アメリカ版のBD/DVDには、英語音声と、日本語音声+英語字幕の2パターン選べます。英語音声+英語字幕という組み合わせはできません。英語版の声優さんも、日本語版の声優と雰囲気がすごい近くてびっくり。セガのソニック並のクオリティ。

Untitled

英訳のマンガもすごかった

続きを読む
posted by @shibukawa at 20:08 | TrackBack(0) | 日記 はてなブックマーク - 魔法少女まどか☆マギカと英語

2012年振り返り〜ソニックグッズ〜

DSC_0331

アメリカ赴任で何が一番楽しみだったかって、ソニックグッズが日本よりもいっぱい売っていることですよ。ソニックが日本発のキャラクターなのに、日本人にすら「アメリカのキャラでしょ?」と言われたりもすることもあるぐらいなので(それだけ日本離れしたクールなキャラという立ち位置がきちんと成立しているということなんだと思います)、日本ではあまり手に入らなかったり・・・数日前に、ジョイポリスで海外のグッズも売られるようになったと中の人がつぶやいていましたが、それだけアメリカの方が充実しています。

まずは、フィギュアとかもろもろ。2011年のソニックジェネレーションズでは、新旧のソニックが共演というコンセプトだったので、目が緑の新ソニックも、目が黒の旧ソニックも、フィギュアがいろいろ販売されてました。本当はもう1つ、新旧ソニックが一緒に走っているフィギュアを会社に置いてきてます。あと、モノポリーとか、神経衰弱(レアキャラもいるよ!)なども。興味深いのはトイザらス限定(ToysRus exclusive)な商品がいくつもあったことですね。一番右はパーティー用の紙ナプキンです。ラジコンとか、コースつきのプルバック式の車のフィギュアなど、未購入なのもたくさんあります。

DSC_0333

次はぬいぐるみとか。できのいいものも、わるいものも、いっぱい売ってます。こっちも新旧いろいろ。でかいシャドウのぬいぐるみのクオリティがとてつもなく高いです。奥のシャドウのクッションは誰かが誕生日のプレゼントで送って下さったのですが、どなたでしょう?下の目が入っている方のソニック帽子は@vestige_さんからのプレゼントです。メロン熊は帽子が潰れないように置いただけですので、ソニックキャラではありません。

DSC_0334

Tシャツもたくさん売ってます。SEARS、TARGET、J.C.Pennyなどの量販店を覗くとだいたい何枚か置いてあります。ゲームキャラの中では、マリオ系、Angry Birdsと並んでトップ3に入る感じです。ベビー服は会社の方々からお祝いでいただきました。真ん中の手描き風のがお気に入り。

DSC_0336

こちらもシャツ系。ウェアホッグとかマニアすぎるチョイス。1枚並べ忘れたけど、それにはブレイズが・・・嫁がエミー好きなのですが、エミーが描かれているTシャツはほとんど売ってないです。女の子向けのキャラクタはハローキティ一人勝ち状態なので、ぜひセガ・オブ・アメリカには頑張ってもらって、女の子用のアパレルコーナーにも切り込んでいっていただきたいです。あと、3月のCrush 40ライブのTシャツも(ライブには行ってないけど)ゲットできました!経路は秘密です!右上の15周年Tシャツは、元セガの方からいただきました。

そろそろ、暗黒の騎士のランスロットのフィギュアとかが出てくるらしい・・・日本では今まで出ていて、海外で逆に手に入りにくかったソニックの音楽CDも、iTunesで配信が始まったりして、アメリカのソニックファンはますますハッピーですね。このペースで増え続けると、ちょっと収納がやばいです。

posted by @shibukawa at 16:42 | TrackBack(0) | 日記 はてなブックマーク - 2012年振り返り〜ソニックグッズ〜

「名前っていうのは一生残るもんなんだ」

DSC_0173

この記事の中に、クレヨンしんちゃんのとうちゃんの言葉(表題のやつ)が書いてありました。名前は、人と人が接する時に使われる「道具」です。プログラマーなら誰しも、名前の重要さを知っています。うちも、今年娘を授かったのでいろいろ考えて決めました。うちの子の名前を決めたのは生まれる4ヶ月ぐらい前だったと思います。名前が決まっていると、お腹の中にいるときも親しみがわきますね。

うちの子の名前を決めるときに重要視したのが「外国の人(英語圏の人)にも通じやすい名前」です。今の時代、海外と接点を持つのはすごく簡単です。メールでもなんでも、国内とやりとりするのと変わらないコストで海外とやりとりできます。アメリカ生まれでアメリカ国籍も持っていることだし、将来海外相手に仕事するようなことも当然ありえることですしね。これは、僕のファミリーネームの「シブカワ」が外国人にとって発音しにくい事この上ないので、特にシブカワ家の場合は切実です。日本人名としても通じる名前。外国人にも親しんでもらいやすい名前にするためには、このあたりを意識すればいいのかな、と考えました。

  • オノマトペ・言葉としての発音のしやすさ
  • 綴りの互換性(ローマ字表記と英語表記が同じか?)
  • 発音の互換性(ローマ字表記の読み方)
  • 性別の互換性

オノマトペ・言葉としての発音のしやすさ

発音のしやすさの大切さついて教えてくれたのは@uupaaさんです。名前は声に出して読まれるものです。発音しやすさは親しみやすさにつながります。呼びやすい名前の方が声をかけやすいですよね?オノマトペの本などを参考にすると良いらしいです。僕はそれは読まなかったのですが、今習っている英語の先生に名前を見てもらって、発音しやすさを確認してもらいました。

知り合いから教えてもらったエピソードとしては、「カズオ」という名前の人が海外の人と結婚したのですが、相手の両親がどうしても「カズオ」と発音できず、「クズ男」になってしまうという・・・

綴りの互換性(ローマ字表記と英語表記が同じか?)

パスポート、クレジットカード、会社のメールアドレスなど、名前のローマ字表記はいろいろなところで使われます。例えば、ジョージという名前があったとします。日本でも譲治、みたいに普通に使われる名前出し、アメリカでも初代大統領の名前だったりします。当然、英語圏の人から親しみのある名前です。でも、日本語のローマ字表記はjojiで、英語名だとgeorgeですよね。リサも英語だとLisaで、ローマ字だとRisa。日本人を悩ますRとL問題がここにも・・・

発音の互換性(ローマ字表記の読み方)

サラ(Sara)はセーラとも読めます。同じ綴りでも、ちょっと違う読み方をされることがあります。

性別の互換性

例えばケイトという名前があったとします。日本人の場合は男の子の名前。アメリカ人は女の子の名前と考えます。性別が逆転しちゃってますね。まぁ、同じ名前が男性、女性の両方に使われるケースは英語の中にも結構ありますけど・・・周りを見ても、クリスとか、ジェシーとか。

これらを全部を満足させるのはなかなか難しいし、男の子の場合はさらに選択肢が狭いという問題はありますので、この中から重要だと思うものをいくつか選んで、それに合致する名前を決める必要があるでしょう。うちは発音は日米で一致しないけど、綴りと性別が日米で一致する名前にしました。 もちろん、ミドルネームを使う方法もあったり、ローマ字じゃない綴りを使う方法もありますが、手続き上いろいろ不便がありそうなので、子供が書類手続きで苦労しないように、ローマ字綴りがそのまま使えるようにしました。

日本人名としてもそのまま使う名前なので漢字もあります。漢字の読みはちょい変則的ではあるけど、他の読み方がしにくい表記だし、辞書に乗っている漢字の音・訓の読みから大きく外れてはないので、キラキラではないです。

両親も気に入っているし、娘も将来きっと気に入ってくれるはずと思っています。

posted by @shibukawa at 04:52 | TrackBack(0) | 日記 はてなブックマーク - 「名前っていうのは一生残るもんなんだ」

2012年12月30日

何のために勉強会をするのか?

Brunel University student study group
By Brunel University under CC BY-NC-SA

Shin x blog 勉強会なんてやらなくても良いという記事がちょっと注目を集めていました。かれこれ10年ぐらい勉強会を開催したり、3年前と去年には勉強会とかコミュニティの本を出したり、僕もそれなりに頭を悩ませた経験がある方かと思うので、僕なりの現在の考えをまとめてみます。勉強会に悩む人の一助になれば、と思います。

参考文献

自分がすごいと思っているものの存在を広めたい

続きを読む
posted by @shibukawa at 08:16 | TrackBack(0) | 日記 はてなブックマーク - 何のために勉強会をするのか?

2012年12月25日

ベジタリアンも感謝祭・クリスマスできるアメリカ

DSC_0541

アメリカでは、感謝祭を筆頭として、お祝いの場では七面鳥とか、巨大なスパイラルハムとかが食卓に並びます。その一方、日本だとヒンズー教やイスラム教の人が来ると店探しに相当苦労しますが(同時に来て店を探したこともありますが)、ベジタリアンが一定数いて、どのレストランに行ってもたいていベジタリアンメニューがあったりして、肉がダメ/牛がダメ/豚がダメという宗教・習慣上食べられないものがある人でもなんとかなるのがアメリカです。ベジタリアン向けのターキーっぽいものも売ってたりします。Tofurkyという、会社の製品です。ここ以外にも、Trader Joe'sが自社ブランドでも出してたりします。

上記の写真は、オーブンで調理中の図ですが、足のない七面鳥な雰囲気です。醤油とオリーブオイルでタレを作って、それをかけて野菜と一緒にオーブンで1時間半ほど温めるだけ。中には七面鳥の足っぽいものが付いているものもあるらしいです。グレービーという名の別物のソースもついてきます。本来は肉汁で作るのですが、これはパンの塊が入っていたりして(温めると崩れてとろとろになる)、ベジタリア仕様です。

DSC_0543

できあがりはこんな感じ。中には最初から詰め物っぽいものもされてたりして、七面鳥風です。味もかなり肉っぽい。食感はかまぼこみたいです。そんなに悪くないです。うちは嫁が鶏肉が嫌いなのでこれを買ってみましたが、なかなかおもしろい経験です。

DSC_0547

嫁が授乳中なので、乾杯はシャンパン風の炭酸ぶどうジュース。白ワインでも使われるシャルドネ100%で作られているみたい。炭酸弱めなのでぽんっとは抜けないのですが、それっぽい雰囲気がばっちり味わえます。

DSC_0556

デザートはpecan nutsのパイと、Eggnog。オトナはEggnogにラム酒をちょっと混ぜて楽しみます。Eggnogも定番の飲み物らしく、昨日にTrader Joe'sに行った時はEggnogの棚が空になってました。pecan nutsのパイは脅威的な甘さですね。これに関しては日本のケーキの方がいいかも・・・食べ物の多様性はアメリカの方が便利なことが多いですね。宗教上の理由だけでなく、周りの人の子がアレルギー持ちが多いし、日本でももっと食べ物の選択肢(料理ではなく原料の)が増えるといいなぁ、といろんな宗教の人と仕事するようになったり、子供の親になって強く思います。

日本ではケンタッキーとかコンビニとかデパ地下とかスーパーが大々的に宣伝していますが、鶏肉は人数が少なくてターキーでは大きすぎる場合の代替品。アメリカでは値段もターキーの方が安いですね。100g10円ぐらいだったか・・・それがプライマリーのような感じで行動する日本人はアメリカの人から奇異な目で見られます。「年越しで手打ち蕎麦食べに行きたかったけど、お店いっぱいだったからカップ麺でごまかそうテヘ」ぐらいの感じなので、アメリカ人女性を口説く予定の男性、もしくはその逆の方は要注意です。

posted by @shibukawa at 15:32 | TrackBack(0) | 日記 はてなブックマーク - ベジタリアンも感謝祭・クリスマスできるアメリカ

2012年12月23日

Python温泉に行って本を書いた話

つまみぐい勉強法売れています!

写真は出た直後の写真です。もう2年半も経つのでさすがに平積みはもうしてないですし、他の本と比べてバカ売れで底が見えそう、なのも今はないと思います。はい。

PySpaアドベントカレンダーに混ぜてもらいました。アメリカはまだ23日ですが、(JSTの)24日のエントリーとして参加します。

Python温泉に初めて行ったのは第4回だかなんだかで、当時はもう芳泉閣になっていて、必ず雨に降られるという点も含めてすでに恒例行事な雰囲気でした。Python温泉に参加した後につまみぐい勉強法という本を書いたのですが、この本でもPython温泉で学んだことが含まれています。Python温泉は勉強会のカテゴリのイベントの一つとして見てもなかなか面白いものがあります。このあたりを軽く紹介しようと思います。

勉強会としてのPython温泉

続きを読む
posted by @shibukawa at 15:30 | TrackBack(0) | 日記 はてなブックマーク - Python温泉に行って本を書いた話

2012年12月15日

Qt+JS: Mac OS Xについての注意点

MacはOSのバージョン間での互換がいろいろクセがあるので、古いバージョンで使っていた方法がそのまま他の方法で使えるとは限りません。

バイナリ配布版+10.6, 10.7

10.6, 10.7はそれほど苦労はないと思います。バイナリ配布されているQtと、XCodeのコマンドラインツールのgcc(4.2, Apple版)を使っておけば問題はないはずです。

バイナリ配布版+10.8

clangを使わないとビルドできないです。QtCreaterを使っている場合は、ツールチェーンをClangにしてください。コマンドラインからQMakeでビルドする際は次のオプションが必要となります。ちなみに、Qt 5系はいろいろトライしていますが、QtScriptバインディングがビルドできません。内部のプライベートなクラスがいろいろ変わっていたりしますが、その部分は解消して、ヘッダをパースしてC++を出すコードの基本部分は対応できました。ただし、生成したコードはまだビルドできないです。コードジェネレータ部分(文字列操作周り)をいじる必要がありそうです。

# Qt 4系
qmake -spec unsupported/macx-clang
# Qt 5系
qmake -spec macx-clang

MacPorts版

MacPortsの中に入っているqmakeがOS設定を知っているっぽいので、とくに-specを追加する必要はありません。

QtScriptバインディングビルド時の環境変数

QtScriptのバインディングをビルドするときは、それぞれ環境変数を追加する必要があります。デフォルトのインストール先に入れた場合の各設定を紹介します。

# Qt5用(ただしまだ成功してない)
export QTDIR=~/Qt5.0.0-rc2/5.0.0-rc2/clang_64/
export PATH=$QTDIR/bin:$PATH
# Qt4系 4.7, 4.8確認済み
export QTDIR=~/QtSDK/Desktop/Qt/4.8.1/gcc/
export PATH=$QTDIR/bin:$PATH
# MacPorts版
export QTDIR=/opt/local/
export PATH=$QTDIR/bin:$PATH

OSバージョン判定シェルスクリプト

sw_versというコマンドラインのコマンドがバージョン番号を文字列で返してくれます。これを使うとバージョンごとに処理を分けることもできそうです。

if expr `sw_vers -productVersion` : "10.8.*" > /dev/null; then
    # 10.8の時のコード
else
    # それ以外のコード
fi

どの環境も、デフォルトではコンパイルしたバージョン以上のOSでしか動かないバイナリを作ると思います。Macではアプリを古いOS向けにビルドするには、リンク時に次のオプションが必要となります。

-mmacosx-version-min=10.6
posted by @shibukawa at 03:33 | TrackBack(0) | 日記 はてなブックマーク - Qt+JS: Mac OS Xについての注意点

2012年12月12日

Qt+JS: コンテナウィジェットの使い方

Qt+JS: QtDesignerによるレイアウト(2)のラストで、コンテナウィジェットのレイアウトについて簡単に紹介しました。これ以外のコンテナウィジェットの注意点を軽く紹介します。

オブジェクトの取得方法

Screen Shot 2012-12-13 at 1.42.32 AM

上記のようなスクロールエリアを置いたとします。このウィジェットの直下にscrollAreaWidgetContentsというオブジェクトがいます。きっとこいつにこの名前でアクセスすれば子供が得られるに違いない!と思うと失敗するのがいやらしいところです。ルートがthis.widgetに格納されているとすると、次のようにアクセスします。

this.pushButton = detail.scrollArea.widget().pushButton;

widget()メソッドを使うと、直下の子供が得られます。それでは次のケースはどうでしょうか?

Screen Shot 2012-12-13 at 1.43.31 AM

これもほぼ一緒です。widget()メソッドに数値でページ番号(ゼロスタート)を渡すとオブジェクトが得られます。コンテナ自身がユーザの操作を受けて反応はしますが、中の子供からすると、特に特別な実装を子供がしなければならないことはありません。QWidgetやQFrameが親の場合と大差ありません。

this.pushButton = detail.tabWidget.widget(0).pushButton;

タブの名前を変更する

Screen Shot 2012-12-13 at 1.44.50 AM

レイアウトを操作するときは、親のQTabWidgetなどを選択して変更すると以前に紹介しましたが、タブの名前も同じです。親のQTabWidgetを選択します。QtDesignerのプロパティシートの最下部にQTabWidgetの設定があります。ここで現在のページに関する項目も並んでいるので、タブ名やオブジェクト名(使いませんが)を選択できます。

posted by @shibukawa at 23:59 | TrackBack(0) | 日記 はてなブックマーク - Qt+JS: コンテナウィジェットの使い方

Sphinx-Users.jpを作った時のお話

Scrabble game
taken by jcolman under CC BY-NC-SA

缶切りでツナ缶を開けようとしたら、缶切りの方が耐久度が低くて壊れたり、パン粉を作るためにプラスチック製のおろし金でパンをすりおろしたら、おろし金の方が削られてツルツルになってしまうような修羅の国アメリカで仕事しています。

僕が日本にいたときに設立したSphinx-Users.jpは代表が変わったあともMLで活発な議論が行われたり、イベントが定期開催されたり、うまく離陸して活動が継続しています。また、当初のもくろみ通りに、単にツールの使い方だけではなく、ドキュメントとは何か?どう書くべきか?ということを考えて発表してくれる人も増えています。

Sphinxのアドベントカレンダーということで、コミュニティについて話をします。easy_installしましょうとかは書きません。Sphinx-Users.jpを作る上で考えたことを思い出しながら書いてみます。

  • 2009/04: Vに勧められてSphinxを触り始めて気に入りドキュメントを翻訳
  • 2009/09: ドメイン取得
  • 2009/11: Sphinx-Users.jpのMLにミッション・ステートメントを決めようとメールを投稿
  • 2010/01: 清水川さんがエキスパートPythonの目次だけSphinxで日本語訳を作って公開したらはてブが400を超えて翻訳が決まる事件
  • 2010/02: 毎月第二火曜日PM10:00から1時間のスタッフミーティング開始
  • 2010/07: 集まってオフ会しましょうかと思ったら、偶然その日に1.0がリリースされて急遽世界最速リリースパーティー開催事件
  • 2011/12: 総会で世界の小宮が代表に

コミュニティを作る上でまず考えたのがスコープ。オープンソースのコミュニティというとツールを作るコミュニティもあれば、使うユーザのコミュニティも、翻訳のコミュニティもあったりします。ここではツールを使うコミュニティにしたいと考えました。アート・オブ・コミュニティ の日本語訳が出版されたのは2011年の4月ですが、翻訳権が取れる前に自主的に翻訳をし始めていて、その2章の組織のスタートアップの章は参考にしました。スタッフMLにも日本語訳を投下しました。

コミュニティづくりはゲームづくり

続きを読む
posted by @shibukawa at 14:14 | Comment(373) | TrackBack(0) | 日記 はてなブックマーク - Sphinx-Users.jpを作った時のお話

2012年12月11日

Qt+JS: 画像を表示する

Qtでは画像を表示する方法が何通りかあります。

アイコンとして表示

テーブルでもツリービューでも使える方法です。サイズを細かく調整することはできませんが、お手軽に表示できます。

var imageLabel = new QTableWidgetItem("", 0);
imageLabel.setIcon(new QIcon(imageFilePath));
this.tableWidget.setItem(1, 1, imageLabel);

ラベルとして表示

ラベルにはPixmapを貼ることもできます。ただ、Pixmapを貼ってしまうとテキストが書けません。ただ画像を表示するだけなら問題ありませんが、ちょっとトリッキーなHTMLを利用する方法を使えば、かなりのことが表現できます。ここでは、テキストと画像を同時に表示しています。

var imagePath = ':/images/label.png';
var label = "hello world";
var text = [
    '',
    '',
    '

', ' ' + label + '

' ].join(''); this.labelWidget.text = text;

カスタムのウィジェットを作成する

画像を表示するウィジェットを作成すると、さまざまな表現が可能になります。QPainterの豊富なメソッドを使ってさまざまなことが表現できます。拡大縮小、色の変更、合成などなどです。カスタムのウィジェットはprotectedなメソッドをオーバーライドする必要が有るため、コードでクラスを作成してnewする必要があります。

QPainter自身はQImageにバインドすれば、画像処理に使うことができますが、画面に表示させるためのQPainterは、paintEventメソッド内でしか使うことができません。以下のコードでは、最大サイズを決めて、それ以下の場合には縮小表示を行なっています。また、縮小するときにはバイリニア補完を使うように設定しています。このように、単にpaintEvent()をオーバーライドすれば、画面表示が行えます。

function ImageView(parent, path)
{
    QWidget.call(this, parent);
    var fileinfo = new QFileInfo(path);
    if (fileinfo.exists())
    {
        this.image = new QImage(path);
    }
}

ImageView.prototype = new QWidget();

ImageView.prototype.paintEvent = function ()
{
    if (this.ratio && this.image)
    {
        var painter = new QPainter();
        painter.begin(this);
        painter.setRenderHint(QPainter.Antialiasing, true);
        painter.setRenderHint(QPainter.SmoothPixmapTransform, true);
        painter.scale(this.ratio, this.ratio);
        painter.drawImage(0, 0, this.image);
        painter.end();
    }
};

ImageView.prototype.calcSize = function ()
{
    if (!this.image)
    {
        return;
    }
    var availableWidth = 340;
    var availableHeight = 300;
    var ratio = Math.min(1, Math.min(availableWidth / this.image.width(), availableHeight / this.image.height()));
    var height = Math.round(this.image.height() * ratio);
    var width = Math.round(this.image.width() * ratio);
   
    this.resize(width, height);
    this.setMinimumSize(width, height);
    this.setMaximumSize(width, height);
    this.ratio = ratio;
};

タイマーで自動更新

もしアニメーションなど、定期的な画面更新が必要であればタイマーをこのオブジェクトに仕込む必要があります。

function ImageView(parent, path)
{
    QWidget.call(this, parent);
    var fileinfo = new QFileInfo(path);
    if (fileinfo.exists())
    {
        this.image = new QImage(path);
    }
    this.timer = new QTimer(this);
    this.updateHandler = this.onTimeout.bind(this);
    this.timer.timeout.connect(this.updateHandler);
    this.timer.start(16); // 16ミリ秒ごとに更新
}

ImageView.prototype.onTimeout = function ()
{
    this.repaint(); // これを呼ぶと強制的に描画イベント発行
};
posted by @shibukawa at 19:47 | Comment(453) | TrackBack(0) | 日記 はてなブックマーク - Qt+JS: 画像を表示する

2012年12月10日

Qt+JS: QTreeWidget (3)

前回のエントリーで、ドラッグ・アンド・ドロップを実装しましたが、その代償としてGUIツールでQTreeWidgetを置いてはいけない、というものでした。基本的なコードでの設定+アルファを紹介します。

// 作成・設置
this.fileTable = new QTreeWidget();
this.widget.layout().insertWidget(0, this.fileTable);
var policy = QSizePolicy.Policy(QSizePolicy.Preferred), QSizePolicy.Policy(QSizePolicy.Preferred);
this.fileTable.setSizePolicy(policy);
// 設定いろいろ
this.fileTable.headerHidden = false;
this.fileTable.rootIsDecorated = true;
this.fileTable.itemsExpandable = true;
this.fileTable.expandsOnDoubleClick = true;
// 選択モードはExtended一択
// OS提供のものとほぼ一緒。Ctrl+Click/Shift+Clickも可になる
this.fileTable.selectionMode = QAbstractItemView.SelectionMode(QAbstractItemView.ExtendedSelection);
// コンテキストメニュー&コールバック
this.fileTable.contextMenuPolicy = Qt.CustomContextMenu;
this.fileTable.customContextMenuRequested.connect(this, this.onFileContextMenuRequested);
// キーボードのフック
this.fileTable.keyPressEvent = this.fileTableKeyTriggered.bind(this);
// その他のコールバック
this.fileTable.itemSelectionChanged.connect(this, this.onFileItemSelected);
this.fileTable.itemDoubleClicked.connect(this, this.onFileItemRenameTriggered);

selectionModeをExtendedSelectionにすると、複数の要素が同時選択できるようになります。currentItemプロパティで選択されたQTreeWidgetItemを取得することも可能ですが、最後に選択されたものしか取得できないため、コード内のcurrentItemを参照している処理はすべてselectedItems()メソッド呼び出しに変える必要があります。

キーボードのフックは次のような感じで書けます。シグナルではなくてオーバーライドなので、これも自分でnewしないと使えない機能な気がします。acceptしないと、親の方にキーイベントが中継されていってしまいます。シンプルに書いてますが、実際にはselectedItems()を取得して、選択状態に応じたifとかを入れる必要があるでしょう。

MyDialog.prototype.fileTableKeyTriggered = function (event)
{
    if (event.matches(QKeySequence.Delete) || event.matches(QKeySequence.Back))
    {
        // 処理するコードをここに書く
        event.accept();
    }
};

コンテキストメニュー表示は以下のように書きます。事前にメニューオブジェクトを作っておけば、コールバックの中は座標取得して表示して終了となりますが、大抵の場合はツリー内で選択されたアイテム数や選択された項目の種類に応じてメニュー項目を増減する必要があると思うので、コールバック内で作ることになると思います。

MyDialog.prototype.onFileContextMenuRequested = function (relativePoint)
 {
    // 何も選択されていない時は何もしない
    if (this.fileTable.selectedItems().length === 0)
    {
        return;
    }
    // 表示位置取得
    var globalPoint = this.assetKeyTable.mapToGlobal(relativePoint);

    var contextMenu = new QMenu('File Menu');
    // メニューに項目を追加
    var renameAction = contextMenu.addAction(new QIcon(), qsTr("Rename"));
    renameAction.triggered.connect(this, this.onRenameTriggered);
    // セパレータ
    assetContextMenu.addSeparator();
    // 階層構造も定義できる
    var sendMenu = new QMenu(qsTr('Send To'));

    var sendFileAction = contextMenu.addAction(new QIcon(), qsTr("File"));
    sendFileAction.triggered.connect(this.onSendTriggered.bind(this, "file"));
    var sendMailAction = contextMenu.addAction(new QIcon(), qsTr("Mail"));
    sendMailAction.triggered.connect(this.onSendTriggered.bind(this, "mail"));

    contextMenu.addMenu(sendMenu);
    // 表示
    assetContextMenu.exec(globalPoint);
};

ドラッグ・アンド・ドロップ以外の細かい設定は以上のような感じです。これらを設定するだけで、ユーザの細かい操作に対応できるツリーが作成できます。

posted by @shibukawa at 08:56 | Comment(405) | TrackBack(0) | 日記 はてなブックマーク - Qt+JS: QTreeWidget (3)

2012年12月09日

Qt+JS: QTreeWidget (2)

ファイルの一覧を表示するQTreeWidgetを作ってみます。ファイルをFinder/Explorerからドロップできるようにしてみます。ファイル名と、サイズを表示します。残念ながら、QtDesignerで作ったオブジェクトでは無理で、コードでnewしたQTreeWidgetでしか動きませんでした。レイアウトツール上ではそのスペースを適当にあけてレイアウトしておきます。

こちらで解説しているような、ダイアログ表示クラスの中に埋め込むコードを前提としています。UI用のクラスをJSで作って、this.widgetにロードした後に差し込む用のコードです。

this.fileTable = new QTreeWidget();
// 挿入位置はレイアウトによって変えてください
this.widget.layout().insertWidget(0, this.fileTable);
var policy = QSizePolicy.Policy(QSizePolicy.Preferred), QSizePolicy.Policy(QSizePolicy.Preferred);
this.fileTable.setSizePolicy(policy);
// ドロップ設定
this.fileTable.acceptDrops = true;
this.fileTable.dropIndicatorShown = true;
this.fileTable.dragDropMode = QAbstractItemView.DropOnly;
this.fileTable.defaultDropAction = Qt.CopyAction;
// オーバーライドするメソッド
this.fileTable.supportedDropActions = this.supportedDropActions.bind(this);
this.fileTable.mimeTypes = this.mimeTypes.bind(this);
this.fileTable.dropMimeData = this.fileDropMimeData.bind(this);
// その他見た目の設定
this.fileTable.columnCount = 2;
var fileTableHeaderItem = this.fileTable.headerItem();
fileTableHeaderItem.setText(0, qsTr("File Name"));
fileTableHeaderItem.setText(1, qsTr("Size"));
this.fileTable.setColumnWidth(0, 200);
this.fileTable.setColumnWidth(1, 80);

オーバーライドするメソッド定義を3個ほど作っておきます。C++なら事前にQTableWidgetの子クラスを作っておかなければなりませんが、適当な場所に動的に関数を作って差し込めば動いてくれるのは動的言語ならではですね。ここでは、MyDialogクラスのメソッドにしておきます。なぜ.uiファイルから読み込んだウィジェットではダメなのかは分かっていませんが・・・

// この2つの定義は定型文
MyDialog.prototype.supportedDropActions = function ()
{
    return Qt.ActionMask;
};

MyDialog.prototype.mimeTypes = function ()
{
    return ["text/uri-list"];
};
// こちらは実際のコードに合わせてカスタマイズが必要
MyDialog.prototype.fileDropMimeData = function (item, index, data, action)
{
    var urls = data.urls();
    for (var i = 0; i < urls.length; i++)
    {
        var filepath = QDir.toNativeSeparators(urls[i].toLocalFile());
        var fileinfo = new QFileInfo(filepath);
        var treeitem = new QTreeWidgetItem(this.fileTable);
        treeitem.setText(0, fileinfo.fileName());
        treeitem.setText(1, fileinfo.size());
    }
    // これがないとFinderが受け取れなくてファイルを戻すアニメーション
    // を実行する。受け取れない形式だったらreturn falseにする。
    return true;
};

これはExplorerやFinderからファイルをドロップする処理ですが、QTreeWidget内部でのドラッグ・アンド・ドロップも実装できます。まずは設定を変更します。

this.fileTable.dragDropMode = QAbstractItemView.DragDropMode(
    QAbstractItemView.DropOnly,
    QAbstractItemView.InternalMove);

次にドロップ時のコールバックを変更します。コード全体を説明はしませんが、どちらの処理かは最後に紹介したコールバックのactionを見れば判別できます。

MyDialog.prototype.fileDropMimeData = function (item, index, data, action)
{
    if (action === Qt.MoveAction)
    {
        // 外部からドロップ
        return true;
    }
    else if (action === Qt.CopyAction)
    {
        // 内部でのドラッグ・アンド・ドロップ
        // マウスで移動した項目たち
        var movedItems = this.fileTable.selectedItems();
        this.fileTable.clearSelection();
        // 移動先はitemに格納
        var moveTargetItem = item;
        // ここで移動後に行われる処理を書く
        // 最後はreturn trueが必要です。
        return true;
    }
};
posted by @shibukawa at 09:40 | Comment(212) | TrackBack(0) | 日記 はてなブックマーク - Qt+JS: QTreeWidget (2)

2012年12月08日

Qt+JS: QTreeWidget (1)

GUIでの設計方法を3回にわたって紹介してきました。次は具体的なコンポーネントをいくつか紹介します。まずはよく使う代表的なものとして、QTreeWidgetを紹介します。

ボタンとテキストエリアだけのUIであればブラウザベースでも全然問題ありませんが、数百項目、場合によっては1000件近いツリー要素をハイパフォーマンスで動かせるのは、デスクトップアプリの利点ですよね。ブラウザベースよりも、より複雑なデータを気軽に扱うことができます。GUIツールでレイアウトをしており、treeWidgetという名前で登録されているものとします。

QTreeWidgetで項目を追加するには、QTreeWidgetItemを使います。

// ルート直下にノードを追加
var treeWidget = this.widget.treeWidget;
var item = new QTreeWidgetItem(treeWidget, 10);
item.setText(0, "Hello World");
item.setIcon(0, new QIcon(':/graphics/flower.png'));

ツリーを使って行を足す場合にこのあたりが最低限のコードになるでしょう。最初のコンストラクタでは、表示対象のQTreeWidgetを指定します。これの次の"10"という数値は、省略可能です。ノードの識別を簡単に行うために使うことができます。後から、var type = item.type(); で取得可能です。ただし変更できません。setTextとsetIconの0はカラムのIDです。これは後述します。最後の行でアイコンを設定しています。コロンから始まるパスは、Qtの画像リソースに登録したファイルを参照するための方法です。もちろん、普通のコンピュータ上の画像を指すパスも使えます。

ツリーなので階層にしないと面白くありません。この時は、QTreeWidgetItemの最初のパラメータに、QTreeWidgetの代わりに親となるノードを渡すだけです。他は一緒です。

// 孫の要素を追加
var grandChild = new QTreeWidgetItem(item, 20);
grandChild.setText(0, "Hello World");
grandChild.setIcon(0, new QIcon(':/graphics/flower.png'));

孫から子を参照するにはparent()メソッドでアクセスできます。子から親を参照しようとするとどうなるでしょうか?この場合はnullが帰ってくるので使い分けましょう。

QTreeWidgetの直下にあるノードの一覧の取得する方法は次の通りです。子供から孫へも同じようにchild(n)メソッドで取得できます。ノードはsetHidden(true)で見えなくすることも可能ですが、この方法を使えば非表示でもそうじゃなくてもすべての項目を取得できます。

var topCount = tableWidget.topLevelItemCount;
for (var i = 0; i < topCount; i++)
{
    var node = tableWidget.topLevelItem(i);
}

先ほど、識別のためのデータを設定できると紹介しましたが、変更できませんでした。変更できるデータももてます。JSONモジュールがあるとしたら、次のようなコードが書けます。

item.setData(0, Qt.UserRole, JSON.stringify({name: "Yoshiki"}));

QTreeWidgetは、名前はツリービューですが、行指向のテーブルを表示するのにも使えます。QTableWidgetはセルごとに編集ができるような高性能な部品となっています。その分セルごとにオブジェクトを設定しなければならなかったりと複雑です。こちらは行ごとにしか選択できませんが、その分、1つのQTreeWidgetItemを使えば1行すべての表示がまかなえます。。setText()を必要なカラム番号付きで呼び出せばいいだけななのでテーブルっぽい表示をするのは難しくありません。ここではコードでカラム数を変更していますが、GUIのツール上でも編集できます。

// ルート直下にノードを追加
var treeWidget = this.widget.treeWidget;
// 列が3つになる。
treeWidget.columnCount = 3;
var item = new QTreeWidgetItem(treeWidget, 10);
item.setText(0, "Hello");
item.setText(1, "World");
item.setText(2, "!!);
item.setIcon(0, new QIcon(':/graphics/flower.png'));

駆け足でしたが、かなり高性能なウィジェットであることがわかったと思います。このコンポーネントの使い方が分かるだけでも世界が大きく広がります。このウィジェットはかなり大掛かりなものなので、何回かシリーズで紹介していきます。

posted by @shibukawa at 02:47 | Comment(204) | TrackBack(0) | 日記 はてなブックマーク - Qt+JS: QTreeWidget (1)

2012年12月07日

Qt+JS: QtDesignerによるレイアウト(3)

部品を並べる時の方法として、QWidget、QFrame、QGroupBox、レイアウトといくつか選択肢があります。どのような基準で使い分けるかを紹介します。

QWidgetとレイアウト

Screen Shot 2012-12-07 at 9.08.22 AM

ツール上はレイアウトは赤枠が表示されますが、プログラム上ではどちらも見た目はほぼ変わりません。QWidgetも内部にレイアウトを持ち、レイアウトを直接置くのと同じパラメータを設定すれば結果は同じです。

レイアウトのメリットとしては、ツリー上に階層にしても、ソースコードから操作する場合は無いものとして扱われる、という点です。つまり「見た目を改善するために、入れ子にしてチェックボックスの横にラベルを追加したよ」という場合も、ソースコードを修正する必要はありません。コードに影響を与えずにちょっとした修正ができるので使えるところはレイアウトを使ったほうがいいでしょう。下記のレイアウトにはボタンが2つありますが、プログラムからは、両方共、"Parent"と書かれたWidgetの子供に見えます。

Screen Shot 2012-12-07 at 9.14.20 AM

QWidgetにもメリットはあります。QWidgetに乗っている複数の子供のウィジェットをまとめてvisible = falseしたり、enabled = falseしたり、ステータスを一括で変更する場合に便利です。

QFrameとQGroupBox

Screen Shot 2012-12-07 at 9.07.35 AM

枠です。どれも枠です。QGroupBoxはflatというオプションを入れると見た目が左下のようになります。QFrameも線の種類をいくつか選べるようになっています。基本は好みで選べばいいと思います。

ラベルを入れたい場合はQGroupBox、いらない場合はQFrame。タブの中とか枠線が多すぎてうるさそうならFlatのQGroupBoxとか、そんな感じで使ってます。FlatじゃないQGroupBoxも入れ子になったり、たくさん並ぶとちょっとうるさい感じがしますね。

たまに部品が多くて小さい画面だと厳しそうだなー、と思う時はQScrollAreaを代わりに使うこともあります。

このあたり使い分けられるようになると、「おれデザイン作っている感」が味わえるようになります。

posted by @shibukawa at 09:34 | Comment(205) | TrackBack(0) | 日記 はてなブックマーク - Qt+JS: QtDesignerによるレイアウト(3)
検索ボックス

Twitter

www.flickr.com
This is a Flickr badge showing public photos and videos from shibukawa.yoshiki. Make your own badge here.
<< 2017年05月 >>
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
最近の記事
カテゴリ
過去ログ
Powered by さくらのブログ