Java 动态儿童沟通
背景:我有一个JPanel(PanelCarga Extended JPanel),它显示的子JPanel(DatosArchivo Extended JPanel)与我希望在程序中打开的文件(n个DatosArchivo面板)一样多,用于不同的目的。此DatosArchivos包含一个“X”按钮,我希望它关闭此DatosArchivos面板,然后通知相应的面板Carga它已关闭,以便可以在其网格中重新组织剩余的n-1个DatosArchivo面板 Tha PanelCarga等级:Java 动态儿童沟通,java,swing,listener,parent,Java,Swing,Listener,Parent,背景:我有一个JPanel(PanelCarga Extended JPanel),它显示的子JPanel(DatosArchivo Extended JPanel)与我希望在程序中打开的文件(n个DatosArchivo面板)一样多,用于不同的目的。此DatosArchivos包含一个“X”按钮,我希望它关闭此DatosArchivos面板,然后通知相应的面板Carga它已关闭,以便可以在其网格中重新组织剩余的n-1个DatosArchivo面板 Tha PanelCarga等级: p
package gui;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.sql.SQLException;
import java.util.LinkedList;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import logica.Cargador;
public class PanelCarga extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private JTextField textField;
private final JPanel panel = new JPanel();
/**
* Create the panel.
*/
public PanelCarga() {
JLabel lblArchivosA = new JLabel("Archivo (-s) a cargar");
textField = new JTextField();
textField.setEditable(false);
textField.setColumns(10);
final JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(panel);
panel.setLayout(new GridLayout(0, 2, 0, 0));
JButton btnAbrir = new JButton("Abrir");
btnAbrir.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JFileChooser escoger = new JFileChooser();
escoger.setMultiSelectionEnabled(true);
int resultado = escoger.showOpenDialog(null);
File[] archivos = null;
String nombres = "";
if (resultado == JFileChooser.APPROVE_OPTION) {
archivos = escoger.getSelectedFiles();
for (int i = 0; i<archivos.length;i++){
if (i==0){
nombres = nombres + archivos [i].getName() ;
}else{
nombres = nombres + "; " +archivos [i].getName() ;
}
DatosArchivo datos = null;
try {
datos = new DatosArchivo();
} catch (SQLException e) {
JDialog error = new JDialog ();
error.setTitle("error");
JLabel mensaje = new JLabel(e.getMessage());
error.getContentPane().add(mensaje);
error.validate();
}
datos.textField_Ruta.setText(archivos[i].toString());
JTextField texto = new JTextField ();
texto.setBounds(10, 10, 100, 100);
panel.add(datos);
}
textField.setText(nombres);
panel.validate();
scrollPane.validate();
}
}
});
GroupLayout groupLayout = new GroupLayout(this);
groupLayout.setHorizontalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGroup(groupLayout.createSequentialGroup()
.addContainerGap()
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
.addComponent(scrollPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 430, Short.MAX_VALUE)
.addGroup(groupLayout.createSequentialGroup()
.addComponent(lblArchivosA)
.addGap(18)
.addComponent(textField, GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(btnAbrir)))
.addContainerGap())
);
groupLayout.setVerticalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGroup(groupLayout.createSequentialGroup()
.addGap(6)
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
.addComponent(lblArchivosA)
.addComponent(textField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(btnAbrir))
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 423, Short.MAX_VALUE)
.addContainerGap())
);
setLayout(groupLayout);
}
public LinkedList <Cargador> getCargadores (){
LinkedList <Cargador> cargadores = new LinkedList <Cargador> ();
for (int i = 0; i < panel.getComponentCount(); i++){
cargadores.add(((DatosArchivo) panel.getComponent(i)).getCargador());
}
return cargadores;
}
public JPanel getPanel (){
return this.panel;
}
}
提前感谢我不确定是否有最好的方法,但我认为有两种可能的方法: 一种方法是允许外部类向DatosArchivo中持有的btnX添加ActionListener,方法是为该类提供一个公共方法。比如:
public void addbtnXActionListener(ActionListener listener) {
btnX.addActionListener(listener);
}
然后外部类可以根据需要从其显示中删除该JPanel。这样做的好处是,DatosArchivo不需要知道保存它的gui。当我这样做时,我还为DatosArchivo提供了一个公共getBtnX()方法来返回btnX JButton。这样我就可以匹配从ActionListener的actionPerformed方法的getSource方法获得的JButton,从而能够决定要处理哪个DatoArchivo对象
例如:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Foo002 {
private static void createAndShowUI() {
JFrame frame = new JFrame("Foo002");
frame.getContentPane().add(new PanelCarga2());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
@SuppressWarnings("serial")
class PanelCarga2 extends JPanel {
private static final Dimension PREF_SIZE = new Dimension(600, 400);
private JPanel datosArchivoContainer = new JPanel();
private BtnXListener btnXListener = new BtnXListener();
public PanelCarga2() {
JButton btnAbrir = new JButton("Abrir");
btnAbrir.addActionListener(new ActionListener() {
int index = 1;
public void actionPerformed(ActionEvent e) {
DatosArchivo2 datosArchivo2 = new DatosArchivo2(index);
datosArchivo2.addbtnXActionListener(btnXListener);
datosArchivoContainer.add(datosArchivo2);
datosArchivoContainer.revalidate();
index++;
}
});
JPanel topPanel = new JPanel();
topPanel.add(btnAbrir);
datosArchivoContainer.setLayout(new BoxLayout(datosArchivoContainer, BoxLayout.LINE_AXIS));
JScrollPane scrollPane = new JScrollPane(datosArchivoContainer);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
setPreferredSize(PREF_SIZE);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
}
private class BtnXListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
Component[] components = datosArchivoContainer.getComponents();
for (int i = components.length - 1; i >= 0; i--) {
if (components[i] instanceof DatosArchivo2) {
DatosArchivo2 datoArchivo = (DatosArchivo2) components[i];
if (source.equals(datoArchivo.getBtnX())) {
datosArchivoContainer.remove(components[i]);
}
}
}
datosArchivoContainer.revalidate();
datosArchivoContainer.repaint();
}
}
}
@SuppressWarnings("serial")
class DatosArchivo2 extends JPanel {
private JButton btnX = new JButton("X");
public DatosArchivo2(int index) {
setPreferredSize(new Dimension(200, 200));
setBorder(BorderFactory.createEtchedBorder());
add(btnX);
add(new JLabel("Index: " + index));
}
public void addbtnXActionListener(ActionListener listener) {
btnX.addActionListener(listener);
}
public JButton getBtnX() {
return btnX;
}
}
另一种方法是给DatosArchivo一个对其包含类的引用,然后让DatosArchivo对象处理自己的删除。这样做的缺点是,我相信会增加一些凝聚力。为此,我将包含PanelCarga的引用传递到DatosArchivo的构造函数中,然后给PanelCarga一个DatosArchivo方法将调用的公共RemoveDataSarchivo,并将其自身作为参数传递:
public void removeDatosArchivo(DatosArchivo3 datosArchivo) {
datosArchivoContainer.remove(datosArchivo);
datosArchivoContainer.revalidate();
datosArchivoContainer.repaint();
}
整个示例程序如下所示:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Foo003 {
private static void createAndShowUI() {
JFrame frame = new JFrame("Foo002");
frame.getContentPane().add(new PanelCarga3());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
@SuppressWarnings("serial")
class PanelCarga3 extends JPanel {
private static final Dimension PREF_SIZE = new Dimension(600, 400);
private JPanel datosArchivoContainer = new JPanel();
public PanelCarga3() {
JButton btnAbrir = new JButton("Abrir");
btnAbrir.addActionListener(new ActionListener() {
int index = 1;
public void actionPerformed(ActionEvent e) {
DatosArchivo3 datosArchivo3 = new DatosArchivo3(index, PanelCarga3.this);
datosArchivoContainer.add(datosArchivo3);
datosArchivoContainer.revalidate();
index++;
}
});
JPanel topPanel = new JPanel();
topPanel.add(btnAbrir);
datosArchivoContainer.setLayout(new BoxLayout(datosArchivoContainer, BoxLayout.LINE_AXIS));
JScrollPane scrollPane = new JScrollPane(datosArchivoContainer);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
setPreferredSize(PREF_SIZE);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
}
public void removeDatosArchivo(DatosArchivo3 datosArchivo) {
datosArchivoContainer.remove(datosArchivo);
datosArchivoContainer.revalidate();
datosArchivoContainer.repaint();
}
}
@SuppressWarnings("serial")
class DatosArchivo3 extends JPanel {
private PanelCarga3 panelCarga;
private JButton btnX = new JButton("X");
public DatosArchivo3(int index, PanelCarga3 panelCarga) {
this.panelCarga = panelCarga;
btnX.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnXActionPerformed(e);
}
});
setPreferredSize(new Dimension(200, 200));
setBorder(BorderFactory.createEtchedBorder());
add(btnX);
add(new JLabel("Index: " + index));
}
private void btnXActionPerformed(ActionEvent e) {
panelCarga.removeDatosArchivo(this);
}
}
我不确定是否有最好的方法,但我认为有两种可能的方法: 一种方法是允许外部类向DatosArchivo中持有的btnX添加ActionListener,方法是为该类提供一个公共方法。比如:
public void addbtnXActionListener(ActionListener listener) {
btnX.addActionListener(listener);
}
然后外部类可以根据需要从其显示中删除该JPanel。这样做的好处是,DatosArchivo不需要知道保存它的gui。当我这样做时,我还为DatosArchivo提供了一个公共getBtnX()方法来返回btnX JButton。这样我就可以匹配从ActionListener的actionPerformed方法的getSource方法获得的JButton,从而能够决定要处理哪个DatoArchivo对象
例如:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Foo002 {
private static void createAndShowUI() {
JFrame frame = new JFrame("Foo002");
frame.getContentPane().add(new PanelCarga2());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
@SuppressWarnings("serial")
class PanelCarga2 extends JPanel {
private static final Dimension PREF_SIZE = new Dimension(600, 400);
private JPanel datosArchivoContainer = new JPanel();
private BtnXListener btnXListener = new BtnXListener();
public PanelCarga2() {
JButton btnAbrir = new JButton("Abrir");
btnAbrir.addActionListener(new ActionListener() {
int index = 1;
public void actionPerformed(ActionEvent e) {
DatosArchivo2 datosArchivo2 = new DatosArchivo2(index);
datosArchivo2.addbtnXActionListener(btnXListener);
datosArchivoContainer.add(datosArchivo2);
datosArchivoContainer.revalidate();
index++;
}
});
JPanel topPanel = new JPanel();
topPanel.add(btnAbrir);
datosArchivoContainer.setLayout(new BoxLayout(datosArchivoContainer, BoxLayout.LINE_AXIS));
JScrollPane scrollPane = new JScrollPane(datosArchivoContainer);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
setPreferredSize(PREF_SIZE);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
}
private class BtnXListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
Component[] components = datosArchivoContainer.getComponents();
for (int i = components.length - 1; i >= 0; i--) {
if (components[i] instanceof DatosArchivo2) {
DatosArchivo2 datoArchivo = (DatosArchivo2) components[i];
if (source.equals(datoArchivo.getBtnX())) {
datosArchivoContainer.remove(components[i]);
}
}
}
datosArchivoContainer.revalidate();
datosArchivoContainer.repaint();
}
}
}
@SuppressWarnings("serial")
class DatosArchivo2 extends JPanel {
private JButton btnX = new JButton("X");
public DatosArchivo2(int index) {
setPreferredSize(new Dimension(200, 200));
setBorder(BorderFactory.createEtchedBorder());
add(btnX);
add(new JLabel("Index: " + index));
}
public void addbtnXActionListener(ActionListener listener) {
btnX.addActionListener(listener);
}
public JButton getBtnX() {
return btnX;
}
}
另一种方法是给DatosArchivo一个对其包含类的引用,然后让DatosArchivo对象处理自己的删除。这样做的缺点是,我相信会增加一些凝聚力。为此,我将包含PanelCarga的引用传递到DatosArchivo的构造函数中,然后给PanelCarga一个DatosArchivo方法将调用的公共RemoveDataSarchivo,并将其自身作为参数传递:
public void removeDatosArchivo(DatosArchivo3 datosArchivo) {
datosArchivoContainer.remove(datosArchivo);
datosArchivoContainer.revalidate();
datosArchivoContainer.repaint();
}
整个示例程序如下所示:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Foo003 {
private static void createAndShowUI() {
JFrame frame = new JFrame("Foo002");
frame.getContentPane().add(new PanelCarga3());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
@SuppressWarnings("serial")
class PanelCarga3 extends JPanel {
private static final Dimension PREF_SIZE = new Dimension(600, 400);
private JPanel datosArchivoContainer = new JPanel();
public PanelCarga3() {
JButton btnAbrir = new JButton("Abrir");
btnAbrir.addActionListener(new ActionListener() {
int index = 1;
public void actionPerformed(ActionEvent e) {
DatosArchivo3 datosArchivo3 = new DatosArchivo3(index, PanelCarga3.this);
datosArchivoContainer.add(datosArchivo3);
datosArchivoContainer.revalidate();
index++;
}
});
JPanel topPanel = new JPanel();
topPanel.add(btnAbrir);
datosArchivoContainer.setLayout(new BoxLayout(datosArchivoContainer, BoxLayout.LINE_AXIS));
JScrollPane scrollPane = new JScrollPane(datosArchivoContainer);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
setPreferredSize(PREF_SIZE);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
}
public void removeDatosArchivo(DatosArchivo3 datosArchivo) {
datosArchivoContainer.remove(datosArchivo);
datosArchivoContainer.revalidate();
datosArchivoContainer.repaint();
}
}
@SuppressWarnings("serial")
class DatosArchivo3 extends JPanel {
private PanelCarga3 panelCarga;
private JButton btnX = new JButton("X");
public DatosArchivo3(int index, PanelCarga3 panelCarga) {
this.panelCarga = panelCarga;
btnX.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnXActionPerformed(e);
}
});
setPreferredSize(new Dimension(200, 200));
setBorder(BorderFactory.createEtchedBorder());
add(btnX);
add(new JLabel("Index: " + index));
}
private void btnXActionPerformed(ActionEvent e) {
panelCarga.removeDatosArchivo(this);
}
}
请编辑您的文章,选择完整代码,然后按{}代码标记请编辑您的文章,选择完整代码,然后按{}代码标记