1

使用 java,我有一个 JFrame,其中包含多个 JPanel,其中包括各种 JComboBoxes、JTextFields 等……它们连接到 xml 文件中的条目,按日期组织和查看。一切都同步并且正在工作,但是当对条目进行更改(即添加/删除等)时,我一直无法让 JFrame 更新/刷新,尽管当我更改日期时它会刷新。我已经到了触发 PropertyChangeListener(打印到控制台)的地步,但是当我尝试使用该侦听器刷新框架时,我认为我只是在重新验证侦听器?

这是来自 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;顶部声明为实例变量。

编辑

万一有人在读这篇文章,我会让 propertyChangeListener 触发某些事件,这些事件会刷新底层面板,但是当 propertyChangeListener 再次被调用时,这会导致无限循环。(re)validate() 和 repaint() 似乎没有这个问题,但他们没有刷新面板的内容......任何可以指出我正确方向/链接到类似问题等的人都会是非常感激。

4

1 回答 1

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(); }
    });
于 2015-06-03T20:13:54.573 回答