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

阿德里安·阿罗约·佩雷斯(Adrian Arroyo Perez)

我正在尝试编写具有JScrollPane的JPane,我想在其中实时添加面板。我的意思是,我有一些组件,一个是Button,它向JScrollPane内部的主要组件(secundario)添加了另一个JPane。问题是,当它添加了一些覆盖范围超过窗口大小的面板时,我放置的滚动条不会移动,因此我无法下去查看下面的面板(它应该是垂直滚动条)。我将代码留在这里:

旧代码:

    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();。我想要做的是将这些组件添加到面板中,当我按下“Añadir”按钮时,它会创建另一个具有相同组件且位于旧面板下方(在列中)的JPanel;问题是现在的尺寸和垂直滚动条在我添加一些面板所占的比例大于窗口尺寸时不起作用。

代码:

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:[email protected]">Berta García Sanz</a>
  * @author <a href="mailto:[email protected]">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

谢谢您的帮助。

充满鳗鱼的气垫船

这会让您感到困惑:

secundario.setPreferredSize(maximumSize);

通过设置组件的首选大小,可以防止它根据所拥有的组件实际计算其首选大小,这可能会阻止secundario组件扩展。首先摆脱这条线。

如果这不能完全解决您的问题,那么您将需要向我们展示您的最小,完整和可验证示例


您声明:

如果我删除了这条线,那么它可以工作,但是水平的,也就是说,面板连续添加一行,然后出现水平滚动条。我想垂直放置它们,并使用垂直滚动条,对不起,我没有提到。

这是与您的问题有关的关键信息,解决方案是使用一个或多个布局管理器来帮助您解决此问题。如果添加到secudario的所有组件都将具有相同的大小,请考虑为其提供GridLayout。然后,我要做的是使用JPanel将GridLayout添加到另一个使用BorderLayout的JPanel并将其添加到BorderLayout.PAGE_START位置,然后将第二个JPanel添加到JScrollPane的视口中。这样可以防止使用JPanel的GridLayout中的网格散开。


解决您的问题的一种方法是创建一个JPanel,该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。JButton具有一些操作,这些操作调用主类中的方法,这些方法告诉主类probMain2添加另一个RowPanel或删除此相同的RowPanel对象。

在主类ProbMain2中,我使用JPanel(这里称为rowHolderPanel)将RowPanels添加到GridLayout中,然后将该JPanel放置到BorderLayout.PAGE_START位置中,就像我最初建议的那样,将其放置到另一个使用BorderLayout的JPanel中。然后,我重新验证并重新绘制rowHolderPanel。我还将RowPanel添加到了ArrayList中,因此我可以更轻松地提取其保存的数据。

这是我完整的最小,完整和可验证的示例程序。请注意,它比您的要小很多,因为它试图消除所有与问题无关的代码(除了一些用于修饰结果的额外代码):

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

该代码具有两个非内部类,但是只有第一个是公共的并且具有main方法,因此这两个非内部类都可以存在于单个文件中。因为现在人们可以更轻松地将此代码复制并粘贴到他们的IDE中并进行测试,所以这使得mcve更好

更好的解决方案是摆脱持有人JPanel和RowPanel,而使用JTable,但是我今晚没有时间或精力进行此操作。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

jQuery滚动条不起作用

来自分类Dev

咒语滚动条不起作用

来自分类Dev

Tkinter滚动条不起作用

来自分类Dev

组碰撞在Pygame的平台滚动条上不起作用

来自分类Dev

完美的滚动条不起作用

来自分类Dev

高图滚动条不起作用

来自分类Dev

为什么我的Tkinter滚动条不起作用?

来自分类Dev

scrollarea中的滚动条不起作用

来自分类Dev

水平滚动条不起作用asp.net

来自分类Dev

滚动条在Java中不起作用

来自分类Dev

Python Tkinter滚动条不起作用

来自分类Dev

从idiotWu反应光滑的滚动条不起作用?

来自分类Dev

tkinter:滚动条出现但不起作用

来自分类Dev

为什么我的div滚动条不起作用?

来自分类Dev

隐藏滚动条在 Mozilla Firefox 中不起作用

来自分类Dev

滚动条不起作用 - Selenium Webdriver

来自分类Dev

约束布局中的滚动条不起作用

来自分类Dev

滚动条在 chrome 中不起作用,但在 Firefox 中起作用

来自分类Dev

画布和框架的宽度不起作用。框架内具有滚动条的画布不起作用。整个框架不可见

来自分类Dev

ASP.NET Gridview固定标题可滚动滚动条不起作用

来自分类Dev

具有自定义滚动条的jQuery选择框(roblaplaca)不起作用

来自分类Dev

extjs 5网格的滚动条在边框布局面板中不起作用

来自分类Dev

滚动条上的锚点突出显示在Firefox中不起作用

来自分类Dev

Chrome和Safari滚动条在Firefox中不起作用

来自分类Dev

当我在jscrollpane上添加jtable时,水平滚动条不起作用

来自分类Dev

ItemsControl [视图]滚动条在由BindableCollection填充时不起作用

来自分类Dev

添加垂直滚动条并更改其颜色不起作用

来自分类Dev

角材料自定义滚动条不起作用

来自分类Dev

滚动条上的突出显示菜单项不起作用

Related 相关文章

热门标签

归档