2015-05-26 4 views
2

Для этого, вероятно, лучший вопрос/ответ, но то, что я нашел, не сработало, и у меня возникли проблемы с формулировкой вопроса для запроса google. В основном у меня есть JFrame с несколькими панелями и компонентами, которые извлекают данные из xml-файлов. Я использую переменную экземпляра JFrame private Date focusDate = new Date();, чтобы сохранить информацию о том, какой день я хочу, чтобы каждая панель отображалась, насколько это хорошо.Triggering Java GUI для обновления

Проблема возникает сейчас, когда я пытаюсь обновить различные действия компонентов навигации после изменения «focusDate». У меня есть панель инструментов в JPanel NavButtons navPanel = new NavButtons(focusDate);, которую я настраиваю как внутренний класс, а консольные отчеты focusDate меняются, но я не могу получить JFrame до validate(), repaint(), etc..., когда я вызываю свой метод setFocus(Date d).

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

public void setFocus(Date d) throws IOException { 
    focusDate = d; 

    dispose(); 
// validate(); //Tried revalidate too, but DisplayView extends JFrame 
// repaint(); 
// revalidate(); 
// pack(); 
// DisplayView view = new DisplayView(focusDate); 
    setVisible(true); } 

и вот как я устанавливаю ActionListener в конструкторе:

public NavButtons(Date d) { 
    newDate = LocalDate.parse(new SimpleDateFormat("yyyy-MM-dd").format(d)); 

     weekBack.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       newDate = newDate.plusDays(-7); 
       try { setFocus(Date.from(newDate.atStartOfDay(ZoneId.systemDefault()).toInstant())); 
       } catch (IOException e) { 
        e.printStackTrace(); } 
       //validate(); 
       //repaint(); 
       } 
     }); 

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

Update Вот вся JFrame

package interfaceComponents; 

import javax.swing.*; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.event.*; 
import java.io.IOException; 
import java.text.*; 
import java.util.*; 
import java.time.*; 

public class DisplayView extends JFrame { 
    //instance variables 
    private Date focusDate = new Date(); 

    //constructor 
    public DisplayView(Date d) throws IOException { 
     DisplayMenus menus = new DisplayMenus(); 
     setJMenuBar(menus); 

     JPanel body = new JPanel(); 
     body.setLayout(new BoxLayout(body, BoxLayout.Y_AXIS)); 
     body.add(new DayView(focusDate)); 
     LocalDate focusNextDay = LocalDate.now(); 
     body.add(new DayView(Date.from(focusNextDay.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()))); 
     add(new JScrollPane(body), BorderLayout.CENTER); 

     JPanel footer = new JPanel(); 
     NavButtons navPanel = new NavButtons(focusDate); 
     JLabel focusPoint = new JLabel(new SimpleDateFormat("E, dd MMM yyyy").format(focusDate).toString()); 
     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 DisplayView() throws IOException { this(new Date()); } 

    public void setFocus(Date d) throws IOException { 
     focusDate = d; 

     SwingUtilities.updateComponentTreeUI(this); 
//  dispose(); 
//  invalidate(); 
//  validate();          //Tried revalidate too, but DisplayView extends JFrame 
     repaint(); 
//  revalidate(); 
//  pack(); 
//  DisplayView view = new DisplayView(focusDate); 
//  setVisible(true); 
     } 
    public Date getFocus() { return focusDate; }  

    class NavButtons extends JPanel { 
     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 JButton calendar = new JButton("L"); 
     private LocalDate newDate = LocalDate.now(); 

     public NavButtons(Date d) { 
      newDate = LocalDate.parse(new SimpleDateFormat("yyyy-MM-dd").format(d)); 

      weekBack.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        newDate = newDate.plusDays(-7); 
        try { setFocus(Date.from(newDate.atStartOfDay(ZoneId.systemDefault()).toInstant())); 
        } catch (IOException e) { 
         e.printStackTrace(); } 
//     invalidate(); 
//     validate(); 
//     repaint(); 
        } 
      }); 
      dayBack.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { newDate = newDate.plusDays(-1); } 
      }); 
      returnToday.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { newDate = LocalDate.now(); } 
      }); 
      nextDay.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { newDate = newDate.plusDays(1); } 
      }); 
      nextWeek.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { newDate = newDate.plusDays(7); } 
      }); 

      toolBar.add(weekBack); 
      toolBar.add(dayBack); 
      toolBar.add(returnToday); 
      toolBar.add(nextDay); 
      toolBar.add(nextWeek); 
      toolBar.add(new GalileoMode()); 
      toolBar.add(calendar); 
      add(toolBar); }   
    } 
} 

Как @MadProgrammer указывал, я должен иметь дату, сохраненную в отдельном объекте (как показано здесь):

package interfaceComponents; 

import java.util.*; 

public class FocusDate { 
    //instance variables 
    Date focus = new Date(); 

    //constructors 
    //intentionally blank: public FocusDate() {} 

    //methods: 
    public void setFocus(Date d) { 
     focus = d; } 
    public Date getFocus() { 
     return focus; } 
} 

и Я отредактировал рамку как таковую:

public class DisplayView extends JFrame { 
    //instance variables 
    FocusDate focus = new FocusDate(); 
// private Date focusDate = new Date(); 

    //constructor 
    public DisplayView(Date d) throws IOException { 
//  focusDate = d; 
     Date focusDate = focus.getFocus(); 

... 

    public void setFocus(Date d) throws IOException { 
//  focusDate = d; 
     focus.setFocus(d); 

Все еще не делает что-то правильно, хотя ...

+1

Посмотрите, поможет ли [этот вопрос] (http://stackoverflow.com/a/7630604/3547126). – goncalotomas

+1

Рассмотрите возможность запуска runnable примера вашей проблемы. Он удалит работу над угадкой и приведет к лучшим ответам. – MadProgrammer

+1

Какое решение должно было бы инкапсулировать дату внутри модели, которая передается каждому компоненту, который в ней нуждается. Модель позволит заинтересованным сторонам зарегистрировать обратный вызов, который будет уведомлять тогда, когда дата изменится, чтобы они могли предпринять соответствующие действия (как шаблон наблюдателя) – MadProgrammer

ответ

4

Итак, основная идея - обернуть «текущее» значение даты в наблюдаемом шаблоне и передать это каждой заинтересованной стороне. Это позволяет навигации вносить изменения в значение даты, но не нужно знать о какой-либо другой части программы, развязывать ее и допускать более гибкий результат.

Итак, я начал с двумя основными контрактами ...

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); 

} 

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

Затем я создал «по умолчанию» реализация модели ...

public class DefaultDateModel extends Observable implements MutableDateModel { 

    private LocalDate date; 

    public DefaultDateModel(LocalDate date) { 
     this.date = date; 
    } 

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

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

    @Override 
    public void removeObserver(Observer o) { 
     // I like the "remove" ;) 
     deleteObserver(o); 
    } 

} 

Я был ленив и используя Observer и Observable API от java.util, вы можете создавать свои собственные, исходя из ваших потребностей, но это просто подходит для примера.

Что это означает, что я могу создать экземпляр DefaultDateModel и передать его в те части программы, которые хотят DateModel и те, кто хочет MutableDateModel без необходимости создавать отдельные экземпляры, аккуратными.

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

в качестве примера ...

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.IOException; 
import java.time.LocalDate; 
import java.time.format.DateTimeFormatter; 
import java.util.Observable; 
import java.util.Observer; 
import javax.swing.BoxLayout; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JToolBar; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class DisplayView extends JFrame { 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 
       DisplayView view = new DisplayView(); 
       view.setDefaultCloseOperation(EXIT_ON_CLOSE); 
       view.pack(); 
       view.setLocationRelativeTo(null); 
       view.setVisible(true); 
      } 
     }); 
    } 

    //constructor 
    public DisplayView(LocalDate d) { 
//  DisplayMenus menus = new DisplayMenus(); 
//  setJMenuBar(menus); 

     DefaultDateModel model = new DefaultDateModel(d); 

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

     DayView nowView = new DayView(); 
     nowView.setModel(model); 
     DayView nextView = new DayView(1); 
     nextView.setModel(model); 

     body.add(nowView); 
     body.add(nextView); 
     add(new JScrollPane(body), BorderLayout.CENTER); 

     JPanel footer = new JPanel(); 
     NavButtons navPanel = new NavButtons(model); 
     JLabel focusPoint = new JLabel(DateTimeFormatter.ISO_DATE.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 DisplayView() { 
     this(LocalDate.now()); 
    } 

    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); 

    } 

    public class DefaultDateModel extends Observable implements MutableDateModel { 

     private LocalDate date; 

     public DefaultDateModel(LocalDate date) { 
      this.date = date; 
     } 

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

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

     @Override 
     public void removeObserver(Observer o) { 
      // I like the "remove" ;) 
      deleteObserver(o); 
     } 

    } 

    public class DayView extends JPanel implements Observer { 
     private JLabel dateLabel; 
     private DateModel model; 
     private int offset; 

     public DayView(int offset) { 
      this.offset = offset; 
      dateLabel = new JLabel("..."); 
      setLayout(new GridBagLayout()); 
      add(dateLabel); 
     } 

     public DayView() { 
      this(0); 
     } 

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

     public DateModel getModel() { 
      return model; 
     } 

     protected void updateLabel() { 
      DateModel model = getModel(); 
      if (model != null) { 
       LocalDate offsetDate = model.getDate().plusDays(offset); 
       dateLabel.setText(DateTimeFormatter.ISO_DATE.format(offsetDate)); 
      } else { 
       dateLabel.setText("..."); 
      } 
     } 

     @Override 
     public void update(Observable o, Object arg) { 
      updateLabel(); 
     } 

    } 

    class NavButtons extends JPanel implements Observer { 

     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 JButton calendar = new JButton("L"); 

     private MutableDateModel model; 

     public NavButtons(MutableDateModel model) { 
      weekBack.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        MutableDateModel model = getModel(); 
        if (model != null) { 
         LocalDate newDate = model.getDate().minusDays(7); 
         model.setDate(newDate); 
        } 
       } 
      }); 
      dayBack.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        MutableDateModel model = getModel(); 
        if (model != null) { 
         LocalDate newDate = model.getDate().minusDays(1); 
         model.setDate(newDate); 
        } 
       } 
      }); 
      returnToday.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        MutableDateModel model = getModel(); 
        if (model != null) { 
         LocalDate newDate = LocalDate.now(); 
         model.setDate(newDate); 
        } 
       } 
      }); 
      nextDay.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        MutableDateModel model = getModel(); 
        if (model != null) { 
         LocalDate newDate = model.getDate().plusDays(1); 
         model.setDate(newDate); 
        } 
       } 
      }); 
      nextWeek.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        MutableDateModel model = getModel(); 
        if (model != null) { 
         LocalDate newDate = model.getDate().plusDays(7); 
         model.setDate(newDate); 
        } 
       } 
      }); 

      toolBar.add(weekBack); 
      toolBar.add(dayBack); 
      toolBar.add(returnToday); 
      toolBar.add(nextDay); 
      toolBar.add(nextWeek); 
//   toolBar.add(new GalileoMode()); 
      toolBar.add(calendar); 
      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 has change!! 
     } 

     protected void setFocus(LocalDate newDate) { 
      // No idea what this is suppose to do... 
     } 

    } 
} 

о, я бы отчасти избежать перемещения между java.util.Date и java.time.LocalDate, если вы можете, для ваших целей, я бы придерживаться LocalDate, но это я;)

+1

Удивительно! Большое спасибо за это и все остальные ваши ответы, которые я читал. Тщательно очистите и покажите мне, что именно мне не хватает. –

+0

@JamesLingo Glad это могло бы помочь – MadProgrammer

+0

Отлично. Каким был бы ваш совет, если бы я хотел использовать что-то другое, кроме 'Observer' и' Observable'? Если бы я хотел, чтобы мой собственный API не должен был расширять эти Interfac в любом случае? – goncalotomas

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