Запуск Java GUI для обновления

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

Моя проблема возникает сейчас, когда я пытаюсь настроить различные действия компонентов навигации для обновления после изменения "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(); 
                }
        });

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

Обновление Вот весь 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 ответ

Решение

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

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

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, но это я;)

Другие вопросы по тегам