首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用java中的MVC模式更新GUI

如何使用java中的MVC模式更新GUI
EN

Stack Overflow用户
提问于 2014-04-01 06:15:32
回答 2查看 2.5K关注 0票数 0

在java中使用MVC模式:我有5个类(视图(GUI)、控制器、模型、Class1和Class2)。当我单击“开始”按钮时,控制器启动模型中的一个线程,然后启动另外两个线程T1 (在类1中实现)&T2(在class2中实现)。

T1应该在JTextArea-1上显示一些信息,然后5秒后,T2应该从JTextArea-1中删除数据并粘贴到JTextArea-2。

我让T1工作了。它将信息显示在JTextArea-1上。但我关切的是,下一个步骤的开始及其实施。

T2如何与相同的模型对话并获得要调用的视图的相同更新方法,但要执行不同的操作集?

线程T1在class1中:

代码语言:javascript
复制
public void run() {

    while(!R.isFinished()) {

    System.out.println("inside kitchen thread");
    String report="";int size =0;
    String str="";int tn=0;

    report = getOrderReport();
    size= report.length();

    for(int i=1;i<=size;i=i+43){
    try
    {
        Thread.sleep(1000);
        str = report.substring(i,i+43);
        tn=Integer.parseInt(str.substring(8,9));
        System.out.println("inside kitchen thread order seq num: " +OrderSeq.getInstance().getNext());
        OrderSeq.getInstance().setLog(str);
        R.receiveAnOrder(str,tn);
        }
    catch (Exception e) {
    System.out.println("Kitchen thread exception" + e.getStackTrace());
    }


}

在上面的代码中: R.receiveAnOrder(str,tn)与模型通信以更新视图。

我如何调用模型中的相同或可能另一个函数来使用来自另一个线程的详细信息更新视图?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-01 08:00:26

首先,您需要两个模型类。

你需要一份订单

代码语言:javascript
复制
public Order {

  private String name;

  public Order(String name) {
    this.name = name;
  }

  public String toString() {
    return name;
  }
}

还有一份订单清单

代码语言:javascript
复制
public OrderList extends DefaultListModel<Order> {

}

还有一个厨师来做命令

代码语言:javascript
复制
public void Cook extends Thread implements ActionListener {

  private OrderList waiting;

  private OrderList finished;

  private boolean keepCooking;

  public Cook(OrderList waiting, OrderList finished) {
    this.waiting = waiting;
    this.finished = finished;
    this.keepCooking = false;
  }

  public void run() {
    keepCooking = true;
    while (keepCooking) {
      if (orders.size() > 0) {
        try {
          currentOrder = orders.remove(0);
        } catch (Exception e) {
          // someone else emptied the list
        }
      }
      prepareOrder(order);
      if (keepCooking && orders.size() <= 0) {
        try {
          Thread.sleep(1000);
        } catch (Exception e) {
          // back to work
        }
      }
    }
 }

 public void prepareOrder(Order order) {
   try {
      Thread.sleep(Math.random() % 10000);
      finished.add(order);
    } catch (Exception e) {
      waiting.add(order);
    }
  }

  public void goHome() {
    keepCooking = false;
  }
}

你需要一些顾客来下订单

代码语言:javascript
复制
public Customers extends Thread {

  private OrderList orders;

  public Customers(OrderList orders) {
    this.orders = orders;
  }

  public void run() {
    int number = 0;
    while (true) {
      number++;
      try {
        Thread.sleep(Math.random() % 10000)
        orders.add(new Order(String.format("Order %d", number)));
      } catch (Exception e) {
        return;
      }
    }
  }
}

现在有一个组件来帮助配置控制器

代码语言:javascript
复制
public CloseKitchen extends AbstractAction {

  private Cook cook;

  public CloseKitchen(Cook cook) {
    super("Close Kitchen");
    this.cook = cook;
  }

  public void actionPerformed(ActionEvent e) {
    cook.goHome();
  }
}

..。在某个代码块中..。

代码语言:javascript
复制
// building the model
OrderList waiting = new OrderList();
OrderList finished = new OrderList();
Cook cook = new Cook(waiting, finished);
Customers customers = new Customers(waiting);

// attaching the view
somePanel.add(new JList(waiting));
somePanel.add(new JList(finished));

// building the controller plug-in
CloseKitchen closeKitchen = new CloseKitchen(cook);

// wiring the plugin into the controller
somePanel.add(new JButton(closeKitchen));

// show the view
somePanel.setVisible(true);

// start the cook and customers
cook.start();
customers.start();

您将看到订单在一个列表中填充,然后移到另一个列表中。也就是说,直到你点击“关闭厨房”按钮,然后厨师将goHome()和顾客将继续点菜。

有很多方法来实现库克和客户。我故意不使用ListDataListener实现来避免对模型需要使用什么的混淆。基本上,真正的模型不需要使用任何与其内部协调相关的swing,只要它能够适应正确的[List|Table|Button|...]Model接口。

票数 2
EN

Stack Overflow用户

发布于 2014-04-01 06:51:20

您可以让Views观察Model。这意味着每次线程更改Models数据时,都会更新所有已注册的视图。

代码语言:javascript
复制
T1     ---  uses `Controller` to manipulate `Model` (e.g. `Model`.value1) -->  `Controller`
T2    ---   uses `Controller` to manipulate `Model` (e.g. `Model`.value1) -->  `Controller`
`View1`  --- observes `Model`, shows Model.value1 on update --> `Model`
`View2`  --- observes `Model`, shows Model.value2 on update --> `Model`

因此,按照您的解释,T2将让Controller读取Model.value1,清除它并将值设置为Model.value2。当Controller更改Models值时,它会指示注册的Views更新(在您的示例中为2个视图)。因此,View1清除其JTextField,因为Model.value1为空,View2将其JTextField更新为Model.value2。

要实现视图的更新机制,请阅读教程中的观察者模式。

此外,请记住,来自线程的GUI操作(例如,SWING)必须由EventDispatcherThread (EDT)完成。SwingUtilities为此提供了一个函数。只需从其他线程运行所有GUI相关代码,如下所示:

代码语言:javascript
复制
SwingUtilities.invokeLater( new Runnable() {
    public void run() {
       //Do the gui stuff here
    }
});

阅读更多关于EDT和SwingUtitlities 这里的信息。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22778192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档