Añadir JScrollbar a JPanel con FlowLayout

Hola:
Me gustaria añadir un scrollbar a un jpanel con flowlayout y no hay manera, lo he intentado todo ya y no consigo hacerlo y lo peor de todo es que no se donde esta el fallo, la verdad es que soy bastante nuevo en java y aun tengo muchos fallos tontos por lo que me gustaria que alguien me pudiera ayudar a ver mi fallo y conseguir que salga la scrollbar.
Este es mi codigo:

 //Creamos el panel que contendra los botones de cada producto diferente
package com.foolsrecords.tpv.tablaproductos.vista;

//Hacemos todas las importaciones necesarias
import com.foolsrecords.tpv.modelo.Producto;
import com.foolsrecords.tpv.modelo.eventos.ControladorEventListener;
import com.foolsrecords.tpv.modelo.eventos.ProductoSeleccionadoListener;
import com.foolsrecords.tpv.servicios.ServicioItemVenta;
import com.foolsrecords.tpv.servicios.ServicioProducto;
import com.foolsrecords.tpv.vista.componentes.JProductoButton;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

//Creamos la clase principal
public class TablaProductos extends javax.swing.JPanel {

    //Creamos las variables y objetos necesarios para poder trabajar
    private Map<Integer, JProductoButton> mapaProductos;
    ProductoSeleccionadoListener objEven = new ProductoSeleccionadoListener(this);
    ServicioItemVenta servItemVenta = new ServicioItemVenta();

    //Creamos el constructor
    public TablaProductos() {
        initComponents();
        inicializarPanelProductos(0); //con los subproductos de tipo 1
    }

    //Inicializamos el panel de productos y le pasamos la familia de los productos como parametro para mostrar los botones correctos
    public void inicializarPanelProductos(int tipoProducto) {

        //Creamos un objeto para conectar con la base de datos a traves de la clase servicioproducto
        ServicioProducto servicio = new ServicioProducto();
       
        //Conectamos con la base de datos y cojemos los productos de la familia enviada como parametro
        List<Producto> productos = servicio.getProductos(tipoProducto);

        //Creamos un mapaproductos para poder crear los botones dinamicamente
        mapaProductos = new HashMap();

        //Borramos el panel jpanelproductos para montarlo de nuevo como nosotros queremos
        jpanelProductos.removeAll();

        //Creamos los 15 botones que contendra el panel y los hacemos todos invisibles
        for (int i = 1; i <= 30; i++) {
            mapaProductos.put(i, new JProductoButton());
            mapaProductos.get(i).addActionListener(objEven);
            mapaProductos.get(i).setVisible(false);
            jpanelProductos.add(mapaProductos.get(i), i - 1);
        }

        //Hacemos visibles tantos botones como productos tenemos en la familia enviada como parametro
        for (int i = 0; i < productos.size(); i++) {
             
            JProductoButton boton = mapaProductos.get(i + 1);
            UIManager.put("Button.select", Color.WHITE);
            boton.setVisible(true);
            boton.setProducto(productos.get(i));
            boton.setHorizontalTextPosition(SwingConstants.CENTER);
            boton.setVerticalTextPosition(SwingConstants.BOTTOM);
            boton.setFocusPainted(false);
            boton.setBackground(Color.WHITE);
            boton.setFont(new java.awt.Font("Arial", 1, 9));;
            boton.setText(productos.get(i).getDescripcion());
            boton.setIcon(new javax.swing.ImageIcon(productos.get(i).getImagen().getScaledInstance(88, 70, Image.SCALE_SMOOTH)));
            boton.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 204), 2));
            boton.setPreferredSize(new java.awt.Dimension(79, 97));
            boton.setMinimumSize(new java.awt.Dimension(79, 97));
            boton.setMaximumSize(new java.awt.Dimension(79, 97));
        }
       
        jpanelProductos.repaint();
    }

    //Este metodo es generado automaticamente por netbeans
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        jpanelProductos = new javax.swing.JPanel();

        setMinimumSize(new java.awt.Dimension(410, 300));
        setName(""); // NOI18N
        setPreferredSize(new java.awt.Dimension(410, 300));
        setLayout(null);

        jPanel1.setPreferredSize(new java.awt.Dimension(410, 300));
        jPanel1.setLayout(null);

        jpanelProductos.setPreferredSize(new java.awt.Dimension(400, 800));
        jpanelProductos.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 2, 2));
        jScrollPane2.setViewportView(jpanelProductos);

        jPanel1.add(jScrollPane2);
        jScrollPane2.setBounds(0, 0, 410, 300);

        add(jPanel1);
        jPanel1.setBounds(0, 0, 410, 300);
    }// </editor-fold>                        

    // Variables declaration - do not modify                    
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JPanel jpanelProductos;
    // End of variables declaration                  

    //Creamos los get y los set necesarios
    public javax.swing.JPanel getJpanelProductos() {
        return jpanelProductos;
    }

    public void setJpanelProductos(javax.swing.JPanel jpanelProductos) {
        this.jpanelProductos = jpanelProductos;
    }

    public void setControlador(ControladorEventListener controlador) {
        this.objEven.setControlador(controlador);
    }

}

Si alguien pudiera ayudarme le estare muy agradecido.
Gracias por todo.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

No entiendo cual es el problema

Hola, hice una pequeña prueba con el codigo que mostraste pero no entiendo cual es el problema que tienes o a qué resultado quieres llegar, esto es lo que me muestra a mi:

por favor proporciona más información

Hola: Gracias por todo, ya

Hola:

Gracias por todo, ya tengo funcionando mi codigo, simplemente lo borre todo y lo hice todo de nuevo por que ya me estaba volviendo loco y ahora todo funciona perfectamente, este es mi codigo nuevo:

 //Creamos el panel que contendra los botones de cada producto diferente
package com.foolsrecords.tpv.tablaproductos.vista;

//Hacemos todas las importaciones necesarias
import com.foolsrecords.tpv.modelo.Producto;
import com.foolsrecords.tpv.modelo.eventos.ControladorEventListener;
import com.foolsrecords.tpv.modelo.eventos.ProductoSeleccionadoListener;
import com.foolsrecords.tpv.servicios.ServicioItemVenta;
import com.foolsrecords.tpv.servicios.ServicioProducto;
import com.foolsrecords.tpv.vista.componentes.JProductoButton;
import java.awt.Color;
import java.awt.Image;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

//Creamos la clase principal
public class TablaProductos extends javax.swing.JPanel {

    //Creamos las variables y objetos necesarios para poder trabajar
    private Map<Integer, JProductoButton> mapaProductos;
    ProductoSeleccionadoListener objEven = new ProductoSeleccionadoListener(this);
    ServicioItemVenta servItemVenta = new ServicioItemVenta();

    //Creamos el constructor
    public TablaProductos() {
        initComponents();
        inicializarPanelProductos(0); //con los subproductos de tipo 1
    }

    //Inicializamos el panel de productos y le pasamos la familia de los productos como parametro para mostrar los botones correctos
    public void inicializarPanelProductos(int tipoProducto) {

        //Creamos un objeto para conectar con la base de datos a traves de la clase servicioproducto
        ServicioProducto servicio = new ServicioProducto();
       
        //Conectamos con la base de datos y cojemos los productos de la familia enviada como parametro
        List<Producto> productos = servicio.getProductos(tipoProducto);

        //Creamos un mapaproductos para poder crear los botones dinamicamente
        mapaProductos = new HashMap();

        //Borramos el panel jpanelproductos para montarlo de nuevo como nosotros queremos
        jpanelProductos.removeAll();

        //Creamos los 15 botones que contendra el panel y los hacemos todos invisibles
        for (int i = 1; i < productos.size()+2; i++) {
            mapaProductos.put(i, new JProductoButton());
            mapaProductos.get(i).addActionListener(objEven);
            mapaProductos.get(i).setVisible(false);
            jpanelProductos.add(mapaProductos.get(i), i - 1);
        }

        //Hacemos visibles tantos botones como productos tenemos en la familia enviada como parametro
        for (int i = 0; i < productos.size(); i++) {
             
            JProductoButton boton = mapaProductos.get(i + 1);
            UIManager.put("Button.select", Color.WHITE);
            boton.setVisible(true);
            boton.setProducto(productos.get(i));
            boton.setHorizontalTextPosition(SwingConstants.CENTER);
            boton.setVerticalTextPosition(SwingConstants.BOTTOM);
            boton.setFocusPainted(false);
            boton.setBackground(Color.WHITE);
            boton.setFont(new java.awt.Font("Arial", 1, 9));;
            boton.setText(productos.get(i).getDescripcion());
            boton.setIcon(new javax.swing.ImageIcon(productos.get(i).getImagen().getScaledInstance(88, 70, Image.SCALE_SMOOTH)));
            boton.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 204), 2));
            boton.setPreferredSize(new java.awt.Dimension(76, 97));
            boton.setMinimumSize(new java.awt.Dimension(76, 97));
            boton.setMaximumSize(new java.awt.Dimension(76, 97));
        }
       
        jpanelProductos.repaint();
    }

    //Este metodo es generado automaticamente por netbeans
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane2 = new javax.swing.JScrollPane();
        jpanelProductos = new javax.swing.JPanel();

        setMinimumSize(new java.awt.Dimension(410, 300));
        setName(""); // NOI18N
        setPreferredSize(new java.awt.Dimension(410, 300));
        setLayout(null);

        jpanelProductos.setPreferredSize(new java.awt.Dimension(350, 2000));
        jpanelProductos.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 2, 2));
        jScrollPane2.setViewportView(jpanelProductos);

        add(jScrollPane2);
        jScrollPane2.setBounds(0, 0, 410, 300);
    }// </editor-fold>                        

    // Variables declaration - do not modify                    
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JPanel jpanelProductos;
    // End of variables declaration                  

    //Creamos los get y los set necesarios
    public javax.swing.JPanel getJpanelProductos() {
        return jpanelProductos;
    }

    public void setJpanelProductos(javax.swing.JPanel jpanelProductos) {
        this.jpanelProductos = jpanelProductos;
    }

    public void setControlador(ControladorEventListener controlador) {
        this.objEven.setControlador(controlador);
    }

    public javax.swing.JScrollPane getjScrollPane2() {
        return jScrollPane2;
    }

    public void setjScrollPane2(javax.swing.JScrollPane jScrollPane2) {
        this.jScrollPane2 = jScrollPane2;
    }

}

Ahora simplemente tengo un pequeño problema, la barra de scroll aparece siempre y yo quiero que aparezca solo cuando sea necesario, se que el problema es debido a que el jpanel es mucho mas grande que el jscrollpane pero lo tenia que poner mas grande para que saliera el scroll y no se como hacer que el jpanel crezca conforme voy añadiendo los botones de los distintos productos, si alguien puede ayudarme con esto o darme alguna idea estare muy agradecido.

Un saludo.

Encontré esto

No se exactamente como solucionar el problema, pero investigando un poco en internet me encontré con esto: http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.htm...
que quizá te pueda ayudar...
Haré unas pruebas con esos ejemplos un poco más tarde cuando tenga tiempo

Pues

Pues agregando los botones manualmente al panel (mediante el evento clic de otro boton), el panel si cambia de tamaño gracias al método JPanel.revalidate(); y tienen el efecto que tú quieres. Por lo que más o menos veo, el problema está en que los botones se crean automáticamente dentro de un ciclo for y, aunque llame a revalidate(), el panel no cambia de tamaño.
Seguiré investigando alguna forma de agregar automáticamente los botones y hacer que crezca el panel, o tal vez ofrecerte una alternativa, como por ejemplo usar un JTable para mostrar los productos y utilizar un botón aparte y hacer que la acción del botón y la selección de una fila en el JTable se junten para pasar la información del producto a otro formulario, que yo supongo es lo que quieres hacer.

Espero haberme dado a entender bien...

Al parecer ya quedó

Después de experimentar un poco (o mucho) y de buscar, hice un par de modificaciones que quizá hagan que quede tu formulario como tienes planeado...
algunos de los cambios son estos:

  • Llamar a jpanelProductos.revalidate(); y jpanelProductos.repaint(); después del ciclo donde haces visibles los botones
  • Darle a tu JFrame un layout de tipo BorderLayout, desconozco cómo lo estás asignando pero supongo por el código que has proporcionado que estás usando netbeans, si es así, puedes dar clic derecho en tu JFrame y en la opción de Set Layout le das un BorderLayout. O si es mediante código: frame.setLayout(new BorderLayout();
  • Darle a tu objeto de tipo TablaProductos un layout de tipo BorderLayout, igual que como en el punto anterior
  • Evitar el uso de setPreferredSize();
  • Cambiar el layout de tu jpanelProductos por un layout de tipo GridLayout con 0 filas, 5 columnas y espacios vertical y horizontal de 2. Si usas netbeans, puedes seguir un procedimiento parecido a los anteriores para asignar un GridLayout, solo le cambias las propiedades de las filas y las columnas. O si es mediante código: GridLayout gl = new java.awt.GridLayout(0, 5); gl.setHgap(3); gl.setVgap(3);

Espero no se me olvide nada mas! y que esto te ayude

Hola pc-carm:Muchisimas

Hola pc-carm:

Muchisimas gracias por todo de verdad, me has guiado por el buen camino y gracias a ti lo tengo funcionando ya, si necesitas algo mio solo tienes que pedirmelo, muchisimas gracias de verdad.
Te explico, tu codigo no me ha servido tal y como me lo pones pero gracias a ti he dado con la solucion que es lo que cuenta. Lo que me dices iba perfecto pero tenia un pequeño problema con el gridlayout por eso lo quite ya de un principio, el problema es que igual hay un producto en el panel que 300 y cuando hay mas de 10 todo es perfecto pero si hay menos queda mal, te pongo unas imagenes para ke lo veas:

PANEL CON MAS DE 10 PRODUCTOS:

http://i57.tinypic.com/9fn0v4.jpg

PANEL CON MENOS DE 10 PRODUCTOS:

http://i62.tinypic.com/34zgbpg.jpg

Eso es lo que me pasa con tu solucion y ya me pasaba antes, pero gracias a ti he investigado por el buen camino y ya lo tengo solucionado todo y funcionando a la perfeccion, lo que te agradezco enormemente, solo he tenido que añadir 4 lineas de codigo que son estas:

 double alto = (double)((double)productos.size()/5);
        int valor1 = (int) Math.ceil(alto) ;
        int valor = valor1 * 100;
        jpanelProductos.setPreferredSize(new java.awt.Dimension(350, valor));

Ahora ya todo funciona perfectamente, muchisimas gracias de nuevo, te debo una y gorda jejejeje.

Por si alguien lo quiere o

Por si alguien lo quiere o por si tu quieres verlo pc-carm dejo el codigo completo que funciona perfectamente:

 //Creamos el panel que contendra los botones de cada producto diferente
package com.foolsrecords.tpv.tablaproductos.vista;

//Hacemos todas las importaciones necesarias
import com.foolsrecords.tpv.modelo.Producto;
import com.foolsrecords.tpv.modelo.eventos.ControladorEventListener;
import com.foolsrecords.tpv.modelo.eventos.ProductoSeleccionadoListener;
import com.foolsrecords.tpv.servicios.ServicioProducto;
import com.foolsrecords.tpv.vista.componentes.JProductoButton;
import java.awt.Color;
import java.awt.Image;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

//Creamos la clase principal
public class TablaProductos extends javax.swing.JPanel {

    //Creamos las variables y objetos necesarios para poder trabajar
    private Map<Integer, JProductoButton> mapaProductos;
    ProductoSeleccionadoListener objEven = new ProductoSeleccionadoListener(this);

    //Creamos el constructor
    public TablaProductos() {
        initComponents();
        inicializarPanelProductos(0); //con los subproductos de tipo 1
    }

    //Inicializamos el panel de productos y le pasamos la familia de los productos como parametro para mostrar los botones correctos
    public void inicializarPanelProductos(int tipoProducto) {

        //Creamos un objeto para conectar con la base de datos a traves de la clase servicioproducto
        ServicioProducto servicio = new ServicioProducto();
       
        //Conectamos con la base de datos y cojemos los productos de la familia enviada como parametro
        List<Producto> productos = servicio.getProductos(tipoProducto);

        //Creamos un mapaproductos para poder crear los botones dinamicamente
        mapaProductos = new HashMap();

        //Borramos el panel jpanelproductos para montarlo de nuevo como nosotros queremos
        jpanelProductos.removeAll();

        //Creamos los 15 botones que contendra el panel y los hacemos todos invisibles
        for (int i = 1; i < productos.size()+2; i++) {
            mapaProductos.put(i, new JProductoButton());
            mapaProductos.get(i).addActionListener(objEven);
            mapaProductos.get(i).setVisible(false);
            jpanelProductos.add(mapaProductos.get(i), i - 1);
        }

        //Hacemos visibles tantos botones como productos tenemos en la familia enviada como parametro
        for (int i = 0; i < productos.size(); i++) {
             
            JProductoButton boton = mapaProductos.get(i + 1);
            UIManager.put("Button.select", Color.WHITE);
            boton.setVisible(true);
            boton.setProducto(productos.get(i));
            boton.setHorizontalTextPosition(SwingConstants.CENTER);
            boton.setVerticalTextPosition(SwingConstants.BOTTOM);
            boton.setFocusPainted(false);
            boton.setBackground(Color.WHITE);
            boton.setFont(new java.awt.Font("Arial", 1, 9));;
            boton.setText(productos.get(i).getDescripcion());
            boton.setIcon(new javax.swing.ImageIcon(productos.get(i).getImagen().getScaledInstance(76, 70, Image.SCALE_SMOOTH)));
            boton.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 204), 2));
            boton.setPreferredSize(new java.awt.Dimension(76, 97));
            boton.setMinimumSize(new java.awt.Dimension(76, 97));
            boton.setMaximumSize(new java.awt.Dimension(76, 97));
        }

        double alto = (double)((double)productos.size()/5);
        int valor1 = (int) Math.ceil(alto) ;
        int valor = valor1 * 100;
        jpanelProductos.setPreferredSize(new java.awt.Dimension(350, valor));
        jpanelProductos.repaint();
        jpanelProductos.revalidate();
    }

    //Este metodo es generado automaticamente por netbeans
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane2 = new javax.swing.JScrollPane();
        jpanelProductos = new javax.swing.JPanel();

        setMinimumSize(new java.awt.Dimension(410, 300));
        setName(""); // NOI18N
        setPreferredSize(new java.awt.Dimension(410, 300));
        setLayout(null);

        jScrollPane2.setBorder(null);

        jpanelProductos.setPreferredSize(new java.awt.Dimension(350, 10));
        jpanelProductos.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 2, 2));
        jScrollPane2.setViewportView(jpanelProductos);

        add(jScrollPane2);
        jScrollPane2.setBounds(0, 0, 410, 300);
    }// </editor-fold>                        

    // Variables declaration - do not modify                    
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JPanel jpanelProductos;
    // End of variables declaration                  

    //Creamos los get y los set necesarios
    public javax.swing.JPanel getJpanelProductos() {
        return jpanelProductos;
    }

    public void setJpanelProductos(javax.swing.JPanel jpanelProductos) {
        this.jpanelProductos = jpanelProductos;
    }

    public void setControlador(ControladorEventListener controlador) {
        this.objEven.setControlador(controlador);
    }

    public javax.swing.JScrollPane getjScrollPane2() {
        return jScrollPane2;
    }

    public void setjScrollPane2(javax.swing.JScrollPane jScrollPane2) {
        this.jScrollPane2 = jScrollPane2;
    }

}

De nuevo muchas gracias por todo.