当前位置:  开发笔记 > 编程语言 > 正文

滚动条不适用于JPane内的JScrollPanel

如何解决《滚动条不适用于JPane内的JScrollPanel》经验,为你挑选了1个好方法。

我正在尝试编写一个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
* 

* Interfaz gráfica. * * @author Berta García Sanz * @author Héctor Mamolar Albitre * * @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 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 listFichDatos; private ArrayList listFichDisp; private JTextField macDispConcreto; private ArrayList listDispConcretos; private Thread capturas; private Thread localizaciones; private JComboBox boxPuntosAcceso; private ArrayList listPAActivar; private ArrayList rutasModulos; private ArrayList parametros; // Permite ir añadiendo elementos a la interfaz tras inicializarlo private JPanel secundario; private Dimension maximumSize; private ArrayList 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(); listFichDisp = new ArrayList(); listDispConcretos = new ArrayList(); listPAActivar = new ArrayList(); panelesModulos = new ArrayList(); 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

谢谢您的帮助.



1> Hovercraft F..:

这会搞砸你:

secundario.setPreferredSize(maximumSize);

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

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


你说:

如果我删除这一行它可以工作但水平,我的意思是,面板连续添加一行,并出现水平滚动条.我想垂直使用垂直滚动条,抱歉我没有提到它.

这是影响您的问题的关键信息,解决方案是使用布局管理器或布局管理器来帮助您解决此问题.如果添加到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);
        }
    }
}

有两个JTextFields和两个JButtons.JButtons具有调用主类中的方法的Actions,它们告诉主类probMain2添加另一个RowPanel,或者删除这个相同的RowPanel对象.

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

这是我完整的Minimal,Complete和Verifiable示例程序.请注意,它比你的小得多,因为它试图消除与问题无关的所有代码(除了一些额外的代码来美化结果):

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 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,但我今晚没有时间或精力来做这件事.

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有