Событие бесконечного цикла SWT - PullRequest
3 голосов
/ 25 января 2012

Я читаю «Определенное руководство по 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" он удаляет всех слушателей (VerifyListener и ModifyListener), и я не понимаю, почему? Почему появляется бесконечный цикл?

Ответы [ 3 ]

3 голосов
/ 25 января 2012

Поскольку вы фактически изменяете текстовую строку (значение) в методе modifyText() элемента Text GUI, это изменение текста вызовет ModifyEvent, который снова вызывает метод modifyText(). Таким образом, вы должны удалить этих слушателей, изменить текст на соответствующее значение и добавить этих слушателей обратно, иначе произойдет бесконечный цикл.

РЕДАКТИРОВАТЬ (на основе комментариев)

Ты прав. Сначала вы вводите ключ в поле Text и вызывается verifyText(). Когда этот метод заканчивается, и печатный текст утверждается, вызывается метод modifyText(). И, как я сказал ранее, этот метод изменяет текстовую строку поля Text методом setText(). Поэтому, прежде чем текстовая строка может быть фактически изменена, вызывается verifyText() и утверждается новая текстовая строка, затем идет метод modifyText(), который должен фактически изменить текст внутри Text элемента GUI, но он пытается вызвать setText() из элемент и снова начинает круг.

Итак, вы вводите какое-то число в элемент Text (например, '5'), вызывается verifyText(), а затем следует modifyText(), вызывается setText(), что снова вызывает verifyText() и modifyText(), вызывается setText() и т. Д. Ах, да, здесь бесконечный цикл ..

1 голос
/ 25 января 2012

Обычно вы удаляете слушателей, когда собираетесь изменить что-то, что вызовет событие слушателя, что, в свою очередь, вызовет метод, который изменяет это что-то снова.

Редактировать: удалена аналогия, так какбыло довольно плохо.

1 голос
/ 25 января 2012

Потому что в противном случае при вызове setText() вы вызовете ModifyListener, который вызовет setText(), что вызовет ModifyListener ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...