NonBlockingGenericDialogによる操作パネル

17th October 2021 at 8:44pm

ImageJでプラグインを作成する際に、run()中に操作パネル的なダイアログが欲しくなる時があります。

これを実現するために、私は、SwingのJDialogを使っていました。

しかし、ImageJのダイアログとは見た目も違うし、プログラミングも大変です。(Swingのスライダーにラベルやテキストボックスは標準でついていません)

Swingの例

ImageJの例

そんな時、モーダレスなGenericDialogであるNonBlockingGenericDialogを見つけました。(見落としていただけですが)

しかし、このクラスもあくまでImageJの作業を阻害しないだけなので、プラグイン中の操作パネルにするには、ひと工夫必要です。

NonBlockingGenericDialog + Thread で実現してみました。

ポイントは以下の通りです。

  • NonBlockingGenericDialogは、GenericDialogと全く同じ使い勝手です。
  • Threadを継承したサブクラス内で、NonBlockingGenericDialogを作成します。
  • 数値の取り出しは都度全て行うことが必要です。JDialogのように、個別のオブジェクトのイベントに対して処理を書くことはできません。

以下参考例です。

プラグインを実行すると、ステータスバーにループカウンターの数値を表示します。スライダーを10未満にすると処理が終わります。

import ij.IJ;
import ij.ImagePlus;
import ij.gui.DialogListener;
import ij.gui.GenericDialog;
import ij.gui.NonBlockingGenericDialog;
import ij.plugin.filter.ExtendedPlugInFilter;
import ij.plugin.filter.PlugInFilterRunner;
import ij.process.ImageProcessor;
import java.awt.AWTEvent;

public class Sample_ThreadDialog implements ExtendedPlugInFilter {
    private final int FLAGS = NO_IMAGE_REQUIRED;
    private boolean isExit = false;    
    
    @Override
    public int showDialog(ImagePlus ip, String string, PlugInFilterRunner pifr) {
        return FLAGS;
    }

    @Override
    public void setNPasses(int i) {
        // do nothing
    }

    @Override
    public int setup(String string, ImagePlus ip) {
        return FLAGS;
    }

    @Override
    public void run(ImageProcessor ip) {
        // スレッドを継承したサブクラスのインスタンス
        SubClass_ThreadDialog thrddg = new SubClass_ThreadDialog();        
        thrddg.start();
        
        double loop_counter = 0;
        
        for(;;){
            
            IJ.showStatus(String.valueOf(loop_counter));            
            loop_counter = loop_counter + 1;
            
            if(isExit) {
                break;
            }
        }
        
        IJ.showMessage("Finish!");
    }
    
    // スレッドを継承したサブクラス    
    public class SubClass_ThreadDialog extends Thread {
        @Override
        public void run() {

            // GenericDialogと使い方は一緒です
            NonBlockingGenericDialog gd = new NonBlockingGenericDialog("SubClass_ThreadDialog");        
            gd.addSlider("value", 0, 100, 50);

            gd.addDialogListener(new DialogListener(){                    
                @Override
                public boolean dialogItemChanged(GenericDialog gd, AWTEvent awte){                        
                    double val = gd.getNextNumber();

                    if(val < 10){
                        isExit = true;
                        gd.dispose();
                    }

                    return true;
                }        
            });

            gd.addMessage("Exit when value is Less than 10.");
            gd.showDialog();
            isExit = false;
        }   
    }
}


HomeへImageJの記事Topへ