Запуск 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
, но это я;)