Just as we did while developing macros, there is a way to add a user interface to your plugin. This will allow us to ask the user for input regarding specific parameters that your code will use before running. This is done through methods of the
GenericDialog
class. Consider the following example, which will also introduce other concepts:
import ij.*; import ij.process.*; import ij.gui.*; import java.awt.*; import ij.plugin.filter.*; public class Dialog_Example implements PlugInFilter { ImagePlus imp; boolean dialogCanceled = false; int radius = 3; int filterType; public int setup(String arg, ImagePlus imp) { this.imp = imp; return DOES_ALL; } public void run(ImageProcessor ip) { doDialog(); if (dialogCanceled) return; RankFilters rf = new RankFilters(); rf.rank(ip, radius, filterType); } private void doDialog() { GenericDialog gd = new GenericDialog("Dialog example"); gd.addMessage("This is a sample generic dialog"); gd.addChoice("Filter type: ", new String[]{"Mean", "Median"}, "Mean"); gd.addNumericField("Input your filter width:", radius, 0); gd.showDialog(); if (gd.wasCanceled()) { dialogCanceled = true; } else { String ch1 = gd.getNextChoice(); if (ch1.equals("Mean")) filterType = RankFilters.MEAN; else if (ch1.equals("Median")) filterType = RankFilters.MEDIAN; radius = (int) gd.getNextNumber(); } } }
The preceding code opens a dialog and allows the user to select between two types of filtering (Mean or Median) and a filter radius. The selection is then applied to the current image. This is the dialog that we have created:
In the preceding code, the setup method is very simple. It simply assigns the ImagePlus
reference and returns the
DOES_ALL
constant, which will allow us to use this plugin in every type of image. There are other variables declared in the class body and we will go through them in a second.
Before getting into the run()
method, let's consider a new method added for this example, doDialog()
. This method does not require any arguments and returns nothing. It is simply a helper method used to build the user interface. As said before, this is done by creating an instance of the GenericDialog
class and then adding new components in a way very similar to what we did while building GUIs in a macro. In this case, we have added a message, a drop-down list, and a numeric field. After all the components have been added, we need to call the showDialog()
method and then check whether the user clicked on the Cancel button. If that is the case, we set the
dialogCanceled
variable to true
. As you can see, this variable is then checked in the run
method and, if true
, the plugin does nothing.
If the user doesn't cancel the dialog, then the variables will be recovered. As you can see, the choice in the drop-down menu is used to set the right value to the filterType
variable according to the static constants defined in the
RankFilters
class. This class implements some of the ImageJ filters and is the one we will use for the actual filtering. The value of the radius
variable is cast to the int
data type, as the getNextNumber()
method returns a double
value.
After all the user input has been retrieved, all that is left to do is call the actual filtering on the ImageProcessor
object, which the run
method receives as an argument. This is done with the rank
method of the RankFilters
class with appropriate parameters.
Can we build the GUI in the setup
method? There is nothing that prevents us from doing that, but consider this: This method is used to check whether the plugin can work with an active image. This check is done after the appropriate constants are returned. If we build the dialog here, the dialog will pop up even if there are no images open or if they are of the wrong type, which is a waste of time for the user if the plugin cannot be finally applied.
You can also create your GUI using AWT or swing components, but consider an advantage of using the
GenericDialog
class: It also makes your plugin macro-compatible. That is, when you use it and give it certain parameters, it will emit a line in the recorder that you can then use to automatize your process.