2

これにはおそらくより良い質問/回答がありますが、私が見つけたことがうまくいかず、Googleクエリの質問の言い回しに問題がありました. 基本的に、xml ファイルからデータを取得するいくつかのパネルとコンポーネントを含む JFrame があります。JFrame のインスタンス変数を使用して、private Date focusDate = new Date();各パネルに表示する日付の情報を格納します。これまでのところ、問題ありません。

私の問題は、「focusDate」を変更した後、ナビゲーション コンポーネントのさまざまなアクションを更新するように設定しようとしているということです。NavButtons navPanel = new NavButtons(focusDate);内部クラスとして設定した JPanel にツールバーがあり、コンソールが変更を報告していますが、メソッドを呼び出すときにfocusDateJFrame を取得できません。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(); 
                }
        });

私はスイングにあまり詳しくないので、これは私が得ていない小さな詳細だと確信していますが、引数の受け渡しを再トリガーし、フレームの子コンポーネントをアマチュアに更新する方法を誰かが説明できる場合よろしくお願いします。

更新 ここに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);

まだ正しいことをしていませんが...

4

1 に答える 1

4

したがって、基本的な考え方は、「現在の」日付値を観察可能なパターンでラップし、これを各関係者に渡すことです。これにより、ナビゲーションは日付値を変更できますが、プログラムの他の部分について知る必要はなく、切り離してより柔軟な結果を可能にします。

それで、私は2つの基本的な契約から始めました...

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

}

1 つは変更不可 (日付を変更する必要のないプログラムの部分) で、もう 1 つは変更可能 (日付を変更できるプログラムの部分) です (ナビゲーションなど)。

次に、モデルの「デフォルト」実装を作成しました...

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

}

私は怠け者で、 のObserverObservableAPIを使用しjava.utilています。必要に応じて独自の API を作成できますが、これは例にぴったりです。

これが意味することは、 のインスタンスを作成して、 を必要と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、それは私です ;)

于 2015-05-27T00:51:39.853 に答える