我知道编辑这个网站吗?
the original version of ImageJ本页介绍与 the original version of ImageJ 相关的内容。点击徽标查看详情。

通用对话框

简介

GenericDialog类是ImageJ的一部分,可用于为脚本和插件制作简单的图形用户界面。它比SciJavascript parameters功能需要更多的工作,但提供了更多的可能性。

Fiji 提供了额外的 PrefService 子类,其中包括额外的 GUI 项目,例如带浏览按钮的文件输入。

与脚本参数一样,使用GenericDialog(其余子类之一)的插件是可录制宏的。

在 Jython(或类似的脚本语言)中

这是 Jython 中的示例。

from ij.gui import GenericDialog

# Create an instance of GenericDialog
gui = GenericDialog("My first GUI")

# Add some gui elements (Ok and Cancel button are present by default)
# Elements are stacked on top of each others by default (unless specified)
gui.addMessage("Some information to display at the top of the gui")
gui.addStringField("Type some input text :", "initial text")
gui.addCheckbox("This is a tickbox->Activate some option", True)

# We can add elements next to each other using the addToSameRow method
gui.addToSameRow() # The next item is appended next to the tick box
gui.addChoice("Choose one option among a list", ["Choice1", "Choice2"], "Choice1") # Choice1 is default here

gui.addNumericField("Some integer", 10, 0) # 0 for no decimal part

# Add a Help button in addition to the default OK/Cancel
gui.addHelp(r"https://imagej.net/scripting/generic-dialog") # clicking the help button will open the provided URL in the default browser

# Show dialog, the rest of the code is not executed before OK or Cancel is clicked
gui.showDialog() # dont forget to actually display the dialog at some point


# If the GUI is closed by clicking OK, then recover the inputs in order of "appearance"
if gui.wasOKed():
    inString = gui.getNextString()
    inBool   = gui.getNextBoolean()
    inChoice = gui.getNextChoice() # one could alternatively call the getNextChoiceIndex too
    inNum    = gui.getNextNumber() # This always return a double (ie might need to cast to int)

###在宏语言中

有2个选项可以用ImageJ宏语言生成GUI。
如果只需要一个或几个参数,第一个选项很方便。
它将为每个请求的参数打开一个专用的输入窗口,即如果有多个参数,则依次显示多个窗口。

someNumber = getNumber("Some number", 0); // 0 is the default here
someString = getString("Some string", "DefaultValue");

可能的输入列表与对话框的第二个选项相同。
使用对话框(第二个选项),将显示一个包含所有参数的输入窗口。这比第一个选项需要更多的编码,但更优雅。

Dialog.create("My inputs");
Dialog.addMessage("Some message to display");

var min = 0;
var max = 10;
var default = 5;
Dialog.addSlider("Some slider", min, max, default);
Dialog.addNumber("Some number", 0);
Dialog.addString("Some string", "DefaultString");

Dialog.addChoice("Type:", newArray("8-bit", "16-bit", "32-bit", "RGB"));
Dialog.addCheckbox("Ramp", true);

// One can add a Help button that opens a webpage
Dialog.addHelp("https://imagej.net/ij/macros/DialogDemo.txt");

// Finally show the GUI, once all parameters have been added
Dialog.show();

// Once the Dialog is OKed the rest of the code is executed
// ie one can recover the values in order of appearance 
inNumber1 = Dialog.getNumber(); // Sliders are number too
inNumber2 = Dialog.getNumber();
inString  = Dialog.getString();
inChoice  = Dialog.getChoice();
inBoolean = Dialog.getCheckbox();

print("Number1:", inNumber1);
print("Number2:", inNumber2);
print(inString);
print("Choice:", inChoice);
print("Do something (1=True, 0=False):", inBoolean);

有关详细信息,请参阅第 Macro functions reference 的“/scripting/generic-dialog”部分。

图片和文件输入

默认情况下,脚本和插件处理最后选择的图像。
然而有时需要指定不同的图像或文件作为输入。
子类GenericDialogPlus这种情况提供了一些方法,而上面显示的所有方法都是从 GenericDialog 类继承的。

from fiji.util.gui import GenericDialogPlus

# Create an instance of GenericDialogPlus
gui = GenericDialogPlus("an enhanced GenericDialog")

# Add possibility to choose some images already opened in Fiji
gui.addImageChoice("Image1","Some description for image1")
gui.addImageChoice("Image2","Some description for image2")


# The GenericDialogPlus also allows to select files, folder or both using a browse button
gui.addFileField("Some_file path", "DefaultFilePath")
gui.addDirectoryField("Some_folder path", "DefaultFolderPath")
gui.addDirectoryOrFileField("Some_Path", "DefaultPath")

gui.showDialog()

# Recover the inputs in order of "appearance"
if gui.wasOKed():
    image1 = gui.getNextImage() # This method directly returns the ImagePlus object
    image2 = gui.getNextImage()

    # Path are recovered as string
    filePath   = gui.getNextString()
    folderPath = gui.getNextString()
    somePath   = gui.getNextString()

宏录制

就像脚本参数一样,使用 GenericDialog 类的插件是可宏记录的。
需要注意的每一件重要的事情是记录命令中变量的名称。该名称实际上是使用项目标签的字符串的第一个单词,仅包含小写字母。
大多数情况下,用一个词来理解一个参数不太容易理解。要在录制的命令中包含标签的下一个单词,补足空格替换为下划线,如上面的some_file所示。

例如,之前在 Fiji.app/scripts/Plugins/Test 中保存为 GUI_.py 的代码会生成以下记录命令:
run("GUI ", "image1=MyImage1.tif image2=MyImage2.tif some_file=DefaultFilePath some_folder=DefaultFolderPath some_path=DefaultPath");

使用 PrefService 调用以前的边境

在接下来运行给定插件时调用前面输入的参数很方便。对于脚本参数(不用以不同方式指定),这种情况会自动发生,但对于 GenericDialog 类则不会。
幸运的是,仍然可以使用 PrefService 进行工作。

服务是一些ImageJ2/SciJava功能,可以将其视为运行时的某种包导入。它们在原始ImageJ中不可用,因此在ImageJ中调用参数的另一种方法是使用临时文件来存储先前输入的参数。
这是GenericDialogPlus的链接。
下面是如何使用它的 Jython 示例。

#@ PrefService prefs 
from fiji.util.gui import GenericDialogPlus 

# Create GUI 
gui = GenericDialogPlus("Some GUI")

gui.addImageChoice("Image", prefs.get(None, "Image", "DefaultImage") ) 
gui.addCheckbox("Activate some option", prefs.getInt(None, "doOption", False) ) # in theory we should use the getBoolean method but it does not work for Jython, the wrong method signature is matched
gui.addStringField("Some_string", prefs.get(None, "someString", "initial")) 
gui.addChoice("Some_choice", ["Choice1","Choice2"], prefs.get(None, "someChoice", "DefaultChoice")) 
gui.addNumericField("Some_integer", prefs.getInt(None, "n", 1), 0)  
gui.addNumericField("Some_float", prefs.getFloat(None, "number", 0.5), 2) 

gui.showDialog() 

if gui.wasOKed(): 
    image      = gui.getNextImage() 
    doOption   = gui.getNextBoolean()
    someString = gui.getNextString() 
    someChoice = gui.getNextChoice() 
    n          = int(gui.getNextNumber()) # cast to int : getNextNumber always return a double
    number     = gui.getNextNumber()

    # Save in memory using PrefService 
    prefs.put(None, "image", image.getTitle()) 
    prefs.put(None, "doOption", doOption) 
    prefs.put(None, "someString", someString) 
    prefs.put(None, "someChoice", someChoice ) 
    prefs.put(None, "n", n) 
    prefs.put(None, "number", number) 

第一步是“导入”PrefService并指定一个名称,此处为prefs。

现在有两种方法分别从 PrefService 中恢复和存储一些参数值,即getput

让我们从get开始。该方法是针对不同的数据类型getIntgetFloatgetBoolean定义的。字符串例外,没有getString,只有get
另外,在 Jython 中,getBoolean 方法未映射正确的 Java 签名,因此请使用 getInt 代替,如上所示。

get方法有3个参数:

  1. 要关联参数持久性的插件类。将其保留为“无”(或在其他语言中为“空”)并使用默认值。 2.从内存/首选项中调用的参数名称,它应该与put该参数使用的名称的方法相同。 3.如果内存中不存在具有该运行名称的参数(即第一个脚本或重置首选项),则使用默认值。

方法put甚至更简单,因为只有一个方法也接受3个参数:

1.就像get一样,一个可选的Plugin类

  1. 用于在内存/首选项中存储参数值的名称,与 get 用于恢复先前输入的值的名称相同。
  2. 要使用参数 2 中的名称存储在内存中的值。如果该参数已存在于内存中,则该值将更新为新提供的值。

因此,在上面的脚本中,GenericDialog 字段的默认值被初始化为内存中可用的值,或者如果内存中缺少某些默认值。
GUI确定后,内存中的值将使用put方法用新输入的值进行更新。

自定义按钮

使用斐济提供的GenericDialogPlus,可以向添加GUI自定义按钮和相关操作。
为此,我们必须从 java.awt.event 导入 ActionListener 接口。
然后,我们创建一个实现这个接口的类,其中包含一个名为 actionPerformed 的方法,只要用户链接到这个事件监听类的项目(如按钮),就会交互调用该方法。
在下面的 jython 示例中,我们定义了 2 个按钮 A 和 B,它们都与名为 ButtonClic 的同一事件处理类关联。
如果单击任意按钮,则调用 ButtonClicactionPerformed 方法。但是事件的来源不同(按钮 A 或 B),因此我们可以为端点情况定义不同的命令来执行。
对于更复杂的情况,还可以创建不同的事件处理类来分配给不同的GUI项目集。

from fiji.util.gui    import GenericDialogPlus
from java.awt.event   import ActionListener


class ButtonClic(ActionListener):
    """Class which unique function is to handle the button clics"""

    def actionPerformed(self, event): # self (or this in Java) to state that the method will be associated to the class instances

        # Check from where comes the event 
        source = event.getSource() # returns the Button object
        print source 

        # Do an action depending on the button clicked
        if source.label == "A":
            print "You clicked A\n"

        elif source.label == "B":
            print "You clicked B\n"


gui = GenericDialogPlus("GUI with custom buttons")
clicRecorder = ButtonClic()      # Create an instance of the ButtonClic class
gui.addButton("A", clicRecorder) # Associate the buttons to an instance of the ButtonClic class
gui.addButton("B", clicRecorder)
gui.showDialog()