我正在尝试编写一个JPane,它有一个JScrollPane,我希望实时添加Panels。我的意思是,我有一些组件,一个是一个Button,它将另一个JPane添加到JScrollPane中的主要组件(secundario)。问题是当它添加一些覆盖超过窗口大小的面板时,我放置的滚动条不会移动,所以我不能下去看下面的面板(它应该是一个垂直滚动条)。我将把代码留在这里:
旧代码:
private JPanel panelModulos() {
JPanel raiz = new JPanel();
raiz.setLayout(new GridLayout(1, 1));
raiz.setPreferredSize(new Dimension(490, 790));
// Lo que guarda el contenedor
secundario = new JPanel();
secundario.setPreferredSize(maximumSize);
// Deficicion del formato
JLabel etModuloDir = etiqueta("Directorio");
JLabel etModuloNombre = etiqueta("Nombre");
JButton botAnModulo = boton("Añadir", "addModulo", 'A', icon("Iconos/addMod_opt.png"));
JButton botElModulo = boton("Eliminar", "delModulo", 'E', icon("Iconos/delMod_opt.png"));
JTextField txtNomMod = texto("", "Nombre", true, 25);
JTextField txtDirMod = texto("", "Directorio", true, 25);
txtDirMod.setMaximumSize(maximumSize);
txtNomMod.setMaximumSize(maximumSize);
// Contenedor de botones y etiquetas
JPanel tercero = new JPanel();
tercero.add(etModuloDir);
tercero.add(txtDirMod);
tercero.add(etModuloNombre);
tercero.add(txtNomMod);
tercero.add(botAnModulo);
tercero.add(botElModulo);
secundario.add(tercero);
principal = new JScrollPane(secundario);
principal.setPreferredSize(new Dimension(490, 790));
principal.setVerticalScrollBar(principal.createVerticalScrollBar());
principal.setWheelScrollingEnabled(true);
principal.getVerticalScrollBar().setEnabled(true);
principal.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
raiz.add(principal);
return raiz;
}
更新: 好的,所以我减少了我的代码,以便你可以在任何地方运行程序。它在问题所在的窗口中显示问题,其余窗口正常工作。 控制该窗口的函数名为panelModulos();我想要做的是将这些组件添加到Panel中,当我按下“Añadir”按钮时,它会创建另一个具有相同组件的JPanel,并在下面(在colums中)创建旧面板;问题是现在的大小和VERTICAL滚动条,当我添加一些占用超过窗口大小的面板时,它不起作用。
代码:
package problem;
import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.EventObject;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
* Clase mainApp
* <p>
* Interfaz gráfica.
*
* @author <a href="mailto:bgs0010@alu.ubu.es">Berta García Sanz</a>
* @author <a href="mailto:hma0002@alu.ubu.es">Héctor Mamolar Albitre</a>
*
* @version 1.0
*
*/
public class probMain implements ActionListener, ItemListener {
/*
* Botones de la aplicación
*/
private JButton btnBBDDRep, btnEliminarAntena, btnEliminarPA, btnAnnadirPAf, btnAnnadirPA, btnAddRed,
btnEliminarRed, btnEliminarPlanta, btnAnnadirEdif, btnEliminarEdif, rutaPA1, rutaPA2, cargarDatos,
iniciarLocalizacion, terminarLocalizacion, conectar, iniciar, obtenerDatos, logs;
/*
* Campos de la aplicación
*/
private JTextField txtUrlBBDDRep, txtDriverBBDDRep, txtUsuarioBBDDRep, finicial, ffinal, tuser, tclase, turl;
private JTextField txtDireccionI = texto("", " Dirección del edificio ", true, 20);
private JTextField txtTelefonoI = texto("", " Teléfono del edificio ", true, 20);
private JTextField txtX = texto("", " Posicion X de la antena ", true, 3);
private JTextField txtY = texto("", " Posicion Y de la antena ", true, 3);
private JTextField txtZ = texto("", " Posicion Z de la antena ", true, 3);
private JTextField txtDCC = texto("\\\\192.168.0.0\\publico", " Direccion de la carpeta compartida ", true, 17);
private JTextField txtAlcance = texto("", " AlcanceAntena ", true, 5);
private JTextField txtModelo = texto("", " ModeloAntena ", true, 5);
private JTextField txtAncho = texto("", " Ancho de planta del edificio ", true, 3);
private JTextField txtAlto = texto("", " Alto de planta del edificio ", true, 3);
private JTextField txtLargo = texto("", " Largo de planta del edificio ", true, 3);
private JTextField txtEPA2 = texto("", " Edificio del PA ", true, 10);
private JTextField txtPPA2 = texto("", " PPlanta del PA ", true, 4);
private JTextField txtEPA = texto("", " Edificio del PA ", true, 10);
private JTextField txtPPA = texto("", " Planta del PA ", true, 4);
private JTextField txtRed = texto("", " Red del PA ", true, 6);
/*
* Áreas de texto de la aplicación
*/
private TextArea localizaciontexto = new TextArea(), areatexto = new TextArea();
private JCheckBox jchx;
private JComboBox<String> eList, pList, antList, antList2, antList3, edificiosList, edificiosList1, edificiosList2,
edificiosList3, plantasList, plantasList2, plantasList3, PAList, PAList2, PAList3, PA1List;
private CheckboxGroup cbg1, cbg2, cbg3;
private Checkbox modEd, modPl, modPA, modAnt, jchxFiltro1, jchxFiltro3, jchxFiltro4;
private JPasswordField tpass, tpassClaveBBDDRep;
private JMenu men;
private JFrame cR, cE, cPA, cD;
private String edif = null;
private String planta = null;
private String fIni = null;
private String fFin = null;
static String password = "";
private Connection conexion, conexionRep, conexionMejora;
private String[] Edificios = { "" };
private String[] Plantas = { "" };
private String[] PuntosAcceso1 = { "" };
private String[] Antenas = { "" };
private File fichero1, fichero2;
private FileNameExtensionFilter filtroFicherotxt = new FileNameExtensionFilter("Archivos .txt", "txt");
private String rutPA1, rutPA2;
// TODO añadido yo
private JTextField txtFuera = texto("", "Fuera (0,1)", true, 2);
private JTextField txtRssiMin = texto("", "RSSI mínimo", true, 3);
private JTextField txtRssiMax = texto("", "RSSI máximo", true, 3);
private JTextField mejorabbddText;
private ArrayList<File> listFichDatos;
private ArrayList<File> listFichDisp;
private JTextField macDispConcreto;
private ArrayList<String> listDispConcretos;
private Thread capturas;
private Thread localizaciones;
private JComboBox<String> boxPuntosAcceso;
private ArrayList<String> listPAActivar;
private ArrayList<String> rutasModulos;
private ArrayList<String> parametros;
// Permite ir añadiendo elementos a la interfaz tras inicializarlo
private JPanel secundario;
private Dimension maximumSize;
private ArrayList<JPanel> panelesModulos;
private JScrollPane principal;
public static void main(String args[]) {
probMain apli = new probMain(508, 808);
}
// -------------
// CONSTRUCTOR
// -------------
/**
* Constructor de la clase
*
* @param alt
* - Altura de la ventana del interfaz de la aplicación
* @param anch
* - Anchura de la ventana del interfaz de la aplicación
*/
public probMain(int alt, int anch) {
listFichDatos = new ArrayList<File>();
listFichDisp = new ArrayList<File>();
listDispConcretos = new ArrayList<String>();
listPAActivar = new ArrayList<String>();
panelesModulos = new ArrayList<JPanel>();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JFrame f = new JFrame("Universidad de Burgos - Sistema de Localización GUI 2.0");
f.setIconImage(new ImageIcon("Iconos/ubu.png").getImage());
f.setSize(anch, alt);
f.setJMenuBar(menu());
f.setContentPane(tabpanel());
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} catch (ClassNotFoundException e) {
JOptionPane.showMessageDialog(new JFrame(), e + "\n Clase No encontrada desempaquetando objeto",
"Excepción java.lang", JOptionPane.WARNING_MESSAGE, null);
} catch (InstantiationException e) {
JOptionPane.showMessageDialog(new JFrame(), e + "\n Excepcion instanciando clase de Aspecto",
"Excepción java.lang", JOptionPane.WARNING_MESSAGE, null);
} catch (IllegalAccessException e) {
JOptionPane.showMessageDialog(new JFrame(), e + "\n Acceso ilegal a clase de Aspecto",
"Excepción java.lang", JOptionPane.WARNING_MESSAGE, null);
} catch (UnsupportedLookAndFeelException e) {
JOptionPane.showMessageDialog(new JFrame(), e + "\n Clase de Aspecto no soportada", "Excepción javax.swing",
JOptionPane.WARNING_MESSAGE, null);
}
}
// ---------------------
// UTILERIA de INTERFAZ
// ---------------------
/**
* Creación de los componentes principales del menú.
*
* @return JMenuBar Barra de menú de la aplicación
*/
private JMenuBar menu() {
JMenuBar mBar = new JMenuBar();
mBar.add(menuConf('Z', "Configuración"));
mBar.add(menuTitulo('A', "Ayuda"));
return (mBar);
}
/**
* Metodo que crea un submenú del menú principal.
*
* @param mnemonic
* Nemotécnico del submenú
* @param nombre
* Nombre del submenú
* @return JMenu Menú de ayuda
*/
private JMenu menuTitulo(char mnemonic, String nombre) {
JMenu men = new JMenu(nombre);
men.setMnemonic(mnemonic);
men.add(objetoMenu("Acerca de...", 'c', "acerca"));
return (men);
}
/**
* Metodo que crea un submenú con tres componentes de configuración del menú
* principal.
*
* @param mnemonic
* Nemotécnico del submenú
* @param nombre
* Nombre del submenú
* @return JMenu Menú de configuración
*/
private JMenu menuConf(char mnemonic, String nombre) {
men = new JMenu(nombre);
men.setMnemonic(mnemonic);
men.setEnabled(false);
men.add(objetoMenu("Configuración Edificios", 'e', "confEdif"));
men.add(objetoMenu("Configuración Puntos de Acceso y Red", 't', "confPA"));
men.add(objetoMenu("Configuración Representación", 'r', "confRep"));
return (men);
}
/**
* Metodo que crea un objeto del menú.
*
* @param nombre
* nombre del objeto a crear
* @param mnemonic
* mnemonic
* @param accion
* accion que realiza
* @return JMenuItem objeto con el objeto implententado
*
*/
private JMenuItem objetoMenu(String nombre, char mnemonic, String accion) {
JMenuItem mT = new JMenuItem(nombre, mnemonic);
mT.setActionCommand(accion);
mT.addActionListener(this);
return (mT);
}
/**
* Metodo que las pestañas de la ventana principal.
*
* @return JTabbedPane Contenedor de pestañas de la interfaz
*/
private JTabbedPane tabpanel() {
JTabbedPane jtp = new JTabbedPane();
jtp.addTab("correct", panelConexion());
jtp.addTab("correct", panelEscaneo());
jtp.addTab("correct", panelObtenerDatos());
jtp.addTab("PROBLEM", panelModulos());
jtp.addTab("correct", panelLocalizarDisp());
return (jtp);
}
// PANEL CONEXION BBDD
/**
* Método que establece el formato deseado de la pestaña de configuración de
* la base de datos.
*
* @return JPanel Panel de conexión a la BBDD de localización
*/
private JPanel panelConexion() {
JPanel raiz = new JPanel(new GridLayout(1, 1));
return (raiz);
}
/**
* Método que establece el formato deseado de la pestaña de escaneo de
* redes.
*
* @return JPanel Panel de escaneo de redes
*/
private JPanel panelEscaneo() {
JPanel raiz = new JPanel(new GridLayout(2, 1));
return (raiz);
}
/**
* Método que establece el formato deseado de la pestaña de filtrado de
* datos.
*
* @return JPanel Panel de filtrado de datos
*/
private JPanel panelObtenerDatos() {
JPanel raiz = new JPanel();
return (raiz);
}
/**
* Método que establece el formato deseado de la pestaña que añade módulos a
* la aplicación.
*
*/
private JPanel panelModulos() {
JPanel raiz = new JPanel();
raiz.setLayout(new GridLayout(1, 1));
// Deficicion del formato
JLabel etModuloDir = etiqueta("Directorio");
JLabel etModuloNombre = etiqueta("Nombre");
JButton botAnModulo = boton("Añadir", "addModulo", 'A', icon("Iconos/addMod_opt.png"));
JButton botElModulo = boton("Eliminar", "delModulo", 'E', icon("Iconos/delMod_opt.png"));
JTextField txtNomMod = texto("", "Nombre", true, 25);
JTextField txtDirMod = texto("", "Directorio", true, 25);
// Lo que guarda el contenedor
secundario = new JPanel();
maximumSize = new Dimension(12, 12);
etModuloDir.setMaximumSize(maximumSize);
etModuloNombre.setMaximumSize(maximumSize);
botAnModulo.setMaximumSize(maximumSize);
botElModulo.setMaximumSize(maximumSize);
txtNomMod.setMaximumSize(maximumSize);
txtDirMod.setMaximumSize(maximumSize);
GridLayout gridLay = new GridLayout(0, 6);
BorderLayout borLay = new BorderLayout();
// Contenedor de botones y etiquetas
JPanel tercero = new JPanel();
tercero.setMaximumSize(maximumSize);
tercero.setLayout(gridLay);
tercero.add(etModuloDir, BorderLayout.PAGE_START);
tercero.add(txtDirMod, BorderLayout.PAGE_START);
tercero.add(etModuloNombre, BorderLayout.PAGE_START);
tercero.add(txtNomMod, BorderLayout.PAGE_START);
tercero.add(botAnModulo, BorderLayout.PAGE_START);
tercero.add(botElModulo, BorderLayout.PAGE_START);
secundario.setLayout(borLay);
secundario.add(tercero);
principal = new JScrollPane(secundario, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
principal.setVerticalScrollBar(principal.createVerticalScrollBar());
principal.setWheelScrollingEnabled(true);
principal.getVerticalScrollBar().setEnabled(true);
// principal.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
raiz.add(principal);
return raiz;
}
/**
* Método que establece el formato deseado de la pestaña de localización de
* dispositivos.
*
* @return JPanel Panel de localización
*/
private JPanel panelLocalizarDisp() {
JPanel raiz = new JPanel(new FlowLayout(FlowLayout.LEFT));
return (raiz);
}
/**
* Método que establece las etiquetas de la interfaz.
*
* @param texto
* Texto de la etiqueta
* @return JLabel Etiqueta de la interfaz
*/
private JLabel etiqueta(String texto) {
return (new JLabel(texto));
}
/**
* Método que crea campo de texto.
*
* @param texto
* Texto del campo
* @param tooltip
* cadena con el tooltip
* @param editable
* El campo es editable o no
* @param columnas
* Tamaño del campo
* @return JTextField Panel de escaneo de redes
*/
private JTextField texto(String texto, String tooltip, boolean editable, int columnas) {
JTextField tf = new JTextField(texto, columnas);
if (editable)
tf.setEditable(true);
else
tf.setEditable(false);
tf.setToolTipText(tooltip + texto);
return (tf);
}
/**
* Método que crea los botones de la interfaz.
*
* @param nombre
* Nombre del botón
* @param accion
* Acción del botón
* @param memo
* Nemotécnico del botón
* @param icon
* Icono asociado al botón
* @return JPanel Panel de escaneo de redes
*/
private JButton boton(String nombre, String accion, char memo, Icon icon) {
JButton b = new JButton(nombre, icon);
b.setActionCommand(accion);
b.setMnemonic(memo);
b.addActionListener(this);
return (b);
}
/**
* Método que obtiene el icono.
*
* @param ruta
* Ruta en la que se encuentra ubicado el icono
* @return JPanel Panel de escaneo de redes
*/
private ImageIcon icon(String ruta) {
return (new ImageIcon(ruta));
}
/**
* Método que devuelve el panel de los que hay en la pestaña de módulos al
* que se corresponde el objeto botón que se recibe como parámetro.
*
* @param bot
* botón a buscar entre los paneles de los módulos de mejora.
* @return panel correspondiente al botón.
*/
private Component getPanel(JButton bot) {
for (JPanel panel : panelesModulos) {
for (int i = 0; i < panel.getComponentCount(); ++i) {
if (panel.getComponent(i).equals(bot)) {
return panel;
}
}
}
return null;
}
/**
* Añade un panel con sus correspondientes componentes a la pestaña de
* módulos para que se introduzca otro.
*/
private void añadeFilaModulos() {
JLabel etModuloDir = etiqueta("Directorio");
JLabel etModuloNombre = etiqueta("Nombre");
JButton botAnModulo = boton("Añadir", "addModulo", 'A', icon("Iconos/addMod_opt.png"));
JButton botElModulo = boton("Eliminar", "delModulo", 'E', icon("Iconos/delMod_opt.png"));
JTextField txtNomMod = texto("", "Nombre", true, 25);
JTextField txtDirMod = texto("", "Directorio", true, 25);
txtDirMod.setMaximumSize(maximumSize);
txtNomMod.setMaximumSize(maximumSize);
JPanel tercero = new JPanel();
tercero.add(etModuloDir);
tercero.add(txtDirMod);
tercero.add(etModuloNombre);
tercero.add(txtNomMod);
tercero.add(botAnModulo);
tercero.add(botElModulo);
panelesModulos.add(tercero);
secundario.add(tercero);
secundario.revalidate();
secundario.repaint();
principal.revalidate();
principal.repaint();
}
/**
* Borra un panel y sus componentes y además los datos del módulo
* correspondiente.
*
* @param e
* evento ocurrido al pulsar el botón de eliminar un módulo.
*/
private void borraFilaModulos(EventObject e) {
// Elimina el panel correspondiente
secundario.remove(getPanel((JButton) e.getSource()));
secundario.revalidate();
secundario.repaint();
principal.revalidate();
principal.repaint();
}
// ---------
// OYENTES
// ---------
// Oyente de Botones
public void actionPerformed(ActionEvent e) {
// Añade los datos del módulo a la base de datos y añade una nueva fila
// para poner otro módulo.
if (e.getActionCommand().equals("addModulo")) {
añadeFilaModulos();
}
if (e.getActionCommand().equals("delModulo")) {
borraFilaModulos(e);
}
}
/**
* Procedimiento para llenar los datos de una planta de un edificio dado
* como parametro segun los datos de la base de datos.
*
* @param idEdificio
* edificio donde se encuentran las plantas
*/
protected void rellenarPlantas(String idEdificio) {
}
/**
* Procedimiento para llenar los datos de una planta de un edificio dado
* como parametro segun los datos de la base de datos.
*
* @param idEdificio
* edificio donde se encuentran las plantas
*/
protected void rellenarPlantas2(String idEdificio) {
}
/**
* Procedimiento para llenar los datos de una planta de un edificio dado
* como parametro segun los datos de la base de datos.
*
* @param idEdificio
* edificio donde se encuentran las plantas
*/
protected void rellenarPlantas3(String idEdificio) {
}
/**
* Procedimiento para llenar los datos de una planta de un edificio dado
* como parametro segun los datos de la base de datos.
*
* @param idEdificio
* edificio donde se encuentran las plantas
*/
protected void rellenarPlantas4(String idEdificio) {
}
/**
* Procedimiento para rellenar los datos de un punto de acceso según la base
* de datos.
*
* @param idEdificio
* edificio donde se encuentra el punto de acceso.
* @param idPlanta
* planta en la que se encuentra el punto de acceso.
*/
protected void rellenarPAC1(String idEdificio, String idPlanta) {
}
/**
* Procedimiento para rellenar los datos de un punto de acceso según la base
* de datos.
*
* @param idEdificio
* edificio donde se encuentra el punto de acceso.
* @param idPlanta
* planta en la que se encuentra el punto de acceso.
*/
protected void rellenarPAC2(String idEdificio, String idPlanta) {
}
/**
* Procedimiento para rellenar los datos de un punto de acceso según la base
* de datos.
*
* @param idEdificio
* edificio donde se encuentra el punto de acceso.
* @param idPlanta
* planta en la que se encuentra el punto de acceso.
*/
protected void rellenarPAC3(String idEdificio, String idPlanta) {
}
/**
* Procedimiento que rellena los datos de una antena conectada a un punto de
* acceso pasado como parámetro.
*
* @param idPA
* identificador del punto de acceso.
*/
protected void rellenarAnt1(String idPA) {
}
/**
* Procedimiento que rellena los datos de una antena conectada a un punto de
* acceso pasado como parámetro.
*
* @param idPA
* identificador del punto de acceso.
*/
protected void rellenarAnt2(String idPA) {
}
/**
* Procedimiento que rellena los datos de una antena conectada a un punto de
* acceso pasado como parámetro.
*
*/
protected void rellenarAnt3() {
}
/**
* Procedimiento que rellena los datos de la red según la antena a la que
* esté conectada que se pasa como parámetro.
*
* @param idAntena
* identificador de la antena.
*/
protected void rellenarRed(String idAntena) {
}
/**
* Rellena los datos del punto de acceso 1.
*
* @param idEdificio
* identificador del edificio
* @param idPlanta
* identificador de la planta
*/
protected void rellenarPA1(String idEdificio, String idPlanta) {
}
public void itemStateChanged(ItemEvent i) {
if (i.getItemSelectable() == jchx) {
if (i.getStateChange() == ItemEvent.SELECTED)
jchx.setSelected(true);
else
jchx.setSelected(false);
}
}
/**
* Procedimiento que guarda la información obtenida en un fichero de texto
* denominado HISTORIAL.txt.
*/
public void guardarInfo() {
}
}
以下是图片:https://www.dropbox.com/sh/082egfz7zk4l7kq/AABmX-EdDdHdlFbGbjsX6pZia?dl=0
感谢您的帮助。
答案 0 :(得分:5)
这会搞砸你:
secundario.setPreferredSize(maximumSize);
通过设置组件的首选大小,可以防止它根据它所拥有的组件实际计算出它的首选大小,这可能会阻止secundario组件扩展。首先摆脱这条线。
如果这不能完全解决您的问题,那么您将要向我们展示您的Minimal, Complete, and Verifiable example。
你说:
如果我删除这一行它可以工作但水平,我的意思是,面板连续添加一行,并出现水平滚动条。我想垂直使用垂直滚动条,对不起,我没有提到它。
这是影响您的问题的关键信息,解决方案是使用布局管理器或布局管理器来帮助您解决此问题。如果添加到secudario的所有组件的大小都相同,那么考虑给它一个GridLayout。我所做的就是使用JPanel将GridLayout添加到另一个使用BorderLayout的JPanel并将其添加到BorderLayout.PAGE_START位置,然后将第二个JPanel添加到JScrollPane的视口中。这可以防止使用JPanel的GridLayout中的网格扩散。
解决问题的一种方法是创建一个JPanel,它包含一行的数据,并使用一个合理的布局管理器,并且有一些方法允许外部类从中提取它所拥有的任何信息。例如这个类:
// holds a row of data
@SuppressWarnings("serial")
class RowPanel extends JPanel {
private static final int COLS = 20;
private JTextField txtDirMod = new JTextField(COLS);
private JTextField txtNomMod = new JTextField(COLS);
private ProbMain2 probMain2;
private int minorStrut = 3;
private int majorStrut = 6;
// TODO: add tool tips, ...
public RowPanel(ProbMain2 probMain2) {
this.probMain2 = probMain2;
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBorder(BorderFactory.createEmptyBorder(minorStrut, minorStrut, minorStrut, minorStrut));
add(new JLabel("Directorio"));
add(Box.createHorizontalStrut(minorStrut));
add(txtDirMod);
add(Box.createHorizontalStrut(majorStrut));
add(new JLabel("Nombre"));
add(Box.createHorizontalStrut(minorStrut));
add(txtNomMod);
add(Box.createHorizontalStrut(majorStrut));
add(new JButton(new AnadirAction()));
add(Box.createHorizontalStrut(minorStrut));
add(new JButton(new EliminarAction()));
}
// to extract data held in the JPanel
public String getDir() {
return txtDirMod.getText();
}
public String getNom() {
return txtNomMod.getText();
}
private class AnadirAction extends AbstractAction {
public AnadirAction() {
super("Anadir");
}
@Override
public void actionPerformed(ActionEvent e) {
// add new RowPanel to the main GUI
probMain2.addRowPanel();
}
}
private class EliminarAction extends AbstractAction {
public EliminarAction() {
super("Eliminar");
}
@Override
public void actionPerformed(ActionEvent e) {
// tell main GUI to remove *this* RowPanel object
probMain2.removeRowPanel(RowPanel.this);
}
}
}
有两个JTextField和两个JButton。 JButtons具有调用主类中的方法的Actions,它们告诉主类probMain2添加另一个RowPanel,或者删除这个相同的RowPanel对象。
在主类ProbMain2中,我使用JPanel将RowPanel添加到GridLayout,这里称为rowHolderPanel,我将JPanel放入另一个使用BorderLayout的JPanel,到BorderLayout.PAGE_START位置,就像我最初建议的那样。然后我重新验证并重新绘制rowHolderPanel。我还将RowPanel添加到了ArrayList中,因此我可以更轻松地提取它所拥有的数据。
这是我完整的Minimal, Complete, and Verifiable example计划。请注意,它比你的小一点,因为它试图消除与问题无关的所有代码(除了一些额外的代码来美化结果):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class ProbMain2 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 500;
// holds the rows, has grid layout with variable number of rows and one column:
private JPanel rowHolderPanel = new JPanel(new GridLayout(0, 1));
private List<RowPanel> rowPanelList = new ArrayList<>();
public ProbMain2() {
// panel below holds the rowHOlderPanel at the PAGE_START position
JPanel borderLayoutPanel = new JPanel(new BorderLayout());
borderLayoutPanel.add(rowHolderPanel, BorderLayout.PAGE_START);
JScrollPane scrollPane = new JScrollPane(borderLayoutPanel);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
addRowPanel();
setLayout(new BorderLayout());
add(scrollPane);
}
public void addRowPanel() {
RowPanel rowPanel = new RowPanel(this);
rowPanelList.add(rowPanel);
rowHolderPanel.add(rowPanel);
rowHolderPanel.revalidate();
rowHolderPanel.repaint();
}
public void removeRowPanel(RowPanel row) {
rowPanelList.remove(row);
rowHolderPanel.remove(row);
rowHolderPanel.revalidate();
rowHolderPanel.repaint();
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
ProbMain2 mainPanel = new ProbMain2();
JFrame frame = new JFrame("ProbMain2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// holds a row of data
@SuppressWarnings("serial")
class RowPanel extends JPanel {
private static final int COLS = 20;
private JTextField txtDirMod = new JTextField(COLS);
private JTextField txtNomMod = new JTextField(COLS);
private ProbMain2 probMain2;
private int minorStrut = 3;
private int majorStrut = 6;
// TODO: add tool tips, ...
public RowPanel(ProbMain2 probMain2) {
this.probMain2 = probMain2;
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBorder(BorderFactory.createEmptyBorder(minorStrut, minorStrut, minorStrut, minorStrut));
add(new JLabel("Directorio"));
add(Box.createHorizontalStrut(minorStrut));
add(txtDirMod);
add(Box.createHorizontalStrut(majorStrut));
add(new JLabel("Nombre"));
add(Box.createHorizontalStrut(minorStrut));
add(txtNomMod);
add(Box.createHorizontalStrut(majorStrut));
add(new JButton(new AnadirAction()));
add(Box.createHorizontalStrut(minorStrut));
add(new JButton(new EliminarAction()));
}
// to extract data held in the JPanel
public String getDir() {
return txtDirMod.getText();
}
public String getNom() {
return txtNomMod.getText();
}
private class AnadirAction extends AbstractAction {
public AnadirAction() {
super("Anadir");
}
@Override
public void actionPerformed(ActionEvent e) {
// add new RowPanel to the main GUI
probMain2.addRowPanel();
}
}
private class EliminarAction extends AbstractAction {
public EliminarAction() {
super("Eliminar");
}
@Override
public void actionPerformed(ActionEvent e) {
// tell main GUI to remove *this* RowPanel object
probMain2.removeRowPanel(RowPanel.this);
}
}
}
代码有两个非内部类,但只有第一个是public,并且有main方法,所以两个非内部类都可以存在于一个文件中。这样可以提供更好的mcve,因为现在人们可以更轻松地将此代码复制并粘贴到IDE中并进行测试。
更好的解决方案是摆脱持有者JPanel和RowPanel,而不是使用JTable,但今晚我没有时间或精力来做这件事。
答案 1 :(得分:0)
或者您可以使用secundario.setMinimumSize(maximumSize);
而不是secundario.setPreferredSize(maximumSize);
这样,您强制布局不会减少超过maximumSize
。