我正在阅读“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
),我不明白为什么?为什么会出现无限循环?
答案 0 :(得分:3)
因为您实际上是在modifyText()
GUI元素的Text
方法中修改文本字符串(值),所以此文本更改将触发ModifyEvent
再次调用modifyText()
方法。因此,您必须删除这些侦听器,将文本更改为适当的值并将这些侦听器添加回来,否则会发生无限循环。
编辑(根据评论)
你是对的。首先,您在Text
字段中键入密钥,然后调用verifyText()
。当此方法完成并且键入的文本被批准时,将调用modifyText()
方法。正如我之前所说,此方法通过Text
方法更改setText()
字段的文本字符串。因此,在实际更改文本字符串之前调用verifyText()
并批准新的文本字符串,然后转到modifyText()
方法,该方法应该实际更改Text
GUI元素内的文本,但它会尝试调用元素的setText()
并再次启动圆圈。
因此,您在Text
元素中键入了一些数字(如'5'
),verifyText()
被调用,modifyText()
跟随,它调用setText()
调用{再次{1}}和verifyText()
,它会调用modifyText()
,依此类推......哦,是的,无限循环就在这里..
答案 1 :(得分:1)
否则,当您拨打setText()
时,您会触发ModifyListener
,会调用setText()
,这会触发ModifyListener
...
答案 2 :(得分:1)
当您要更改会导致侦听器事件触发的内容时,通常会删除侦听器,而这又会调用再次更改该内容的方法。
编辑:删除了类比,因为它非常糟糕。