2011-12-21 3 views
1

Я ищу эффективный метод для запуска изменения в наборе объектов после того, как было выполнено изменение ключевого объекта. Я хочу сделать следующее: Существует один объект, который при изменении выполняет метод в других объектах.Уведомление объектов о событии

Я пытался использовать PropertyChangeListener для достижения этой цели:

import java.awt.BorderLayout; 
import java.awt.Container; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.JButton; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class BoundSample { 
    public static void main(String args[]) { 
     JFrame frame = new JFrame("PropertyChangeListener Sample"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     final JButton button1 = new JButton("Open"); 
     final JButton button2 = new JButton("Cancel"); 

     final String[] languages = { "English", "Spanish" }; 

     final JComboBox combo = new JComboBox(languages); 

     final JPanel panel = new JPanel(); 


     ActionListener actionListener = new ActionListener() { 
      public void actionPerformed(ActionEvent actionEvent) { 
       JComboBox comboTmp = (JComboBox) actionEvent.getSource(); 

       if (combo.getSelectedItem().equals("English") || combo.getSelectedItem().equals("Ingles")) { 
        String[] langs = { "English", "Spanish" }; 
        comboTmp.setModel(new JComboBox(langs).getModel()); 
       } 
       else if (combo.getSelectedItem().equals("Spanish") || combo.getSelectedItem().equals("Espanol")) { 
        String[] langs = { "Ingles", "Espanol" }; 
        comboTmp.setModel(new JComboBox(langs).getModel()); 
       } 
      } 
     }; 

     PropertyChangeListener propertyChangeListener = new PropertyChangeListener() { 
      public void propertyChange(PropertyChangeEvent propertyChangeEvent) { 
       String property = propertyChangeEvent.getPropertyName(); 

       JComboBox comboTmp = (JComboBox) propertyChangeEvent.getSource(); 
       String language = (String) comboTmp.getItemAt(0); 

       System.out.println(language); 

       if ("model".equals(property)) { 
        if (language.equals("English")) { 
         button1.setLabel("Open"); 
         button2.setLabel("Cancel"); 
        } else if (language.equals("Ingles")) { 
         button1.setLabel("Abierto"); 
         button2.setLabel("Cancelar"); 
        } 

       } 
      } 
     }; 

     combo.addPropertyChangeListener(propertyChangeListener); 
     combo.addActionListener(actionListener); 

     Container contentPane = frame.getContentPane(); 
     panel.add(button1, BorderLayout.CENTER); 
     panel.add(button2, BorderLayout.SOUTH); 

     contentPane.add(combo, BorderLayout.NORTH); 
     contentPane.add(panel, BorderLayout.SOUTH); 

     frame.setSize(300, 100); 
     frame.setVisible(true); 
    } 
} 

Проблема такого подхода заключается в том, что с ростом числа объектов метод propertyChange() будет затратить и будет трудно управлять. Более того, чтобы добавить новый JComponent, мне также придется изменить свойствоChange().

Есть ли способ сделать это наоборот, сделав объекты «замеченными» для изменения ключевого объекта и заставить их действовать соответственно вместо того, чтобы воздействовать на них, выполняя действие в PropertyChangeListener ключа объект? Или, может быть, другой аккуратный способ сделать это?

+0

есть связывающие каркасы, которые берут на себя схему подключения, fi BetterBeansBinding или JGoodies Binding – kleopatra

ответ

2

Знаете ли вы, что observer pattern? Он делает то, что вы хотите: объекты будут регистрироваться на объекте, чтобы получать уведомление, когда что-то происходит.

observer pattern

3

Во-первых, рекомендация - всегда получить родной динамик, чтобы сделать свои переводы. Это помогает избежать определенных типов ошибок. Например, слово, которое вы выбрали в качестве замены для «открытого», обычно используется как прилагательное (как, например, «открытое окно»), а не как глагол, в то время как вы используете неопределенное время для «отмены». У вас также нет знаков акцента, которые могут сбивать с толку некоторые читатели (некоторые слова отличаются только от их акцентов ...).

Далее вы не должны выбирать язык жестов или использовать его; они должны быть загружены из файлов .properties или аналогичных. Это делает майнинг тривиальным, особенно при добавлении дополнительных языков. @ Ответ Морта об использовании шаблона наблюдателя правильный - вот как следует обрабатывать обновления. Вот (на самом деле грубо), как бороться с языковыми аспектами:
Сначала вам нужны файлы .properties.

spanishButtonNames.properties 
================================== 
openButton=Abrir 
cancelButton=Cancelar 

englishButtonNames.properties 
================================== 
opernButton=Open 
cancelButton=Cancel 

Вы хотите, чтобы обернуть их в какой-то PropertyManager, который будет иметь дело с загрузкой файлов ресурсов за кулисами, когда язык просят (и, возможно, освобождения ресурсов).

Далее, при создании кнопок, назовите их:

JButton openButton = new JButton(); 
openButton.setName("openButton"); 
// And add them to a list 
buttonList.add(openButton); 
// More buttons.... 

Обновлением пуговицы из списка кнопки затем тривиальные. Вы можете иметь только buttonList слушать (и распространение информации о) обновлений:

for(JButton button : buttonList) { 
    button.setText(languagePropertyManager.getProperty(button.getName())); 
} 

(Обратите внимание, что с каким-то умным кодированием, можно загрузить даже макет GUI из текстового файла, но я никогда не пробовал. Я считаю, что есть рамки, чтобы справиться с этим, однако.)

Смежные вопросы