简体   繁体   English

滚动条在JPane内的JScrollPanel上不起作用

[英]Scrollbar doesn't work on a JScrollPanel inside a JPane

i am trying to code a JPane which has a JScrollPane where i want to add Panels in real time. 我正在尝试编写一个具有JScrollPane的JPane,我想在其中实时添加面板。 I mean, I have some Components and one is a Button that adds another JPane to the main one (secundario) which is inside a JScrollPane. 我的意思是,我有一些组件,一个是Button,它向JScrollPane内部的主要组件(secundario)添加了另一个JPane。 The problem is that when it adds some panels that cover more than the size of the window the scrollbar i put doesn't move, so i can't go down to see the panels below (it should be a vertical scrollbar). 问题是,当它添加了一些覆盖范围超过窗口大小的面板时,我放置的滚动条不会移动,因此我无法下去查看下面的面板(它应该是垂直滚动条)。 I'll leave the code here: 我将代码留在这里:

Old code: 旧代码:

    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;
}

UPDATE: OK so I reduced to the minimum my code so that you can run the program everywhere. 更新:好的,所以我将代码减少到最低限度,以便您可以在任何地方运行该程序。 It says PROBLEM in the window where my problem is, the rest windows work correctly. 它在我的问题所在的窗口中显示“问题”,其余窗口正常工作。 The function which controls that window is named panelModulos(); 控制该窗口的函数名为panelModulos();。 what I am trying to do is adding those components to a Panel and when I press the "Añadir" button it creates another JPanel with the same components and below (in colums) the old panel; 我想要做的是将这些组件添加到面板中,当我按下“Añadir”按钮时,它会创建另一个具有相同组件且位于旧面板下方(在列中)的JPanel; the problem is the size now and the VERTICAL scrollbar which doesn't work when I add some panels that occupy more than the size of the window. 问题是现在的尺寸和垂直滚动条在我添加一些面板占用的窗口大于窗口大小时不起作用。

Code: 码:

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() {

}

} }

Here are the images: https://www.dropbox.com/sh/082egfz7zk4l7kq/AABmX-EdDdHdlFbGbjsX6pZia?dl=0 这是图像: https : //www.dropbox.com/sh/082egfz7zk4l7kq/AABmX-EdDdHdlFbGbjsX6pZia?dl=0

Thanks for the help. 谢谢您的帮助。

This will mess you up: 这会把你弄乱:

secundario.setPreferredSize(maximumSize);

By setting the component's preferred size, you prevent it from actually calculating what should be its preferred size based on the components it holds, and this could prevent the secundario component from expanding. 通过设置组件的首选大小,可以防止组件根据其持有的组件实际计算其首选大小,这可能会阻止secundario组件扩展。 Get rid of this line first and foremost. 首先摆脱这条线。

If this doesn't fully solve your problem, then you're going to want to show us your Minimal, Complete, and Verifiable example . 如果这不能完全解决您的问题,那么您将想要向我们展示您的“ 最小,完整和可验证”示例


You state: 您声明:

If i remove this line it works but horizontally, i mean, the panels add sequentially in a row and an horizontal scrollbar appears. 如果我删除了这条线,那么它可以工作,但是水平的,也就是说,面板连续添加一行,然后出现水平滚动条。 I would like to have them vertically, with a vertical scrollbar, sorry that i didn't mention that. 我想垂直放置它们,并使用垂直滚动条,对不起,我没有提到。

This is key information that has bearing on your problem, and the solution is to use a layout manager or layout managers to help you with this. 这是与您的问题有关的关键信息,解决方案是使用一个或多个布局管理器来帮助您解决此问题。 If all components added to secudario are going to be the same size, then consider giving it a GridLayout. 如果添加到secudario的所有组件都将具有相同的大小,请考虑为其提供GridLayout。 What I've done is then add the GridLayout using JPanel to another JPanel that uses BorderLayout and add it to the BorderLayout.PAGE_START position, and then add that second JPanel to the JScrollPane's viewport. 然后,我要做的是使用JPanel将GridLayout添加到另一个使用BorderLayout的JPanel并将其添加到BorderLayout.PAGE_START位置,然后将第二个JPanel添加到JScrollPane的视口中。 This prevents the Grids in the GridLayout using JPanel from spreading out. 这样可以防止使用JPanel的GridLayout中的网格散开。


One way to solve your problem is to create a JPanel that holds one row's worth of data, and that uses a sensible layout manager, and that has methods that allow outside classes to extract from it any information that it holds. 解决问题的一种方法是创建一个JPanel,它保存一行的数据,并使用一个明智的布局管理器,并且具有允许外部类从中提取其保存的任何信息的方法。 For instance this class: 例如,此类:

// 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);
        }
    }
}

Has two JTextFields and two JButtons. 有两个JTextField和两个JButton。 The JButtons have Actions that call methods in the main class that tell the main class, probMain2, to add another RowPanel, or to remove this very same RowPanel object. JButton具有一些操作,这些操作调用主类中的方法,这些方法告诉主类probMain2添加另一个RowPanel或删除此相同的RowPanel对象。

Within the main class, ProbMain2, I add the RowPanels to a GridLayout using JPanel, here called rowHolderPanel, and I place that JPanel into another JPanel that uses BorderLayout, to the BorderLayout.PAGE_START position, just as I recommended originally. 在主类ProbMain2中,我使用JPanel(这里称为rowHolderPanel)将RowPanels添加到GridLayout中,然后将该JPanel放置到BorderLayout.PAGE_START位置中,就像我最初建议的那样,将其放置到另一个使用BorderLayout的JPanel中。 I then revalidate and repaint the rowHolderPanel. 然后,我重新验证并重新绘制rowHolderPanel。 I've also added the RowPanel to an ArrayList, so I can more easily extract the data it holds. 我还将RowPanel添加到了ArrayList中,因此我可以更轻松地提取其保存的数据。

Here is my complete Minimal, Complete, and Verifiable example program. 这是我完整的最小,完整和可验证的示例程序。 Notice that it's quite a bit smaller than yours as it tries to eliminate all code not relevant to the problem (except for a little extra code to prettify the results): 请注意,它比您的要小很多,因为它试图消除所有与该问题无关的代码(除了一些用于修饰结果的额外代码):

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);
        }
    }
}

The code has two non-inner classes, but only the first one is public and has the main method, so both non-inner classes can exist in a single file. 该代码具有两个非内部类,但是只有第一个是公共的并且具有main方法,因此两个非内部类都可以存在于单个文件中。 This makes for a better mcve since now folks can more easily copy and paste this code into their IDE and test it. 因为现在人们可以更轻松地将此代码复制并粘贴到他们的IDE中并进行测试,所以这使得mcve更好。

A better solution is to get rid of the holder JPanel and the RowPanel and instead use a JTable, but I don't have the time or energy tonight to do this. 更好的解决方案是摆脱持有人JPanel和RowPanel,而改用JTable,但是我今晚没有时间或精力进行此操作。

Or you could either use secundario.setMinimumSize(maximumSize); 或者您可以使用secundario.setMinimumSize(maximumSize); instead of secundario.setPreferredSize(maximumSize); 而不是secundario.setPreferredSize(maximumSize);
In this way you are forcing the layout to not reduce more than maximumSize . 这样,您将迫使布局缩小的大小不要超过maximumSize

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM