CS6までだとコードの中で塗った順に関係なく、上にあるオブジェクトが見えていたが、CCだとコードの順で見た目が変わる。UIのbackgroundColorを変えると、その子も適用されちゃうみたい(多分)。なのでWindowオブジェクトから順番に適用していかないと思ったようにならない。かもかも。
app.settings.getSettingsで読み込めるデータは2kb以内らしい。めんどくさいから全部'data'ってオブジェクトにまとめて1つのkeyNameにして保存してたけど、ユーザーが自由に登録できる系などデータサイズが予測できないものには適していないようですな。解決策としては、データを細かく分けてキー名を複数するか、外部ファイル化する。キー名を増やすことに関してはまた別の上限があるのかは知らない。
①任意のアプリでフォントを使ってPDFをつくる。readerで開く。ファイル->プロパティ->フォントで出てくる。
②Photoshopで次のスクリプトを実行
//フォント一覧をコンソールに出力 Photoshopを使用
#target photoshop
for(var i=0; i<app.fonts.length; i++){
$.writeln(app.fonts[i]+"postScriptName : "+app.fonts[i].postScriptName)
}
UI作ってるときに、スクショしてエクスプローラーで表示されてるアイコンをパクりたいときがある。AEとかPSDのファイルアイコンは影が落ちてるのだけれど、その影をアルファ持たせたPNGにして作成したいと思った。
該当部分をPhotoshopの塗りつぶしツールで黒[0,0,0]で不透明度30%にしたら元と同じ影を持たせることが出来た。
多分CS6だけ。UIパーツをマウスオーバー時にテキスト表示できるhelpTipを適用している時、長い文章を書いてしまい、UIのウィンドウ(またはScripUIパネル)の範囲からはみ出るサイズの時、そこで切れる。
例えばドロップダウンリストをクリックしただけでAEがクラッシュするとかいう現象が起きている
ScriptUIパネルの時だけ発生する
これら両方に該当したら、「以前のバージョンのUIを使用」がONになっているかもしれない。パネル名横から出せるメニューから「以前のバージョンのUIを使用」をOFFにすることで解消される。
このバグは2021(18.0)で解消されている。
AutoLayoutを使用していて、例えば、ドロップダウンの選択に合わせて表示が変わるなど、コントロールと連動して他のUI更新が必要なとき。WindowのShow後だと追加するコントロール全てに対してboundsが定義されてないとAutoLayoutできないっぽい?locationが不明とか言われる。
layout.resize()記述前にlayout.layout()しとかないとパネルの時にエラーになる。リサイズできない。
UIの中に置いたGroup(以外も?)のenabledが false -> true 変わった状態でウィンドウを閉じると、その次回から開くウィンドウの中身が真っ白になる現象。よくわからんが true -> false の時はバグらない。
UIで選択状態が変わったときに別のパーツのenabledを切り替えるときに起こりやすい。例えば下図のような、チェックボックスの選択によって他のコントロールが無効になる仕組みの時。
これは他のScriptのWindowにも影響する。「異変!真っ白になったウィンドウ!懸命の捜索虚しく、原因は特定できず。別のスクリプト関与の噂!?」みたいな状態。(なんやそれ)
懸命の捜索の結果、Windowを閉じる前に該当のコントロールをenabled = false にすることで解決することがわかった。でもたくさんあるとめんどくさいので、
window.enabled = false と、トップレベルからまとめてやっちゃうことで楽に回避できた。なので、設定画面とか凝って作るときは、下記コードを入れとくと無難。
Window.onClose = function(){
this.enabled = false;
}
この現象は「メインのウィンドウやパネルから新たに出現させるウィンドウ」のみで確認済み。例えば、「このボタンを押したら設定ウィンドウが出ますよ」といったときのみ発生する。メインのパネル内でenabledをごちゃごちゃする分には問題ない。
Button.window
みたいな感じで、UIのパーツが属しているトップレベルの[object Window]を返してくれる。ScriptUI Panelでの表示の時はエラーになる。なぜならScriptUI Panelのときはトップレベルが[object Window]じゃなくて[object Panel]だから。そしてPanelの時に使える変わりのプロパティは無い。
Windowオブジェクト作成時、ウィンドウの種類を 'dialog' , 'palette' , 'Window'から選択できるが、'palette' の時は Window.close() しても、メモリには残り続ける。エンジン(AE)が生きている限り残るらしい...。シラナカタヨー。
Window.find("palette" , windowText)
を実行して、メモリ上にウィンドウがあるか調べる。windowTextにはWindow.text の値(タイトルバーの文字)を。戻り値はWindow Objectまたはnull。
textが同じウィンドウが複数作成してたらどうなるんや。メモリ的には上書きされんのか?調べてない。
ただし、findにはまた別のトラブルを抱えている。下記の「ウィンドウが消えない」参照。
UIパネルにボタンを設置して、クリックするとウィンドウ(例えば設定ウィンドウとか)が出てくる、というものを作ったとする。コード上問題ないのに、クリックしてもウィンドウが現れないことがある。ずっと待ってると出てきたりする。
なぜかAfterEffectsからフォーカスを外すと即出てくる。つまり、出てこない時はエクスプローラやブラウザなど何でもいいので他のアプリケーションをアクティブにするとよい。恥ずかしがりか!
CS6で現象確認。いつ直ったかはわからないが、2020ではこれは解決している模様。
出てこなかったり、消えなかったり...厄介なヤツやの!!w
上記「paletteの恐怖」で書いた通り、paletteではfindでウィンドウの再利用が出来る。再利用したウィンドウをスクリプト上で閉じようと、
[Window].close()
しても消えない。
CS6では問題ないので、CCのどこかから。最終兵器「Alt+F4」でも消せない。
そうなったらfindでの再利用は諦めて、毎回 new Window で生成する。
で、解決すると思ったけど、しなかった。解決方法模索中。
あまりにshow/closeを繰り返すような使い方の場合、メモリ的に圧迫してくるのかどうかはわからない。
ちなみにCS6の場合、onCloseコールバック
[Window].onClose = [Function]
を設定すると、ウィンドウが消えなくなるかもしれない。多分。
Dialog Windowでは問題ない、はず。
開発初期にウィンドウが一瞬出てすぐ消えるときがある。
ただ単にボタン付きのpaletteウィンドウを表示しようと思った時、
(function () {
var w = new Window('palette{\
btn: Button{text: "ボタン"}\
}');
w.show();
})();
これを実行するとなるかも。ソースコードに問題はないはず。
ここでonClickに関数を与えてみる。
(function () {
var w = new Window('palette{\
btn: Button{text: "ボタン"}\
}');
w.btn.onClick = function () {}
w.show();
})();
とすると出てくる。なんでかは知らん。onClickじゃなくても独自のプロパティでもいいので、なにかしら関数を割り当てるとちゃんと出るようになる。
独自のプロパティというのは
w.btn.aa = function(){};
みたいなのでもいいということ。
これはdialogの時には起きない。
CS4 → 最後に visible = true
CS6 → 最初に visible = true
タブパネル作成するときaddする書き方だと
var w=new Window ('dialog' , "panel test");
var tp=w.add("tabbedpanel");
var tab1=tp.add("tab",undefined,"tAB1TAB1TAB1ATAB1");
tab1.add("button",[10,10,100,50],"button");
みたいに書くからPanelと別もんかと思ってたがalertしたら「Object Panel」って言われるしよくわからんかったけど。なるほどPanelのtypeで指定できることにやっと気づいたので、こう書ける。
//プロパティに直追加のときは、Panelとして作成して、typeで種類を指定
var w=new Window ('dialog{ text : "panel test",\
tp : Panel{ type : "tabbedpanel" ,\
tb1 : Panel{ type : "tab" , text : "aaa" , \
btn : Button{ text : "Button" }\
}\
}\
}');
自分の環境だとCS6で [4230,1870] までしかいかなかった。他は知らん。CS4だと[2510,974]?
クリックしたら色が変わるとかいうとき、また選択が変わったら元の色に戻したい。そんなとき。
ウィンドウ表示前とかに
.graphics.backgroundColor.color
でデフォルトの色を拾っておいて、切り替えの時に使えばいいんだけど。対象アプリケーションがESTKの時だとundefinedでエラーになっちゃう。
UI作り始めはAEと連動するのめんどくさいからESTKでやっちゃうけど、そこでエラー出て困る必要はない。実際使用するときはAE上なのでエラー起きない。最初からAEでデバッグしてればいいのかもだけど。
CS6まではGroupに対してonClickでコールバックが使えていたのだけれど、CCのいつからか使えなくなっている。addEventListener('click',Function)に書き換える必要あり。このあたりは後述の「EventListener」の項も参照されたし。
①Groupを入れ子にしている状態でonShowのときに親Groupのenabledをfalseにする
②チェックボックスで親GroupのenabledをOFF -> ONにする
③ウィンドウのサイズを変更する
以上の手順を踏むと停止した。すべてのケースで発生するかはわからない。スクリプト作成中にここで詰まった事があるので。
回避策としては、めんどくさくてもGroupでまとめてenabledを操作せずに、コントロールを直接設定していく。
ボタンにはbackgroundcolorを設定できないけど、ボタンの親をGroupにしておいて、Groupの背景色を変えるとボタンの色も変わる。(ターゲットがAEのとき。ESTKだとならん)
画像サイズにプラスで12pxのマージン(枠)ができる
[ImageObj].image = [FileObj];
を使って画像をセットできるが、これをウィンドウの onShow 時に実行するとウィンドウ表示時点で画像が表示されないことがある。AfterEffectsのバージョンによってまちまちなので、表示されない時は確認してみるが吉。onShow の中で書かなければ解決する。
onShowの挙動はバージョンによってゆらぎが大きい気がする。
と書くと語弊があるが、
[IconButton].onClick = [Function]
で
[IconButton].addEventListener('click', fucntion(){})
としても反応しない?onClickを使うしかないのか?2022 (ver22.2.1) で確認。
上の項目で「onClickを呼び出せない」とあるが、書きかけで詳細は忘れた。まぁonClickかaddEventListenerどちらかは使えると思うので、使える方を使う。
自分で画像を全て作成する時、つまり1つのIconButtonに対して「通常時」「ボタン無効時」「クリック時」「マウスオーバー時」の4種類の画像を自分で用意する時、画像のデザインだけを表示させて、もともとのボタンのデザインは隠したいことがある。デフォルト状態では「ボタン無効時」「クリック時」「マウスオーバー時」のボタンに対して、暗くなったり、フォーカスを表す青い枠がついたり、といった変化を用意してくれているが、それをユーザーに見せたくない時。
properties.toolbutton = trueにしてボタンの枠を消すことで「出っ張ったボタンのデザイン」を無くすことは出来るが、それだけでは「通常時」以外の変化(マウスオーバーで暗くなったり...)は無くせない。それらを「見えなくする」という直接的なプロパティは無いので、設定する画像でボタン全面を覆って隠すことになる。IconButtonと同じサイズの画像を使えば全面隠せるんじゃね...と思うのが普通だが、微妙に違った。
IconButtonの大きさ(sizeとかpreferredSize)と同じ大きさの画像を適用すると右側が1ピクセル、下地のデフォルトデザインがはみ出てしまう。20x20のサイズのIconButtonを作成したら、実際には21x20の画像サイズが必要と見たほうがいい。画像を右側1ピクセル余分に作っておき、それを適用すると下のボタンは一切見えなくなる。
ちなみに画像に透明部分が存在する場合、下地が透けて見えるので回避不能。(透けてても、toolbuttonの設定でボタンデザインを消しているので「通常時」だけは見た目はOK)
2023からアイコンボタンの形状が角丸長方形になった。
ドロップダウンリストのアイテムにはアイコンを設定できるが、選択した後の表示がバージョンによって変わる。
CS6だとドロップダウンリストをクリックして出る選択肢にはアイコンが付くが、選択後にはテキストしか表示されない。CC2019では(どのバージョンからなのかは不明)選択後もアイコンが表示されている。
addEventListenerでmouseoverを指定していたものが使えなくなった。
ドロップダウンリストにはアイテムには、通常のテキスト以外にもアイテム間の区切りとしてセパレータを設定することが出来る。これは通常選択出来ないアイテムである。CS6では選択出来なかった(これが本来の挙動)。CCのいつからかUI上でこれが選択できてしまう(2019~2022で確認)。
セパレータを選択した場合、選択アイテムを表す ListBox.selection の値には null が入る。つまり、セパレータを選択した場合は選択解除と同じ扱いになるっぽい。ちなみにドロップダウンリストの通常の操作で選択解除することは出来ない。
リストボックスに複数文字を一気に入れても一文字ずつ入れられる。
つまりはonChangingは文字数分だけ呼び出される。ということ。
[80,20]
CS4だとwindow直下にListbox配置すると表示されない。1回Group作成してそこに入れないと何故か表示されぬ。
ListBox.add("item","ABC") を繰り返して追加していってもいいんだけど、forループがめんどくさい。追加するデータが配列で取得済みならなおさら。UIもaddじゃなくてプロパティとして文字列で一気に追加するタイプの場合、その中に組み込みたいと思う。
ListBox{ properties : { items : [arr] } }
にぶち込める形に配列を変換したい。つまり、
ListBox{ properties : { items : ["abc","def","ghi"] } }
の形に落ち着くようにすればいい。
配列をArray.toSource() で変換すると、目的の形にできる。ただし、2バイト文字が\uで始まるUnicodeに変換されてしまう。これをアイテムとして追加してもダメ。なので元に戻す必要がある。
function ArrToSource( arr){
return arr.toSource().replace(/\\u.{4}/gi , function(m){ return String.fromCharCode(m.replace('\\u','0x')); })
}
これで返ってくる文字列をproperties : { items : [arr] } の[arr]にぶち込めばいける。
DropDownListでも可能。
AE2020で確認。
ListBoxでは"properties"プロパティで、
ListBox: {properties: {numberOfColumns: 5}}
の様にすると複数列のリストを作成出来て、さらに
ListBox: {properties: {numberOfColumns: 5}, columnWidths:[10,15,3,20,-1]}
の様にcoumnWidthsに数値の配列を与えると、それぞれの列幅を指定できる。(-1は、自動フィット)
CS6ではリストアイテムのテキストの文字数に関係なく、各列がColumnWidthsで指定した幅で表示されたが、2020では違った。
リストアイテムに長い文字列が入る時、データが見切れないように幅が勝手に修正されてしまう。つまり、列幅の最低値はデータ内容に依存している。
データ全体が見えることよりも、列幅を優先したいときに困る。
UI追加後にLsitItem追加
ウィンドウのonShowコールバック内でListItem追加
先にウィンドウをlayout.layout()して、UIの位置・大きさを確定してからListItemを追加
ListItemを追加するボタンを用意する。ListItem無しでウィンドウを表示してから、ボタンクリックでListItem追加
どれをしてみても結果は一緒だった。4つ目では最初、アイテムが無いときは指定した幅になっているが、追加した瞬間に列幅が変更された。
CS6だと、「Ctrl+クリック」でそのアイテムを選択解除出来る
2020だとそれが出来ない。代わりに、ListBox内でリストアイテムのない空いてるところを選択すると全てのアイテムを選択解除できる。逆にCS6ではこれは出来ない。
2022は出来る。
ボタンとかをクリックしてListBoxのtextを書き換えた場合、CS6では即座に見た目に反映されるのに、2020の場合は反映されない。ように見える。選択状態に何かしら変更を与えたるスクロールしたり、何かしら再描画させると反映される。
ホイールでリストボックスをスクロールした時、今までは3項目くらいのスクロール幅だったのが、2023では7ピクセルくらいになっている。スクロールが遅くてすごく面倒。
これで解決するっぽいかもしれない多分。Progressbarの値を変更する度に、windowのupdateを使う。変わらなければその後showするといいかも?それでもなかなかリアルタイムな表示はされない。他のバージョンだときれいに動くものもある。
//Progressbarの値を変更した後に
window.update();
window.show(); //なくてもいい?
キーのdetailプロパティを調べる。1はシングル、2はダブルクリック
addEventListener('click',function(e){
if(e.detail==1){ alert("Single Click!!");
if(e.detail==2){ alert("Double Click!!");
}
CS6はどっちにしても0になるので判別ができない。detailってクリックした回数ちゃうんかい。0ってなんやねん。
どのキーが押されたかは基本的にはkeyNameなどで判定できるが、Ctrl,Alt,Shiftといった修飾キーや、数字キーなど「キーボード上に複数あるキー」を押したとき、keyLocationの値でどのキーか判別できる。
左の修飾キー 1
右側の修飾キー 2
テンキーの数字 3
それ以外 0
な!ん!だ!け!ど!ESTKで実行した時しかうまく行かない。
AE上だとkeyLocationの返り値は0になるようになっていた...。
■keyLocation が全部 0
16.1.3 (2019)
17.7.0 (2020)
18.0.0 (2021)
そんな訳でkeyLocationは使い物にならないなう!
通常、
[EditText].addEventListener('keydown', func);
のように書くと、EditTextがアクティブになっている時に何かキーを押すとキーイベントを拾うことができる。
addEventListenerは子にも伝播するので、例えば、
[Window].addEventListener('keydown', func);
の様にすると、Windowまたはそこに含まれる何かしらのUIパーツがアクティブならいつでもイベントを発生させられる。つまり、ウィンドウが開いている間いつでもショートカットキー的に使える挙動を設定できる...のだけれど。
CS6だと、ButtonとかEditTextとか、コンテナ(Window, Panel, Group)以外の何かしらがアクティブになっていないと反応しないっぽいので、
[Window].show();
で、ウィンドウを表示する前に何かしらをactiveにしておくのが無難。UIをいろいろつけていて、操作中にアクティブなのがいなくなってしまうと、また効かなくなるので注意。UIそれぞれにonDeactivateコールバックを設定しておいて、非アクティブになったときに他の何かしらをactiveにするようにしておけば回避できるか?そこまでやったこと無いけど。
2020だと、EditTextがアクティブ状態でウィンドウの空いてるスペースをクリックするとEditTextが非アクティブになるが、その後activeな物が何もない状態になるので、この状態でも効かなくなる。
まとめると、
前提として、コンテナとStaticTextはタブオーダーに含まれない。これらはユーザーがアクティブにすることが出来ない
例外:CS6はStaticTextをクリックすることでアクティブにすることができる
基本的にはタブオーダーに含まれるUIパーツがアクティブでないと反応しない
例外:2020だとウィンドウ表示直後だけ、何もアクティブになっていない状態でも反応する
例外:CS6はウィンドウ表示直後だけ、StaticTextがアクティブ状態でも反応する
2020でEditTextがアクティブ状態でウィンドウ上の空白部分(コンテナ) or StaticTextをクリックしてEditTextを非アクティブにすると、何もアクティブじゃない状態になる。この状態では反応しない
例外:CS6ではEditTextの外側をクリックして非アクティブにすることが出来ない。似たことをしようとするとStaticTextをクリックするしか無い
Keyboardイベントで、キーボードの押したキーについての情報を取れる。
[KeyboardEvent].keyName
で、押したキーの名前(「A」とか「PageUp」とか)を取得できる。
ウィンドウを開いている時に、何かしらのキーを押したタイミングで何かを実行したい時に使用する。どのキーを押したか関係なく、とりあえず何かを押したら実行されるので、実行する関数の中で「押したのが『A』」の時とか「押したのが『上矢印』の時」なんて条件分けする。
条件分けの時にkeyNameを使用したいのだが、過度な信用は禁物。
キーボードは国・地域ごとに違う。スクリプトの仕様はもちろんアメリカなどで使われる「US配列キーボード」を基準にしているので、日本の「JIS配列キーボード」を使用していると、押したキー通りの名前が返ってくるとは限らない。
といってもUS配列とJIS配列は似ているので、AとかBとかよく使うキーは問題ない。右手薬指、小指付近にある記号たちが危険。
2020の場合、US配列前提でkeyNameが返ってきているので、keyNameで判断すると思ったように行かないかもしれない。JISにしかないキーを押すと、CS6だと関係ないkeyNameが入るし。ソースコード内ではkeyNameで書いたほうが見やすいけど、keyIdentifierで判断したほうがよさげ?
と思いきや、keyIdentifierもバージョンによって変わることがある。
実際に使うキーの内容を考えると、keyNameのほうが無難か。
screenX,screenYはaddEventListenerで実行する関数に与えられる引数が持つプロパティ。実行時のカーソル座標が取得できる。
CS4ではこれらがカーソルの絶対座標を返す。これを利用して右クリックメニューに似せたウィンドウを作ったりしてた。
これがなぜかCS6で使うと、欲しい位置にウィンドウが出てこない。
調べてみると、どうもscreenX,screenYの返す値が ウィンドウの種類(Window か Panelか)によって変わっている模様。
Windowで表示していると今まで通りの挙動。スクリーン上の絶対座標を返す。
ただし、Panel表示の場合はパネル内のローカル座標を返す。だったら、パネルの絶対座標が取得できればええやん、と思ったが、
最上位のPanelのlocationを調べると、どこにいても[0,0]が返ってくる。
えーそんなぁー。詰んだ?模索中。
CC(2015.3と2018で検証)で、addEventListener('click',Function)で左クリックが効かなくなった(mousemoveとかもバグってるらしい)。
ちなみにCS6は左クリックしか反応しない。右クリックでポップアップウィンドウ出すとかが一切できなくなってた\(^o^)/オワタ
CCに話を戻して。。。
正確にいうと、ButtonとIconButtonに当てたやつだけ?なのかどうかは未検証。少なくともGroupに対しては問題なく動作した。
フォーラムで出てた解決策は「click」を使わず「mousedown」で代用する。でも普通のクリックは「mouseup」の時反応する。「mousedown」の中で「mouseup」のEventListenerを実行すれば再現できるのだけれど。入れ子が複雑になっていくのは嫌。
なのでマイ解決策は、
addEventListener('click',Function)した後(前でもいいけど)、onClickも設定する。
addEventListenerは中&右クリック用、onClickは左クリック用。
充てる関数は仮にClickFuncとする。
function ClickFunc(mouseEvent){
if(mouseEvent.button == 0){
//左クリックの処理
}
else if(mouseEvent.button == 1){
//中クリックの処理
}
else if(mouseEvent.button == 2){
//右クリックの処理
}
}
Button.addEventListener('click' , ClickFunc) で中右クリックはクリア。これは問題ない。
左クリックは、onClickを使うが、これはmouseEventが取れない。
なのでCCの時だけ、
if(parseFloat (app.version) >= 12){
Button.onClick = function(){
ClickFunc({button : 0 });
}
}
としてonClickを設定。そこに「button」プロパティを持つオブジェクトをぶち込んでみた。そうするとClickFunc内の「//左クリックの処理」が実行される。
onClickを左クリック専用として扱うから出来る荒業。CS6は中右クリックという2種類が判別できないので、この技は無理。ctrl+クリックとか、修飾キー併用で逃げるしかないか。
addEventListenerで割り当てた関数の引数に、自動的に修飾キーやクリックしたボタンの種類などが入るようになっているが、前項の通りaddEventListenerを使用したくないときもある。onClickで充てた関数には自動的に入ることはないが
これを知らなくて、前項では頭を悩ませた末の対策を考えた。深く考えなくていいことがわかった。
ScriptUI.environment.keyboardState
これでいつでもキーボードのキー押下状態が拾える。
onClickの関数内でこれを使って、ctrlKey、altKey、shiftKeyの値を拾えば「ctrl+クリック」などの判別ができる。
[object KeyboardState]
altKey: [Boolean]
ctrlKey: [Boolean]
metaKey: [Boolean]
shiftKey: [Boolean]
画像本来のサイズではなく任意のサイズで表示しようと思った時、ImageのonDraw関数を書いておけば自動で伸縮するように出来るが、なぜかそれが発動しない時がある。
ウィンドウAに設置したボタンをクリックするとウィンドウAを閉じ、新たに別のウィンドウBを表示する。
とやったときに起きた。ウィンドウAを表示するときは問題ないが、ウィンドウBの表示で発生する。
対策は、Imageオブジェクトにアクセスすること。ウィンドウBのonShowコールバック内に、Imageオブジェクトにアクセスする何かを書いておけば良い。プロパティを設定するとかそういうのも必要なく、
var w = new Window('dialog{\
im: Image{}\
}');
たとえばこんな構造だったら、
w.im;
と書くだけでアクセスしたことにはなる。
画像をスクリプトのソースコード内に埋め込んでいる時、[object Image] の icon/image にその画像データを設定しようとすると、エラーになる時がある。CS6で発現した。2020では出ない。IconButton でも起こるかも。
謎なのが、スクリプト実行を6回くらい繰り返すとエラー無く通るということ。
原因は不明なままだが、繰り返しているうちに通るのでソースコードは問題なしと見ることにした。
装飾として Image を使用していただけだったので、エラーになる時は try~caych で逃げることにした。エラーで止まることはないが、アイコン画像は設定されないままウィンドウが表示される。
絶対に表示されないとダメなのであれば画像を埋め込みにせず、通常通りファイルパスを指定して File オブジェクトを作成すべき。それならばこの現象は起きない。
UIのフォントをいじりたかったのだけれど、CS6ではフォントファミリーは変更できるが、文字サイズとか効かなくなってる。さらにCCのどこかのバージョンからフォントファミリーも変えれない。できてStaticTextのforegroundColorくらいか。どうぶつの森風のウィンドウ作りたかったけど、どうしてもフォント変えたい場所は画像にしとかないとダメかしらね。
CS4だとUIのフォント好きに変えれたのに・・・。
CS6ではStaticTextをドラッグすると文字を選択できる。そのままコピーもできる。
でもこれは設計者の意図じゃないはず。新しいバージョンでは選択不可能になっている。
StaticTextをenabled = FALSEにしたらStaticTextがグレーアウトしてほしいのだけれど、グレーアウトしてくれないバージョンが存在する。マイナーバージョン単位で変わるようなので追跡不能(めんどくさい)。以下のスクリプトで実験して変わらなかったら諦める。
もっと前からあった気もするけど覚えてない...。
■変わらないのを確認したバージョン
17.1.4
// StaticTextのenabledを切り替えるだけのボタン
var w = new Window('dialog{\
st: StaticText{text:"グレーアウトしろ!"}\
btn: Button{text: "enabled = TRUE"}\
btn2: Button{text: "enabled = FALSE"}\
}');
w.btn.onClick = function () {
w.st.enabled = true;
}
w.btn2.onClick = function () {
w.st.enabled = false;
}
w.show();
StaticTextはデフォルトでは1行しか表示できないが、
[StaticText].properties.multiline
をtrueに設定すると複数行のテキストを表示することが出来る。
ただ、これと自動レイアウトを同時に使用している時、少し困ることがある。
複数行をONにしてStaticText生成
layout前(≒ウィンドウ表示前)にtextプロパティに複数行のテキストを設定
自動レイアウトして表示
の流れとする。この時、自動レイアウトによってStaticTextが、与えた複数行に必要な高さに自動で設定されるのを普通は期待する。
2で設定した複数行のテキストに2バイト文字が混入していると、自動レイアウト時に必要な高さの計算が狂うようで、なぜか必要な高さの2倍くらい(もしくはそれ以上)の高さに設定されてしまう。
回避策としては、ダミーで、2バイト文字を含まない同じ行数のテキストを事前に入れておく、それで一旦layout.layout()を使えば適切なboundsが設定されるので、その後に本命のテキストを入力する。Windowの場合はonShowにでも入れておけばいい。折返しが発生するレイアウトの場合は上手く行かないかも。
2018か2019かくらいから、EditTextの
[EditText].onEnterKey = callback
や
[EditText].addEventListener('enterKey', callback)
でEnterキーに反応するようにした後、Enterすると2回実行されることがある。コールバック自体は1回だが、その中で呼んでいる関数が2回呼ばれていた。正確には関数自体の呼び出しは1回だが、関数の終わりまでいったら、関数の途中から望んでいない2回目の処理が始まっていた。
コールバック内の再帰処理外すと問題なかったりしたが、再帰処理使っていないやつでも発動するので、直接的な原因ではなさそう。
Enterキーを押す代わりに別ボタン用意するとかで回避は出来るが、UIの使い勝手に影響するので私的には割と深刻。関数実行時にフラグを立てておくしか無いか?う~ん。
シンプルなサンプルを作成してもそれは発生しない。コールバック内で複雑な処理が行われている時のみ発生するっぽい?が、決定的な原因は不明。
dialogでは起きない。paltteかUIパネルの時だけ。ブレークポイントで一度止めてから実行したらdialogじゃなくても問題は発生しないのも謎。
最終的には、
[EditText].addEventListener('keydown', callback)
で全てのキーに対して反応するようにしておいてから、callback関数に渡されるKeyboardEventオブジェクトを調べる
[KeyboardEvent].keyName == 'Enter'
のときだけ続きの処理を行うことでなんとか凌いだ。
EditTextがアクティブな間、全てのキーに対して反応するので、CS4くらいのときはもたついて正常にタイピング出来なかったので避けていた。2020で久しぶりにやってみたら問題なさそうだったのでこれで行くことにした。
EditTextに数値を入れてEnterエンター、数値を入れてEnter、...
するようなUIを作っていた。
Enterのコールバック内では、
レイヤーに対してやりたい処理
EditTextのtext内容に次の候補を自動的に入力
EditTextをactiveにすることでtextを選択状態にする
という流れの処理を書いていた。自動入力された候補で問題なければエンターの連打で。ダメだったら、テキストは全選択状態なのでそのまま希望の文字を打ち込んでしまえばいちいち消さなくても上書きできる。
[EditText].active = true
をすればテキストが全選択された状態になるのでそれを利用していた。
CS4では問題なかったが、CS6から
[EditText].active = true
を実行しても文字を選択状態に出来なくなった。正確には、Enterのコールバック中にEditTextのtextの書き換えを行うと、activeにしても文字の選択状態に出来ない。text内容を書き換えない場合は選択状態に出来る。ただ、これでは使い勝手が悪かったので、意味がない。
幸い、このUIに関してはEditTextは1つではないのでTABでフォーカスを移動することで文字を選択状態にすることは可能。なので、
EditTextに数値を入れて、エンター、数値を入れてエンター、...
というのが、
EditTextに数値を入れて、エンター、TAB、数値を入れてエンター、...
という流れにせざるを得なくなった。
app.activate() などいろいろ試してみたが、どうにも見つからなかった。根本解決は多分無理?できた神様がいたら、教えてほしい。
app.scheduleTask
を利用することにした。これは遅延実行させる時に使うもの。呼び出してから実行までの時間を設定できるので、それを0にしてしまうことで、実質即時実行させる。
scheduleTaskで呼び出した関数は呼び出した場所に関係なくグローバルで実行されるので、グローバルから参照できるようにグルーバル変数を用意する必要がある。対象のEditTextをグローバル変数にダイレクトに入れておいてもよいし、なんかオブジェクトで包んでおいても◎。とにかく遅延実行した関数からはschedukeTaskを実行した場所から参照できるローカル変数はアクセス出来ないのを覚えておく。