eclipse 在Java中使JButton更新其他类中的JLabel文本

k4aesqcs  于 2023-10-18  发布在  Eclipse
关注(0)|答案(1)|浏览(172)

我正在为我的公司编写一个程序,它引用excel文件来获取项目信息。我已经将程序组织成4个JPanel,每个都在自己的类中。即Panel_1、Panel_2等。我在panel_1中有一个按钮,允许用户选择项目信息文件,并且工作正常。我想做的是让那个按钮将项目中的信息应用到其他JPanel 2、3和4中的JLabel。
UI类

public class UI extends JFrame implements ActionListener {
    
    //Variables declared outside constructor, and to be used in multiple Panels
    static String JobNo = "";
    static String JobName = "";
    static String Attention = "";
    static String Contractor = "";
    public UI() {
        
        //Define JFrame
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.getContentPane().setLayout(new GroupLayout(this.getContentPane()));
        this.setSize(FW + 36, FH);
        this.getContentPane().setBackground(col1);
        
        //Add panels to JFrame
        Panel_1 panel1 = new Panel_1();
        this.add(panel1);
        Panel_2 panel2 = new Panel_2();
        this.add(panel2);
        Panel_3 panel3 = new Panel_3();
        this.add(panel3);
        Panel_4 panel4 = new Panel_4();
        this.add(panel4);
        
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        
    }
    
    
}

Panel_1类

public class Panel_1 extends JPanel implements ActionListener{
    
     Panel_1() {
        
        //Define Panel_1
        this.setBounds(UI.offSet, UI.offSet, UI.p1W, UI.p1H);
        this.setBackground(UI.col2);
        this.setLayout(new GroupLayout(this));
        
        JLabel title = new JLabel("Please select Project Folder:");
        title.setBounds(20, 10, 300, 15);
        title.setForeground(UI.colText);
        this.add(title);
        
        //Text field to display project file location
        UI.field1 = new JTextField();
        UI.field1.setBounds(20, 35, 570, 20);
        UI.field1.setBackground(UI.colTF);
        UI.field1.setForeground(UI.colText);
        UI.field1.setText(UI.sDefPath);
        UI.field1.setCaretColor(UI.colText);
        UI.field1.setBorder(BorderFactory.createLoweredBevelBorder());
        UI.field1.addActionListener(this);
        this.add(UI.field1);
        
        //Browse for project file
        UI.butBrowse1 = new JButton("Browse");
        UI.butBrowse1.setBounds(600, 35, 80, 20);
        UI.butBrowse1.setBackground(UI.colBut);
        UI.butBrowse1.setForeground(UI.colBT);
        UI.butBrowse1.setBorder(BorderFactory.createEmptyBorder());
        UI.butBrowse1.setFocusable(false);
        UI.butBrowse1.addActionListener(this);
        this.add(UI.butBrowse1);
    }
     
     @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            if (e.getSource()==UI.butBrowse1) {
                
                //Choose project file location
                JFileChooser fileChoose1 = new JFileChooser(UI.sDefPath);
                fileChoose1.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                Action details = fileChoose1.getActionMap().get("viewTypeDetails");
                details.actionPerformed(null);
                fileChoose1.setPreferredSize(new Dimension(500, 600));
                fileChoose1.showOpenDialog(null);
                UI.sPath = fileChoose1.getSelectedFile().getAbsolutePath();
                
                //Assign file paths from selected folder
                UI.field1.setText(UI.sPath);
                UI.sPIPath = UI.sPath + UI.sPIadd;
                UI.sPDFPath = UI.sPath + UI.sPDFadd;
                UI.sSubPath = UI.sPath + UI.sSubadd;
                
                //Test assigned file paths
                System.out.println(UI.sPIPath);
                System.out.println(UI.sPDFPath);
                System.out.println(UI.sSubPath);
                
                //Assigning data from xlsx
                //These are the variable that I need to display in Panel_4
                UI.JobNo = XLSX_Reader.XLSX_Reader(UI.sPIPath, 0, 1);
                UI.JobName = XLSX_Reader.XLSX_Reader(UI.sPIPath, 1, 1) + "\n" + XLSX_Reader.XLSX_Reader(UI.sPIPath, 2, 1);
                UI.Contractor = XLSX_Reader.XLSX_Reader(UI.sPIPath, 4, 1);
                UI.Attention = XLSX_Reader.XLSX_Reader(UI.sPIPath, 8, 1);
                
                //testing xlsx reader
                System.out.println(UI.JobNo);
                System.out.println(UI.JobName);
                System.out.println(UI.Contractor);
                System.out.println(UI.Attention);

                
            }
        }

Panel_4类

public class Panel_4 extends JPanel implements ActionListener{
    
     Panel_4() {
        
        //Define Panel_4
        this.setBounds((UI.offSet * 2) + UI.p1W, UI.offSet, UI.p4W, UI.p4H);
        this.setBackground(UI.col2);
        this.setLayout(new GroupLayout(this));
        
        //Doesn't update when Panel_1 assigns value to UI.Contractor
        JLabel to = new JLabel("To: " + UI.Contractor);
        to.setBounds(50, 190, 200, 30);
        to.setForeground(UI.colText);
        this.add(to);
        
        //Doesn't update when Panel_1 assigns value to UI.JobNo
        JLabel Job = new JLabel("Job No. " + UI.JobNo);
        Job.setBounds(500, 110, 100, 15);
        Job.setForeground(UI.colText);
        this.add(Job);
        
        //Doesn't update when Panel_1 assigns value to UI.Attention
        JLabel Att = new JLabel("Attention " + UI.Attention);
        Att.setBounds(350, 150, 100, 15);
        Att.setForeground(UI.colText);
        this.add(Att);
        
        //Doesn't update when Panel_1 assigns value to UI.JobName
        JLabel Re = new JLabel("Re: " + UI.JobName);
        Re.setBounds(350, 190, 100, 15);
        Re.setForeground(UI.colText);
        this.add(Re);

如果他们在同一个班级,我通常会这样做:

String pName = "Sam";

JLabel name = new JLabel(pName);
name.setBounds(...);
this.add(name);

JButton button = new JButton();
button.addActionListener(this);
this.add(button);
}
}

@Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource()==UI.butBrowse1) {
        pName = "Dave";
        name.setText(pName);

但我不知道跨班级是否可行。

bnlyeluc

bnlyeluc1#

首先,你要解耦你的代码。在你的“输入”UI和“输出”UI之间不应该有直接的关系。这将使代码的重用和维护变得更加容易。
为此,您应该使用“模型-视图-控制器”概念。也就是说,模型提供数据,视图以某种有意义的方式呈现数据。
添加“观察者模式”,对象可以监视模型,并在某些状态发生变化时采取行动。
例如...

public interface Model {
    public interface Observer {
        public void modelDidChange(Model model);
    }
    
    public void addObserver(Observer observer);
    public void removeObserver(Observer observer);
    public LocalDateTime getDate();
}

这是一个非常简单的演示,但是,ModelLocalDateTime值的容器。它还通过使用Model.Observer提供了“可观察性”,因此当模型发生变化时,感兴趣的各方可以得到通知。
在某些时候,我们可能想要改变模型的值,在这种情况下,我们可以使用一个专门的模型。

public interface MutableModel extends Model {
    public void setDate(LocalDateTime date);
}

这基本上描述了一个模型,其值可以改变。
为什么这很重要?这隔离了责任,不是模型的所有消费者都想要或应该被允许修改模型的状态,这里我们支持“关注点/责任分离”原则。
我个人也喜欢interface s,因为它们提供了合约的描述,而没有公开实现,这使得它们非常灵活。
接下来,我们需要模型的实现。你怎么做可能并不重要,但我从一个AbstractModel开始。

public abstract class AbstractModel implements Model {
    private List<Observer> observers = new ArrayList<>();

    protected List<Observer> getObservers() {
        return observers;
    }

    @Override
    public void addObserver(Observer observer) {
        getObservers().add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        getObservers().remove(observer);
    }
    
    protected void fireModelDidChange() {
        for (Observer observer : getObservers()) {
            observer.modelDidChange(this);
        }
    }
}

这实现了所有其他模型都需要的核心“锅炉板”功能。注意,我没有实现getDate方法,这是故意的,因为如何管理这个值应该取决于实际的实现。
接下来,我实现了一个“可变”模型的概念。

public class DefaultMutableModel extends AbstractModel implements MutableModel {
    private LocalDateTime date;

    @Override
    public LocalDateTime getDate() {
        return date;
    }
    
    public void setDate(LocalDateTime date) {
        this.date = date;
        fireModelDidChange();
    }
}

我认为这是不言自明的。
这一切都很好,但我们实际上如何使用它?
好吧,基本上,我们可以创建模型的示例,并将其传递给需要它的各种对象,这是一个“依赖注入”的概念,例如......

ActionPane

public class ActionPane extends JPanel {
    private MutableModel model;

    public ActionPane(MutableModel model) {
        this.model = model;
        setLayout(new GridBagLayout());
        setBorder(new EmptyBorder(32, 32, 32, 32));
        
        JButton btn = new JButton("Tick");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                getModel().setDate(LocalDateTime.now());
            }
        });
        add(btn);
    }

    public MutableModel getModel() {
        return model;
    }
}

OutputPane

public class OutputPane extends JPanel {
    private Model model;
    private JLabel label;

    public OutputPane(Model model) {
        this.model = model;
        setLayout(new GridBagLayout());
        setBorder(new EmptyBorder(32, 32, 32, 32));
        
        add(getLabel());
        
        model.addObserver(new Model.Observer() {
            @Override
            public void modelDidChange(Model model) {
                label.setText(DateTimeFormatter.ISO_LOCAL_TIME.format(model.getDate()));
            }
        });
    }
    
    protected JLabel getLabel() {
        if (label != null) {
            return label;
        }
        label = new JLabel("------------");
        return label;
    }

    public Model getModel() {
        return model;
    }
}

这两个面板是分开的,彼此不知道,但通过模型,他们可以沟通。
现在,我们简单地创建一个模型和UI.

MutableModel model = new DefaultMutableModel();

add(new ActionPane(model));
add(new OutputPane(model));

就是这样当模型的状态改变时,UI将被更新。

可运行示例.

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainPane extends JPanel {
        public MainPane() {
            MutableModel model = new DefaultMutableModel();
            setLayout(new GridLayout(1, 2));

            add(new ActionPane(model));
            add(new OutputPane(model));
        }
    }

    public interface Model {
        public interface Observer {
            public void modelDidChange(Model model);
        }

        public void addObserver(Observer observer);

        public void removeObserver(Observer observer);

        public LocalDateTime getDate();
    }

    public interface MutableModel extends Model {
        public void setDate(LocalDateTime date);
    }

    public abstract class AbstractModel implements Model {
        private List<Observer> observers = new ArrayList<>();

        protected List<Observer> getObservers() {
            return observers;
        }

        @Override
        public void addObserver(Observer observer) {
            getObservers().add(observer);
        }

        @Override
        public void removeObserver(Observer observer) {
            getObservers().remove(observer);
        }

        protected void fireModelDidChange() {
            for (Observer observer : getObservers()) {
                observer.modelDidChange(this);
            }
        }
    }

    public class DefaultMutableModel extends AbstractModel implements MutableModel {
        private LocalDateTime date;

        @Override
        public LocalDateTime getDate() {
            return date;
        }

        public void setDate(LocalDateTime date) {
            this.date = date;
            fireModelDidChange();
        }
    }

    public class ActionPane extends JPanel {
        private MutableModel model;

        public ActionPane(MutableModel model) {
            this.model = model;
            setLayout(new GridBagLayout());
            setBorder(new EmptyBorder(32, 32, 32, 32));

            JButton btn = new JButton("Tick");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    getModel().setDate(LocalDateTime.now());
                }
            });
            add(btn);
        }

        public MutableModel getModel() {
            return model;
        }
    }

    public class OutputPane extends JPanel {
        private Model model;
        private JLabel label;

        public OutputPane(Model model) {
            this.model = model;
            setLayout(new GridBagLayout());
            setBorder(new EmptyBorder(32, 32, 32, 32));

            add(getLabel());

            model.addObserver(new Model.Observer() {
                @Override
                public void modelDidChange(Model model) {
                    label.setText(DateTimeFormatter.ISO_LOCAL_TIME.format(model.getDate()));
                }
            });
        }

        protected JLabel getLabel() {
            if (label != null) {
                return label;
            }
            label = new JLabel("------------");
            return label;
        }

        public Model getModel() {
            return model;
        }
    }
}

你应该注意到,我没有在哪里需要调用revalidateinvalidaterepaint来更新标签。除了将初始值设置为一个“合理的”长值之外,标签(通常)是自我更新的。
我已经提到了很多“概念”和“术语”,我强烈建议你花时间进一步研究它们,因为它们对你解决未来的问题是无价的。

相关问题