2015-06-03 19 views
0

使用java,我有一個JFrame包含多個JPanels,其中包含各種JComboBoxes,JTextFields等......它們連接到xml文件中的條目,按日期組織和查看。一切都同步並且正在工作,但是我在更改/刷新條目(即添加/刪除等)時無法讓JFrame更新/刷新,儘管它在更改日期時會刷新。我已經到了我有一個PropertyChangeListener被觸發(打印到控制檯)的地步,但是當我嘗試使用該Listener刷新框架時,我認爲我只是重新驗證了偵聽器?使用PropertyChangeListener刷新JFrame(不觸發無限循環)

下面是從JFrame中(我用的話來表明發生故障的部分)的代碼:

package interfaceComponents; 

import java.beans.*; 
import javax.swing.*; 
import org.jdesktop.swingx.JXDatePicker; 
import java.awt.*; 
import java.awt.event.*; 
import java.text.*; 
import java.io.IOException; 
import java.util.*; 
import java.time.*; 
import java.time.format.*; 

public class DailyView extends Frame { 
    private static final long serialVersionUID = 7827570917642254745L; 
    private final JXDatePicker calendar = new JXDatePicker(); 
    private JLabel focusPoint; 

    public DailyView(LocalDate d) throws IOException { 
     DefaultDateModel model = new DefaultDateModel(d); 

     OperatorMenus menus = new OperatorMenus(); 
     setJMenuBar(menus); 

     JPanel body = new JPanel(); 
     body.setLayout(new BoxLayout(body, BoxLayout.Y_AXIS)); 

     DayView anchorDay = new DayView(0); 
     anchorDay.setModel(model); 
     DayView nextDay = new DayView(1); 
     nextDay.setModel(model); 

     body.addPropertyChangeListener(new PropertyChangeListener() { 
      public void propertyChange(PropertyChangeEvent evt) { 
       System.out.println("OperatorView.propertyChange"); 
       //***This is where I'm trying to TRIGGER the REFRESH*** 
       refreshFrame(); } 
     }); 
     body.add(anchorDay); 
     body.add(nextDay); 
     add(new JScrollPane(body), BorderLayout.CENTER); 

     JPanel footer = new JPanel(); 
     NavButtons navPanel = new NavButtons(model); 
     focusPoint = new JLabel(DateTimeFormatter.ofPattern("E, dd MMM yyyy").format(model.getDate())); 
     focusPoint.setForeground(Color.RED); 
     footer.setLayout(new BorderLayout()); 
     footer.add(focusPoint, BorderLayout.CENTER); 
     footer.add(navPanel, BorderLayout.EAST); 
     footer.setBackground(Color.BLACK); 
     add(footer, BorderLayout.SOUTH); 

     pack(); } 

    public DailyView() throws IOException { this(LocalDate.now()); } 

    //interfaces 
    public interface DateModel { 
     public LocalDate getDate(); 
     public void addObserver(Observer o); 
     public void removeObserver(Observer o); } 

    public interface MutableDateModel extends DateModel { 
     public void setDate(LocalDate date); } 

    //methods 
    public void refreshFrame() {  //***This is where I'm trying to TRIGGER the REFRESH*** 
     this.revalidate(); 
     this.repaint(); } 

    //inner classes 
    public class DefaultDateModel extends Observable implements MutableDateModel { 
     private LocalDate date; 

     public DefaultDateModel(LocalDate d) { date = d; }   

     @Override 
     public void setDate(LocalDate d) { 
      date = d; 
      setChanged(); 
      notifyObservers(); } 

     @Override 
     public LocalDate getDate() { 
      return date; } 

     @Override 
     public void removeObserver(Observer o) { 
      deleteObserver(o); } 
    } 

    public class ShiftFocus extends AbstractAction implements Observer { 
     private static final long serialVersionUID = 680383526965967229L; 
     private MutableDateModel model; 
     private int shift; 

     public ShiftFocus(MutableDateModel m, int i) { 
      setModel(m); 
      shift = i; } 

     public void actionPerformed(ActionEvent event) { 
      MutableDateModel model = getModel(); 
      if (model != null) { 
       model.setDate(model.getDate().plusDays(shift)); 
        calendar.setDate(Date.from(model.getDate().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())); 
       pack(); } 
     } 

     public void setModel(MutableDateModel value) { 
      if (model != null) { 
       model.removeObserver(this); } 
      this.model = value; 
      if (model != null) { 
       model.addObserver(this); } 
     } 

     public MutableDateModel getModel() { 
      return model; } 

     @Override 
     public void update(Observable o, Object arg) { 
      focusPoint.setText(DateTimeFormatter.ofPattern("E, dd MMM yyyy").format(model.getDate())); } 
    } 

    class NavButtons extends JPanel implements Observer { 
     private static final long serialVersionUID = 914087518688373731L; 

     //instance variables 
     private JToolBar toolBar = new JToolBar("Navigation"); 
     private JButton weekBack = new JButton("<<"); 
     private JButton dayBack = new JButton("<"); 
     private JButton returnToday = new JButton("Today"); 
     private JButton nextDay = new JButton(">"); 
     private JButton nextWeek = new JButton(">>"); 
     private MutableDateModel model; 

     //constructor 
     public NavButtons(MutableDateModel model) { 
      weekBack.addActionListener(new ShiftFocus(model, -7)); 
      dayBack.addActionListener(new ShiftFocus(model, -1)); 
      returnToday.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        MutableDateModel m = getModel(); 
        m.setDate(LocalDate.now()); 
        setModel(m); 
        pack(); } 
      }); 
      nextDay.addActionListener(new ShiftFocus(model, 1)); 
      nextWeek.addActionListener(new ShiftFocus(model, 7)); 

      toolBar.add(weekBack); 
      toolBar.add(dayBack); 
      toolBar.add(returnToday); 
      toolBar.add(nextDay); 
      toolBar.add(nextWeek); 

      calendar.setEditable(true); 
      calendar.setFormats("E, dd MMM yyyy"); 
      calendar.setDate(Date.from(model.getDate().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())); 
      calendar.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        MutableDateModel model = getModel(); 
        if (model != null) { 
         model.setDate(LocalDate.parse(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getDate()))); 
         pack(); } 
       } 
      }); 
      toolBar.add(calendar); 
      toolBar.add(new GalileoMode()); 

      add(toolBar); 
      setModel(model); }   

     public void setModel (MutableDateModel value) { 
      if (model != null) { 
       model.removeObserver(this); } 
      this.model = value; 
      if (model != null) { 
       model.addObserver(this); } 
     } 
     public MutableDateModel getModel() { 
      return model; } 

     @Override 
     public void update(Observable o, Object arg) {/* models data changes */} 
    } 
} 

編輯

一些反饋後,到目前爲止,已經試過這樣:

 thisFrame = this; 
     body.addPropertyChangeListener(new PropertyChangeListener() { 
      public void propertyChange(PropertyChangeEvent evt) { 
       System.out.println("OperatorView.propertyChange"); 
//    thisFrame.removeAll(); 
//    thisFrame.dispose(); 
//    thisFrame.remove(body); 
//    thisFrame.add(new JScrollPane(body),  BorderLayout.CENTER); 
       thisFrame.getContentPane().validate(); 
//    thisFrame.revalidate(); 
       thisFrame.getContentPane().repaint(); 
//    thisFrame.refreshFrame(); 
       } 
     }); 

DailyView thisFrame;聲明爲實例變量at 頂端。

編輯

如果還有人在那裏讀這篇文章,我收到的PropertyChangeListener觸發,將刷新基礎面板的某些事件,但導致一個無限循環的的PropertyChangeListener被再次調用。 (重新)validate()和repaint()似乎沒有這個問題,但他們不刷新面板的內容...任何人可以指向我在正確的方向/鏈接到類似的問題等將是不勝感激。

+0

現在我使用計時器刷新每隔幾秒鐘的JFrame,但我寧願避免,如果可能的話。 –

回答

1

當您使用'this'指針時,它總是指您所在的類。我相信您的問題即將到來,因爲'this'指針確實指向您的偵聽器而不是JPanel。也許你的問題可以通過解決

Frame thisFrame = this; 
body.addPropertyChangeListener(new PropertyChangeListener() { 
     public void propertyChange(PropertyChangeEvent evt) { 
      System.out.println("OperatorView.propertyChange"); 
      //***This is where I'm trying to TRIGGER the REFRESH*** 
      thisFrame.refreshFrame(); } 
    }); 
+0

這似乎沒有工作。 Eclipse希望將thisFrame聲明爲最終變量(我也嘗試將它聲明爲實例變量)。我應該從'refreshFrame()'方法中刪除'this.'嗎?另外,不會'thisFrame'與我試圖刷新的實例不同嗎? –

+0

奇怪,所以當我用'thisFrame.removeAll()'替換'thisFrame.refreshFrame()'時,監聽器擦除了JFrame(我猜我回答了關於實例的問題),但是當我切換到'thisFrame.validate ); thisFrame.repaint();'仍然沒有快樂:( –

+0

嘗試thisFrame.remove(body)/ add(body),但這會導致無限循環... –