2013-04-10 5 views
0

это моя проблема с Swing:
Представьте кадр с одним текстовым полем и одной кнопкой. За этим кадром есть класс данных с одним полем.
Приоритет событий

  • TextField имеет FocusListener, который обновляет поле класса данных со значением в текстовом поле на FocusOut
  • кнопку
  • имеют ActionListener, который посылает класс данных на сервер по щелчку

если я изменить значение в текстовом поле и нажмите кнопка сразу, dataclass со старым значением иногда отправляется на сервер. Мне кажется, что нет гарантии, что событие FocusOut текстового поля будет обработано до события ActionPerformed кнопки. Если да, есть ли способ защитить его? Я имею в виду какой-то чистый способ, я не хочу, чтобы все было грязно, если не нужно.

+0

Что такое 'FocusOut'? Я никогда не слышал об этом событии. – camickr

+0

недавнее QA показывает [валидность формы [плохого человека]] (http://stackoverflow.com/a/14041811/203657) - для более развитого элемента управления рассмотрите использование структуры проверки, например f.i. JGoodies. Не мой день для тщательного чтения ;-) только что заметил, что ваш вопрос связан с управлением привязкой и проверкой: оберните действие фиксации в SwingUtilities.invokeLater, чтобы гарантировать, что сначала нужно перенести значение поля в класс данных перед фиксацией. – kleopatra

ответ

1

если я изменить значение в текстовом поле и нажмите кнопку сразу, со старым класса-данными является значением иногда отправляется на сервер. Мне кажется, что нет гарантии, что событие FocusOut текстового поля будет обработано до события ActionPerformed кнопки. Если да, есть ли способ защитить его?

Дизайн формы по-разному. То есть, когда вы нажимаете кнопку, ActionListener должен вызывать метод getText() во всех текстовых полях формы.

+0

простейшим, спасибо –

1

вы можете сделать это так. Я только даю псевдокод.

private boolean check = false; 

txtField FocusOutMethod { 
check = true; 
} 

button ActionPerformedMethod(){ 

if(check){ 

     place your code that you want to execute in button click. 

     check = false; 
} 
} 

К этому методу actionPerformed будет работать только код после выполнения этого focusOut метода.

+0

не было никакого преступления, но это именно то, что я имел в виду под строкой, в которой я не хочу обманывать :) Также у меня такое чувство, что если бы я сделал это так, пользователю пришлось бы дважды нажать кнопку если actionPerformed обрабатывается до того, как FocusOut –

+1

щелкнет по кнопке, пользователь сначала поместит мышь над этой кнопкой, чтобы вы также могли использовать свойство MouseEntered этой кнопки для вызова того же кода, который вы хотите выполнить в FocusOut ....:). Я надеюсь, что это сработает и выполнит ваши требования .... –

+0

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

1
  • не представляется возможным в свинге, есть не возможен упорядочение событий из одного слушателя не в том случае, если два или более Слушатель стрельбы события concurently

если я изменить значение в текстовом поле и нажмите кнопку сразу, dataclass со старым значением иногда отправляется на сервер. Мне кажется , что нет гарантии, что событие FocusOut текстового поля будет обработано до события ActionPerformed кнопки. Если это так, есть ли способ обеспечить его безопасность ? Я имею в виду какой-то чистый способ, я не хочу, чтобы все грязно об этом, если не нужно.

  • Фокуса асинхронно, но во всех случаях стрельбы надлежащего события, проблема может быть в вашем коде

  • некоторых комбинации Приёмников могут вызвана вполне бесконечный цикл (события увольняют Атмосферостойкие задержки), то ваш контроллер может стрелять неправильные заказы события

+0

Я добавил sysouts своим слушателям, их порядок обработки является чисто случайным. Я боюсь, что у меня осталось ничего, кроме грязных вещей ... которые, кстати, не обязательно должны были бы быть плохими, если бы программа не была задействована :-) –

+0

добавить DocumentListener в JTextComponent, тогда все изменения будут ... , обратите внимание, но как возможно, что ', который обновляет поле класса данных со значением в текстовом поле на FocusOut', потребляет много времени ???, просто удалите, отключите, измените это – mKorbel

2

Просто для удовольствия, однонаправленное связывание бедных людей, реализованное с помощью InputVerifier: обратите внимание, что гарантированно будет доступен входной драйвер, прежде чем передавать фокус (и, похоже, работает в текущих версиях jdk), возникли некоторые проблемы в более ранних версиях из них), так что делать какие-либо обновления в проверяющего должны быть безопасными, пока передача фокуса участвует в фиксации действия:

верификатор, и некоторые сырой объект данных:

/** 
* Very simple uni-directional binding (component --> data) class. 
*/ 
public static class BindingVerifier extends InputVerifier { 

    private RawData data; 
    private boolean first; 
    public BindingVerifier(RawData data, boolean first) { 
     this.data = data; 
     this.first = first; 
    } 


    @Override 
    public boolean shouldYieldFocus(JComponent input) { 
     String text = ((JTextComponent) input).getText(); 
     if (first) { 
      data.one = text; 
     } else { 
      data.two = text; 
     } 
     return true; 
    } 


    @Override 
    public boolean verify(JComponent input) { 
     return true; 
    } 

} 

public static class RawData { 
    String one; 
    String two; 
    public RawData(String one, String two) { 
     this.one = one; 
     this.two = two; 
    } 

    public String toString() { 
     return one + "/" + two; 
    } 
} 

Использование:

final RawData data = new RawData(null, null); 
JTextField first = new JTextField(20); 
first.setInputVerifier(new BindingVerifier(data, true)); 
JTextField second = new JTextField(20); 
second.setInputVerifier(new BindingVerifier(data, false)); 
Action commit = new AbstractAction("commit") { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println(data); 
    } 
}; 
JComponent form = new JPanel(); 
form.add(first); 
form.add(second); 
form.add(new JButton(commit)); 
Смежные вопросы