2015-10-08 4 views
0

Я пытаюсь написать программу, в которой будут показаны два Jtextareas, оба из которых доступны для редактирования. Цель заключается в том, когда вы редактируете textAreaRom (ввод римской цифры), вторая область (textAreaArab) отображает эквивалент арабского номера. Но дело в том, что я не могу заставить это случиться в режиме реального времени. Я читал об использовании DocumentListeners, но это один из первых случаев, когда я когда-либо делал программирование графического интерфейса, и я не уверен, как это реализовать. Все помогает. Я новичок в GUI, а также StackOverflow.Обновление в реальном времени одного JtextArea из другого JtextArea

Примечание: Мои методы преобразования все работают отлично.

public class ArabicToRomanGUI_Hard extends JFrame 
{ 
private static final long serialVersionUID = 1L; 
private static String input = ""; 
private static String output = ""; 

//constructor to add text fields to frame 
public ArabicToRomanGUI_Hard() 
{ 
    //JFrame frame = new JFrame("Convert Back And Forth"); 
    final JTextField enterRomNumber = new JTextField(20); 
    final JTextArea textAreaRom = new JTextArea(20,20); 
    final JTextField enterArabNumber = new JTextField(20); 
    final JTextArea textAreaArab = new JTextArea(20,20); 
    setLayout(new FlowLayout()); 
    enterRomNumber.setText("Please enter a Roman numeral"); 
    enterArabNumber.setText("Please enter a Arabic Number"); 

    textAreaRom.setEditable(true); 
    textAreaArab.setEditable(true); 

    //textAreaRom.setText(enterRomNumber.getText()); 
    //textAreaArab.setText(enterArabNumber.getText()); 

    if(textAreaRom.isFocusOwner() == true) 
    { 

     textAreaRom.addKeyListener(new KeyAdapter() 
      { 
       public void keyReleased(KeyEvent e) 
       {  
        { 
         e.getKeyChar(); 
         input += e.getKeyChar(); 
         ConversionLogic_Hard.ConvertFromRomanToArabic(input); //convert 
         ConversionLogic_Hard.getCheckFail(); //check if conversion is valid. 

         output = ConversionLogic_Hard.getConvertedRomanNumeral(); //get the conversion 

         while(ConversionLogic_Hard.getCheckFail() == true && textAreaArab.isFocusOwner() == false) 
         { 
          textAreaArab.setText(output); 
         } 
         textAreaArab.setText(input); 
        } 
       } 
      });    
     } 



    getContentPane().add(enterRomNumber, BorderLayout.EAST); 
    getContentPane().add(textAreaRom, BorderLayout.WEST); 
} 

ответ

0

Вы на самом деле есть три проблемы ...

  1. Обновления второго компонента текста, когда первый обновляются, который, относительно легко.
  2. Обновление первого текстового компонента при обновлении второго ... ну, что получило REAL сложный РЕАЛЬНЫЙ быстро.
  3. Отфильтруйте текст так, как он был введен. Это на самом деле довольно легко, Implementing a Document Filter

Теперь реальная проблема # 2, это происходит потому, что вы могли бы в конечном итоге в неприятную место очень быстро, как первое поле пытается обновить второе поле, которое вызывает и событие который заставляет второе поле обновлять первое поле, которое запускает и событие, которое заставляет первое поле обновлять второе поле ... и вы начинаете получать идею.

К счастью, Swing фактически не позволит ему получить, что плохо, и бросить IllegalStateException

Для более приходят это, вам нужно иметь какой-то способ, чтобы знать, когда обновление до Document это было вызвано по ведомому полю или когда он был вызван чем-то другим (например, setText был вызван, пользователь вводит или вставляет текст в поле) и игнорирует некоторые из этих событий.

Теперь, возможно, действительно классный и простой способ сделать это, но мой мозг сегодня не в «простом» режиме, извините.

Итак, я начинаю с обычаем Document, это в основном имеет флаг, который позволяет мне осмотреть его состояние

public class MirrorDocument extends PlainDocument { 

    private boolean ignoreUpdates; 

    public void setIgnoreUpdates(boolean ignoreUpdates) { 
     this.ignoreUpdates = ignoreUpdates; 
    } 

    public boolean isIgnoreUpdates() { 
     return ignoreUpdates; 
    } 

} 

Теперь я определяю DocumentListener для отслеживания изменений в Document. Это DocumentListener берет «раб» Document, который используется этим приемником для обновления

public static class DocumentHandler implements DocumentListener { 

    private MirrorDocument slaveDocument; 
    private boolean ignoreUpdates = false; 

    public DocumentHandler(MirrorDocument slaveDocument) { 
     this.slaveDocument = slaveDocument; 
    } 

    @Override 
    public void insertUpdate(DocumentEvent e) { 
     Document doc = e.getDocument(); 
     if (doc instanceof MirrorDocument) { 
      MirrorDocument md = (MirrorDocument) doc; 
      if (!md.isIgnoreUpdates()) { 
       try { 
        String text = e.getDocument().getText(e.getOffset(), e.getLength()); 
        slaveDocument.setIgnoreUpdates(true); 
        slaveDocument.insertString(e.getOffset(), text, null); 
       } catch (BadLocationException ex) { 
        ex.printStackTrace(); 
       } finally { 
        slaveDocument.setIgnoreUpdates(false); 
       } 
      } 
     } 
    } 

    @Override 
    public void removeUpdate(DocumentEvent e) { 
     Document doc = e.getDocument(); 
     if (doc instanceof MirrorDocument) { 
      MirrorDocument md = (MirrorDocument) doc; 
      if (!md.isIgnoreUpdates()) { 
       try { 
        slaveDocument.setIgnoreUpdates(true); 
        slaveDocument.remove(e.getOffset(), e.getLength()); 
       } catch (BadLocationException ex) { 
        ex.printStackTrace(); 
       } finally { 
        slaveDocument.setIgnoreUpdates(false); 
       } 
      } 
     } 
    } 

    @Override 
    public void changedUpdate(DocumentEvent e) { 
    } 

} 

Теперь, действительно Tripy части здесь вокруг ignoreUpdates флага. В принципе, то, что это делает, когда происходит событие, сначала проверить ignoreUpdates флаг Document, который вызвал событие, если это false, мы исходили установить ignoreUpdates флаг из slaveDocument в true, что предотвращает его DocumentListener от обработки любого нового а затем обновите slaveDocument

Хорошо, это может показаться немного странным, и мне очень жаль, но поверьте мне, это будет иметь смысл ... (однажды ...и когда это произойдет, вы можете объяснить это мне)

Таким образом, в следующем, мы должны создать все и приклеить его вообще ...

JTextArea left = new JTextArea(10, 20); 
    JTextArea right = new JTextArea(10, 20); 

    MirrorDocument leftDoc = new MirrorDocument(); 
    MirrorDocument rightDoc = new MirrorDocument(); 

    left.setDocument(leftDoc); 
    right.setDocument(rightDoc); 

    leftDoc.addDocumentListener(new DocumentHandler(rightDoc)); 
    rightDoc.addDocumentListener(new DocumentHandler(leftDoc)); 

Таким образом, мы создаем два JTextArea с, left и right , Мы создаем два MirrorDocument с, по одному для каждого JTextArea, затем мы создаем два DocumentHandler с, по одному для каждого JTextArea и обеспечить противоположную Document в качестве ведомого устройства (rightDoc для left и leftDoc для right), это позволяет случае переправиться и обновления для происходят

Это позволяет создать что-то вроде ...

MirroredTextAreas

import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.DocumentEvent; 
import javax.swing.event.DocumentListener; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.Document; 
import javax.swing.text.PlainDocument; 

public class MirrorTextAreas { 

    public static void main(String[] args) { 
     new MirrorTextAreas(); 
    } 

    public MirrorTextAreas() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      JTextArea left = new JTextArea(10, 20); 
      JTextArea right = new JTextArea(10, 20); 
      setLayout(new GridLayout(1, 2)); 

      add(new JScrollPane(left)); 
      add(new JScrollPane(right)); 

      MirrorDocument leftDoc = new MirrorDocument(); 
      MirrorDocument rightDoc = new MirrorDocument(); 

      left.setDocument(leftDoc); 
      right.setDocument(rightDoc); 

      leftDoc.addDocumentListener(new DocumentHandler(rightDoc)); 
      rightDoc.addDocumentListener(new DocumentHandler(leftDoc)); 
     } 

    } 

    public class MirrorDocument extends PlainDocument { 

     private boolean ignoreUpdates; 

     public void setIgnoreUpdates(boolean ignoreUpdates) { 
      this.ignoreUpdates = ignoreUpdates; 
     } 

     public boolean isIgnoreUpdates() { 
      return ignoreUpdates; 
     } 

    } 

    public static class DocumentHandler implements DocumentListener { 

     private MirrorDocument slaveDocument; 
     private boolean ignoreUpdates = false; 

     public DocumentHandler(MirrorDocument slaveDocument) { 
      this.slaveDocument = slaveDocument; 
     } 

     @Override 
     public void insertUpdate(DocumentEvent e) { 
      Document doc = e.getDocument(); 
      if (doc instanceof MirrorDocument) { 
       MirrorDocument md = (MirrorDocument) doc; 
       if (!md.isIgnoreUpdates()) { 
        try { 
         String text = e.getDocument().getText(e.getOffset(), e.getLength()); 
         slaveDocument.setIgnoreUpdates(true); 
         slaveDocument.insertString(e.getOffset(), text, null); 
        } catch (BadLocationException ex) { 
         ex.printStackTrace(); 
        } finally { 
         slaveDocument.setIgnoreUpdates(false); 
        } 
       } 
      } 
     } 

     @Override 
     public void removeUpdate(DocumentEvent e) { 
      Document doc = e.getDocument(); 
      if (doc instanceof MirrorDocument) { 
       MirrorDocument md = (MirrorDocument) doc; 
       if (!md.isIgnoreUpdates()) { 
        try { 
         slaveDocument.setIgnoreUpdates(true); 
         slaveDocument.remove(e.getOffset(), e.getLength()); 
        } catch (BadLocationException ex) { 
         ex.printStackTrace(); 
        } finally { 
         slaveDocument.setIgnoreUpdates(false); 
        } 
       } 
      } 
     } 

     @Override 
     public void changedUpdate(DocumentEvent e) { 
     } 

    } 

} 

Хорошо, так что примерно половина из того, что нам нужно, чтобы нам нужно было фильтровать содержимое, которое было введено в одно из полей, поэтому мы можем изменить его, это может быть выполнено Implementing a Document Filter

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