ScrollPane adding to grid layout

2019-09-18 14:00发布

问题:

in my code I am calling a few items(my buttons with their names leading to different project. The names and everything are taken from a database) I want a J ScrollPane to surround my buttons, what can I do? I just want the buttons to be called inside the scroll pane. Here is my code

import java.sql.*;
import java.util.ArrayList;

import java.util.List;

import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JLabel;

import javax.swing.JButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;


public class AdminClass implements ActionListener  {

ProjectButton[] buttons = new ProjectButton[35];

//Creating data field for unique Ids in the form of array list
ArrayList<Integer> uniqueIDList = new ArrayList<Integer>();
String[] projectNames;
int[] uniqueIds;

Connection conn1 = null;
Statement stmt1 = null;

JFrame frame = new JFrame("Admin Panel");
private JPanel panel = new JPanel();
JButton btnNewButton = new JButton("Add New Project");

public AdminClass() {

    panel.setLayout(new GridLayout(10, 1));

    panel.add(new JLabel("Welcome to Admin Panel"));

    btnNewButton.addActionListener(this);
    panel.add(btnNewButton);

    panel.add(new JLabel("Existing Projects"));

    conn1 = sqliteConnection.dbConnector();

    try{
          Class.forName("org.sqlite.JDBC");
          conn1.setAutoCommit(false);
          stmt1 = conn1.createStatement();
          ResultSet rs1 = stmt1.executeQuery( "SELECT * FROM Project;" );

          List<String> projectNameList = new ArrayList<String>();

          while ( rs1.next() ){
              int id = rs1.getInt("uniqueid");
              String projectName = rs1.getString("name");

              projectNameList.add(projectName);
              uniqueIDList.add(id);
          }

          // Converting array list to array
          projectNames = new String[projectNameList.size()];
          projectNameList.toArray(projectNames);

          uniqueIds = convertIntegers(uniqueIDList);


          rs1.close();
          stmt1.close();
          conn1.close();
    }
    catch ( Exception e1 ) {
        JOptionPane.showMessageDialog(null, e1);    
    }

    // Adding buttons to the project
    try{
        for (int i = 0; i < projectNames.length; i++){
            buttons[i] = new ProjectButton(projectNames[i]);
            buttons[i].setId(uniqueIds[i]);

            panel.add(buttons[i]);
            buttons[i].addActionListener(this);

        }
    }
    catch (Exception e2){
        JOptionPane.showMessageDialog(null, e2);
    }

    frame.add(panel);
    frame.setVisible(true);
    frame.setSize(500, 500);

}

public void actionPerformed(ActionEvent e) {

    for (int j = 0; j < buttons.length; j ++){
        if (e.getSource() == buttons[j]){
            AdminStatus sc = new AdminStatus(buttons[j].getId());
            frame.dispose();
        }
    }

    if (e.getSource() == btnNewButton){

        frame.dispose();
        WindowProjectAdmin wpa = new WindowProjectAdmin();

    }

}

//Method to convert integar array list to integar array
public int[] convertIntegers(List<Integer> integers)
    {
        int[] ret = new int[integers.size()];
        for (int i=0; i < ret.length; i++)
        {
            ret[i] = integers.get(i).intValue();
        }
        return ret;
    }

}

This may seem very normal but it's really not, for some reason they are not visible or are not called inside a scroller. Please edit my code maybe?

回答1:

Start by adding the buttons to their own container, this way you can control the layout of the buttons separately from the rest of the UI

    JPanel panelFullOfButtons = new JPanel();
    try {
        for (int i = 0; i < projectNames.length; i++) {
            buttons[i] = new ProjectButton(projectNames[i]);
            buttons[i].setId(uniqueIds[i]);

            panelFullOfButtons.add(buttons[i]);
            buttons[i].addActionListener(this);

        }
    } catch (Exception e2) {
        JOptionPane.showMessageDialog(null, e2);
    }

Then add the "main" panel to the NORTH position of the frame and the "buttons" panel to the CENTER

    frame.add(panel, BorderLayout.NORTH);
    frame.add(new JScrollPane(panelFullOfButtons), BorderLayout.CENTER);

Mind you, in this case, I'd be very tempted to use something like a JList instead. See How to Use Lists for more details

I have done the same, can you tell me what's wrong?

// Problem #1...
JScrollPane pane = new JScrollPane();
pane.add(buttonPanel);

//...
// Problem #2...
panel.add(pane);
frame.add(panel);

These are competing with each other, moving the content around and overlapping with existing content...

public AdminClass() {

    panel.setLayout(new GridLayout(3, 1));

    panel.add(new JLabel("Welcome to Admin Panel"));

    btnNewButton.addActionListener(this);
    panel.add(btnNewButton);

    panel.add(new JLabel("Existing Projects"));

    List<String> projectNameList = new ArrayList<String>();
    for (int index = 0; index < 1000; index++) {
        projectNameList.add("Project " + index);
    }
    projectNames = projectNameList.toArray(new String[0]);

    // Adding buttons to the project
    buttons = new JButton[projectNameList.size()];
    try {
        for (int i = 0; i < projectNames.length; i++) {
            buttons[i] = new JButton(projectNames[i]);

            btnPnl1.add(buttons[i]);
            buttons[i].addActionListener(this);

        }
    } catch (Exception e2) {
        JOptionPane.showMessageDialog(null, e2);
    }

    frame.add(panel, BorderLayout.NORTH);
    frame.add(new JScrollPane(btnPnl1), BorderLayout.CENTER);

    frame.setVisible(true);
    frame.setSize(500, 500);

}

In this case I'd prefer to use either a JList to show the projects or a WrapLayout for laying out the buttons



回答2:

Its useless to create a GridLayout like this: panel.setLayout(new GridLayout(10, 1));. If you declare the rows as a non zero value, the column count will be ignored. When you declare the maximum number of rows as ten, you force the eleventh component to be added in a second column (then a third, a forth and so on). Use panel.setLayout(new GridLayout(0, 1)); instead to force the only one column and frame.add(new JScrollPane(panel)); to create the ScrollPane.

But note that GridLayout will try to shrink your components the maximum as possible to fit the container size before scrolling is enabled.



回答3:

I just want the button part to be inside J Scroll Pane

If you just want the JButton's (those added within the loop):

  1. Create a new JPanel that you add the buttons to
  2. Add (1) to a JScrollPane
  3. Add (2) to panel

For example:

JPanel buttonPanel = new JPanel(new FlowLayout());
for (int i = 0; i < projectNames.length; i++){
    buttons[i] = new ProjectButton(projectNames[i]);
    buttons[i].setId(uniqueIds[i]);
    panel.add(buttons[i]);
    buttonPanel[i].addActionListener(this);
}
JScrollPane scroller = new JScrollPane(buttonPanel);
panel.add(scroller);

You might also consider using a different Component that doesn't require a JScrollPane, of course depending upon your needs - for instance a JComboBox.