我有一个小程序,它从JDateChooser组件输入日期,并计算从现在到输入日期的天数。它使用MVC模式,在Netbeans IDE中编码,并计算正确的天数,但不会在“labelDays”(JLabel)中显示。当我输入labelDays.setText(“29”)时,它可以工作,当我获得labelDays.getText()的值时,它会检索到未来的正确天数,并且strDays是正确的,但标签不会显示更新的值。以下是示例代码:
model:
public class CountDownModel {
public LocalDate getCurrentDate() {
return LocalDate.now();
}
public long getDays(LocalDate futureDate) {
long daysBetween = DAYS.between(LocalDate.now(), futureDate);
if(daysBetween <= 0) {
return 0;
}
return daysBetween;
}
view:
public class CountDownView extends javax.swing.JFrame {
...
private CountDownController controller = new CountDownController();
public CountDownView() {
initComponents();
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
future_date.setDate(output);
}
private void button_calculateMouseClicked(java.awt.event.MouseEvent evt) {
Date futureDate;
futureDate = future_date.getDate();
String strDate = DateFormat.getDateInstance().format(futureDate);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MMM-yyyy");
LocalDate localDate = LocalDate.parse(strDate, formatter);
controller.setDays(localDate);
}
...
public void setDays(long days) {
String strDays = String.valueOf(days);
System.out.print("strDays:");
System.out.println(strDays);
String oldValue = labelDays.getText();
labelDays.setText(strDays);
labelDays.paintImmediately(labelDays.getVisibleRect());
String newValue = labelDays.getText();
System.out.print("oldValue:");
System.out.println(oldValue);
System.out.print("newValue:");
System.out.println(newValue);
System.out.println("================");
}
}
controller:
public class CountDownController {
public void startApplication() {
CountDownView view = new CountDownView();
view.setDays(0);
view.setVisible(true);
}
public void setDays(LocalDate futureDate) {
CountDownModel model = new CountDownModel();
CountDownView view = new CountDownView();
long longDays = model.getDays(futureDate);
if(longDays <= 0) {
longDays = 0;
}
view.setDays(longDays);
}
}
main:
public class DateCountDown {
public static void main(String[] args) {
// TODO code application logic here
CountDownController controller = new CountDownController();
controller.startApplication();
}
}
Output:
run:
strDays:0
oldValue:200
newValue:0
================
strDays:28
oldValue:200
newValue:28
================
感谢。我需要做些什么来使它工作? PS:我想知道我的错误是否是由于我设置MVC的方式。
菲利普
答案 0 :(得分:0)
我发现在这里设置MVC有点奇怪。
首先,我认为没有理由每次你CountDownView
时重新创建setDays
。这可能是标签未显示其新文本的原因 - CountDownView
的新实例可能根本不可见:CountDownView
的旧实例可见,而新实例则不可见。因此,这里控制器可以将CountDownView
的实例作为对象级字段。关于CountDownModel
我可以这么说。
此外,视图会创建自己的控制器,但效率不高,因为会导致交联和内存泄漏。我认为CountDownView
的构造函数可以接受CountDownController
的实例作为agrument,并将其存储为对象级弱引用。
此外,通常的做法是在Runnable
的新实例中启动所有Swing作业,例如:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
CountDownController controller = new CountDownController();
controller.startApplication();
}
});
您可以通过以下方式修改代码(希望有所帮助):
model:
public class CountDownModel {
public LocalDate getCurrentDate() {
return LocalDate.now();
}
public long getDays(LocalDate futureDate) {
long daysBetween = DAYS.between(LocalDate.now(), futureDate);
if(daysBetween <= 0) {
return 0;
}
return daysBetween;
}
}
view:
public class CountDownView extends javax.swing.JFrame {
...
private WeakReference<CountDownController> controller;
public CountDownView(CountDownController controller) {
this.controller = new WeakReference<>(controller);
initComponents();
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
future_date.setDate(output);
}
private void button_calculateMouseClicked(java.awt.event.MouseEvent evt) {
Date futureDate;
futureDate = future_date.getDate();
String strDate = DateFormat.getDateInstance().format(futureDate);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MMM-yyyy");
LocalDate localDate = LocalDate.parse(strDate, formatter);
controller.get().setDays(localDate);
}
...
public void setDays(long days) {
String strDays = String.valueOf(days);
System.out.print("strDays:");
System.out.println(strDays);
String oldValue = labelDays.getText();
labelDays.setText(strDays);
labelDays.paintImmediately(labelDays.getVisibleRect());
String newValue = labelDays.getText();
System.out.print("oldValue:");
System.out.println(oldValue);
System.out.print("newValue:");
System.out.println(newValue);
System.out.println("================");
}
}
controller:
public class CountDownController {
private CountDownView view;
private CountDownModel model;
public void startApplication() {
view = new CountDownView(this);
model = new CountDownModel();
view.setDays(0);
view.setVisible(true);
}
public void setDays(LocalDate futureDate) {
long longDays = model.getDays(futureDate);
if(longDays <= 0) {
longDays = 0;
}
view.setDays(longDays);
}
}
main:
public class DateCountDown {
public static void main(String[] args) {
// TODO code application logic here
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
CountDownController controller = new CountDownController();
controller.startApplication();
}
});
}
}