如何更新/刷新GUI Swing组件(jpanel,jtable)? (专业人士的战略观点)

时间:2016-11-04 12:55:37

标签: java swing jtable jpanel getter-setter

我的问题是基于我最近决定升级的大型应用。 我的应用程序中有很多面板,表格需要在数据从服务器获得数据后刷新。由于应用程序的所有部分都是在不同的时间和不同的知识水平上编写的,所以我使用了不同的更新方法,我需要标准化。

现在我的问题是在刷新数据后更新组件的最佳方法(面板中的所有组件,其数量和内容都基于ArrayLists)来自下面的方法(或另一个,我没有&# 39; t计数)?我搜索的答案不是假设,而是基于文档的,为什么以这种方式实现更为正确。

我认为有更新组件的下一种方法:

  1. 在从服务器接收新数据的方法中,调用所需的容器并重新绘制()。
  2. 缺点:我只会在你打电话时工作,例如textfield.setText()。如果我只是替换此面板引用的ArrayList,这种方法就无法工作。

    我从服务器接收数据的代码(如果ADD我需要添加操作以更新某些面板或表格):

    public class ClientOperation {  
    private Socket socket;
    private ObjectInputStream cin;
    private ObjectOutputStream cout;
    private DataStorage data = new DataStorage();
    
    public static void main(String[] args) {
        ClientOperation client = new ClientOperation();
        client.clOperation();
    }
    
    public void clOperation() {
        try {
            socket = new Socket("localhost", 7800);     
            cin = new ObjectInputStream(socket.getInputStream());
            cout = new ObjectOutputStream(socket.getOutputStream());
            while ((request = (Request) cin.readObject()) != null) {
                switch (request.getType()) {
                case PROJECT:
                    switch (request.getAction()) {
                    case ADD:
                        data.getProjects().add((Base.Project) request.getData());
                        break;
                    }
                    break;
                 }
               }
            }
         }
    

    支持类作为发送对象的包:

    public class Request  implements Serializable{
    
    private static final long serialVersionUID = 1L;
    private CatalogEnum.Type type;
    private CatalogEnum.Action action;
    private Object data;
    
    public Request(CatalogEnum.Type type, CatalogEnum.Action action, Object data){
        this.type = type;
        this.action = action;
        this.data = data;
    }
    }
    
    1. 在从服务器接收新数据的方法中,调用所需的容器并使用updateUI()。
    2. 缺点:我发现这只是更新外观,所以它对我没有帮助。

      1. 在从服务器接收新数据的方法中,从容器中调用removeAll()的所有操作以添加所有新组件
      2. 缺点:每次创建容器都有很多动作,所以需要一个单独的类。

        另外:我通过一个单独的类实现了这种方式,所有方法都刷新了不同类的不同面板,并使用了面板的getter和setter。

        添加的缺点:我不得不创建很多面板和表格的例子。在我看来,将它们保存在记忆中是不正确的。但是,现在它是现在最好的方式。

        简而言之,我向您展示了这个代码:

        public class PanelContent implements PanelContentInterface {    
        private JPanel taskPanel = new JPanel();
        private DataStorage data;
        private JFrame mainwindow = new JFrame(nameFrame);
        
        public  JPanel getTaskPanel() {     
            taskPanel.updateUI();
            return taskPanel;
        }
        
        public void setTaskPanel() {
            taskPanel.removeAll();
        
            for (int i = 0; i<data.getProjects().size();i++){
                JButton btn = new JButton (data.getProjects().get(i).getTitle());
                taskPanel.add(btn);
            }
        
            this.taskPanel = taskPanel;
            mainframe.setContentPane(taskPanel);
        }
        public JFrame frameConstructor (JFrame mainframe, String nameFrame, JPanel panel) {
        mainframe.setTitle(nameFrame);
        mainframe.setJMenuBar(***.getMenuBar());
        panel.setBackground(Color.WHITE);
        mainframe.setContentPane(panel);
        mainframe.setVisible(true);
        return mainframe;
        }
        }
        

        想象一下,框架已经可见,如果在我通过在ClientOperation中初始化PanelContent来添加这样的行之前ADD代码示例:

            case ADD:
                data.getProjects().add((Base.Project) request.getData());
                panelContent.setTaskPanel();
                break;
        

        此代码有效。但是,它需要将所有面板分成基本和静态部件以及动态部件。

        1. 要上次操作,我们可以添加revalidate()
        2. 缺点:我知道在任何情况下都会调用此方法,因为根据文档更改了容器的基本参数,因此调用它不会产生影响。

          1. 对于Tables和ComboBoxes,我也可以提一下fireTableDataChanged()
          2. 缺点:我还读到如果模型有任何变化,会自动调用此方法。但我经常更换模型,而不是改变它,所以它不适合我。

            1. 至于我工作的方法是从服务器接收新数据调用表和setModel到它。
            2. 缺点:由于使用特殊类来设置所有模型,我必须保存并发送大量变量作为结构。示例如下。

              Panel.comboBox.setModel(Panel.model.comboBox(Panel.arraySchedule));
              

              最终,除了JPanels的方法3和JTables和JComboBoxes的方法6之外,我觉得相对合适。

              我要求您添加您的观点:

              如果您认为相同,可能会说我添加的缺点并不重要。

              如果你认为我做错了其他方法,你能否说出为什么他们更好是指它的属性。

              或者您有其他实践?

1 个答案:

答案 0 :(得分:0)

根据@trashgod的参考文献,我最后使用了混合更新系统。

如果我需要更新所有面板,我将其设为内部类为Observer的类。具有所有列表的getter / setter的DataStorage类我实现了Observable,特别是setter调用notifyObservers()

如果我只需要更新面板或组合框,我添加了PropertyChangeListener并在setter中创建并使用代码字激活PropertyChangeEvent

因此,在任何从服务器更改的情况下,我只需从DataStorage调用我的列表中的seter。