我正在阅读“SWT和JFace绝对指南”,并且试图理解以下代码:

public class MultipleListenersExample implements HelpListener, VerifyListener,
  ModifyListener{

    // Constants used for conversions
    private static final double FIVE_NINTHS = 5.0 / 9.0;
    private static final double NINE_FIFTHS = 9.0 / 5.0;

    // Widgets used in the window
    private Text fahrenheit;
    private Text celsius;
    private Label help;

    /**
     * Runs the application
     */
    public void run() {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Temperatures");
        createContents(shell);
        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }

    /**
     * Create the main window's contents
     * @param shell the main window
     */
    private void createContents(Shell shell) {
        shell.setLayout(new GridLayout(3, true));

        // Create the label and input box for Fahrenheit
        new Label(shell, SWT.LEFT).setText("Fahrenheit:");
        fahrenheit = new Text(shell, SWT.BORDER);
        GridData data = new GridData(GridData.FILL_HORIZONTAL);
        data.horizontalSpan = 2;
        fahrenheit.setLayoutData(data);

        // Set the context-sensitive help
        fahrenheit.setData("Type a temperature in Fahrenheit");

        // Add the listeners
        fahrenheit.addHelpListener(this);
        fahrenheit.addVerifyListener(this);
        fahrenheit.addModifyListener(this);

        // Create the label and input box for Celsius
        new Label(shell, SWT.LEFT).setText("Celsius:");
        celsius = new Text(shell, SWT.BORDER);
        data = new GridData(GridData.FILL_HORIZONTAL);
        data.horizontalSpan = 2;
        celsius.setLayoutData(data);

        // Set the context-sensitive help
        celsius.setData("Type a temperature in Celsius");

        // Add the listeners
        celsius.addHelpListener(this);
        celsius.addVerifyListener(this);
        celsius.addModifyListener(this);

        // Create the area for help
        help = new Label(shell, SWT.LEFT | SWT.BORDER);
        data = new GridData(GridData.FILL_HORIZONTAL);
        data.horizontalSpan = 3;
        help.setLayoutData(data);
    }

    /**
     * Called when user requests help
     */
    public void helpRequested(HelpEvent event) {
        // Get the help text from the widget and set it into the help label
        help.setText((String) event.widget.getData());
    }

    /**
     * Called when the user types into a text box, but before the text box gets
     * what the user typed
     */
    public void verifyText(VerifyEvent event) {
        // Assume you don't allow it
        event.doit = false;

        // Get the character typed
        char myChar = event.character;
        String text = ((Text) event.widget).getText();
        System.out.println(text);

        // Allow '-' if first character
        if (myChar == '-' && text.length() == 0) event.doit = true;

        // Allow zero to nine
        if (Character.isDigit(myChar)) event.doit = true;

        // Allow backspace
        if (myChar == '\b') event.doit = true;
    }

    /**
     * Called when the user modifies the text in a text box
     */
    public void modifyText(ModifyEvent event) {
        // Remove all the listeners, so you don't enter any infinite loops
        celsius.removeVerifyListener(this);
        celsius.removeModifyListener(this);
        fahrenheit.removeVerifyListener(this);
        fahrenheit.removeModifyListener(this);

        // Get the widget whose text was modified
        Text text = (Text) event.widget;

        try {
            // Get the modified text
            int temp = Integer.parseInt(text.getText());

            // If they modified Fahrenheit, convert to Celsius
            if (text == fahrenheit) {
                celsius.setText(String.valueOf((int) (FIVE_NINTHS * (temp - 32))));
            } else {
            // Convert to Fahrenheit
                fahrenheit.setText(String.valueOf((int) (NINE_FIFTHS * temp + 32)));
            }
        } catch (NumberFormatException e) { /* Ignore */ }

        // Add the listeners back
        celsius.addVerifyListener(this);
        celsius.addModifyListener(this);
        fahrenheit.addVerifyListener(this);
        fahrenheit.addModifyListener(this);
    }

    /**
     * The application entry point
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new MultipleListenersExample().run();
    }

}

在“modifyText”方法中,它删除了所有侦听器(VerifyListenerModifyListener),我不明白为什么?为什么出现无限循环?

最佳答案

因为您实际上是在modifyText() GUI元素的Text方法中修改文本字符串(值),所以这种文本更改将触发ModifyEvent,它再次调用modifyText()方法。因此,您必须删除这些侦听器,将文本更改为适当的值,然后再添加这些侦听器,否则会发生无限循环。

编辑(基于评论)

你是对的。首先,您在Text字段中键入密钥,然后调用verifyText()。完成此方法并批准键入的文本后,将调用modifyText()方法。就像我之前说的,此方法通过Text方法更改setText()字段的文本字符串。因此,在实际更改文本字符串之前,会先调用verifyText()并批准新的文本字符串,然后转到modifyText()方法,该方法实际上应更改Text GUI元素内的文本,但它会尝试调用该元素的setText()并再次开始循环。

因此,您在Text元素中键入一些数字(例如'5'),然后调用verifyText(),然后调用modifyText(),然后调用setText(),再次调用verifyText()modifyText(),再调用setText(),依此类推。等等。哦,是的,无限循环在这里。

09-13 13:05