使用java,我有一个包含多个JPanel的JFrame,其中包括各种JComboBox,JTextFields等...它们连接到xml文件中的条目,按日期组织和查看。一切都同步并正在工作,但是当我对条目进行更改(即添加/删除等)时,我一直无法更新/刷新JFrame,尽管它在我更改日期时会刷新。我已经到了我有一个触发的PropertyChangeListener(打印到控制台),但当我尝试使用该Listener刷新帧时,我想我只是重新验证了监听器?
以下是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再次被调用。 (重新)验证()和重绘()似乎没有这个问题,但他们没有刷新面板的内容......任何能指出我正确方向/链接到类似问题等的人都会非常感谢。
答案 0 :(得分: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(); }
});