JScrollPane and GridBagLayout problems while creating Inspector-like thing - java

I am creating something like inspector panel for my program, so I can easily change some variables at runtime.
When you run the code bellow, you should see something like this:
inspector screenshot
There are several things that bothers me and I still cannot make them to work properly.
Items are verticaly aligned to the center... I have tried setting anchor to the North but it remains the same. In the example code bellow, there is one line commented out that can fix this: inspector.finish() but the solution seems kinda hacky to me. It works by adding empty JPanel as last item on the panel, acting as some kind of vertical glue to expand the lower area and push the components up. I don't like this, because with this solution I no longer can add more items to the inspector later at runtime.
If you add more items to the inspector (you can do this by changing n variable that fills the inspector with some test data) the scroll bar will not show up, and all the lower items are out of screen even it's all wrapped inside JScrollPane... I have tried several hacks to fix this but none of them works correctly. One of them was setting preferredSize of JPanel to some hard-coded dimensions but I don't like this because I don't know exact size of the panel.
When you push some of the spinner buttons and then click on the combobox (titled as "choose me"), the options are hidden behind the button bellow. This looks like some kind of z-ordering issue. Maybe this is bug in swing, dunno.
When you resizing the window vertically to smaller size, the items on the top will begin to shrink instead of staying the same size. Is there any option to set them constant height at all times?
Maybe I am using the wrong layout manager, but I don't know which other one to choose. I was thinking about simple grid layout, but this does not allow me to do things like having some rows with one item and others with multiple items in such a way that they will always use the whole width "capacity" of the row.
example code:
import java.awt.*;
import javax.swing.*;
public class Test {
// Setup test scenario
public Test() {
// Create window
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.setSize(800, 600);
f.setTitle("Inspector");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Create panel which will be used for the inspector
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(200, 0));
// Encapsulate it to the scroll panel so it can grow vertically
JScrollPane sp = new JScrollPane();
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
sp.setViewportView(p);
// Create the inspector inside panel p
Inspector inspector = new Inspector(p);
// Fill the inspector with some test data
int n = 3;
for (int i = 0; i < n; ++i) {
inspector.addTitle("Title");
inspector.addButton("push me");
inspector.addCheckBox("check me");
inspector.addSpinner("Spin me");
inspector.addTextField("Edit me", "here");
inspector.addComboBox("Choose one", new String[]{"A", "B", "C"});
inspector.addSeparator();
}
//inspector.finish();
// The inspector will be on the right side of the window
f.getContentPane().add(sp, BorderLayout.LINE_END);
// Show the window
f.setVisible(true);
}
// Main method
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
// Inspector class itself
private class Inspector {
private final JPanel panel;
private final GridBagConstraints constraints;
private int itemsCount = 0;
public Inspector(JPanel p) {
panel = p;
panel.setLayout(new GridBagLayout());
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 0.5;
}
// Adds component which will span across whole row
private void addComponent(Component component) {
constraints.gridx = 0;
constraints.gridwidth = 2;
constraints.gridy = itemsCount;
panel.add(component, constraints);
itemsCount++;
}
// Adds descriptive label on the left and component on the right side of the row
private void addNamedComponent(String description, Component component) {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(new JLabel(description), constraints);
constraints.gridx = 1;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(component, constraints);
itemsCount++;
}
public void addSeparator() {
// (little hacky)
addComponent(new JPanel());
}
public void addTitle(String title) {
addComponent(new JLabel(title));
}
public void addButton(String actionName) {
addComponent(new Button(actionName));
}
public void addCheckBox(String description) {
addNamedComponent(description, new JCheckBox());
}
public void addSpinner(String description) {
addNamedComponent(description, new JSpinner());
}
public void addTextField(String description, String text) {
addNamedComponent(description, new JTextField(text));
}
public void addComboBox(String description, String[] options) {
JComboBox<String> comboBox = new JComboBox<>();
ComboBoxModel<String> model = new DefaultComboBoxModel<>(options);
comboBox.setModel(model);
addNamedComponent(description, comboBox);
}
public void finish() {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 2;
constraints.weighty = 1.0;
panel.add(new JPanel(), constraints);
}
}
}

The Reason that you can't scroll up or down is because you are setting the preferred size of sp to 200x0. You need to remove this line.
p.setPreferredSize(new Dimension(200, 0));
As for the issue with everything being centered instead of at the top. I would prefer to leave p with the default FlowLayout and give each "section" it's own panel, and the make that panel a GridBagLayout. By doing this you probably will not need addSeparator() anymore.
public class Test {
// Setup test scenario
public Test() {
// Create window
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.setSize(800, 600);
f.setTitle("Inspector");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Create panel which will be used for the inspector
JPanel p = new JPanel();
// Encapsulate it to the scroll panel so it can grow vertically
JScrollPane sp = new JScrollPane();
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
sp.setViewportView(p);
// Create the inspector inside panel p
Inspector inspector = new Inspector(p);
// Fill the inspector with some test data
int n = 2;
for (int i = 0; i < n; ++i) {
inspector.addTitle("Title");
inspector.addButton("push me");
inspector.addCheckBox("check me");
inspector.addSpinner("Spin me");
inspector.addTextField("Edit me", "here");
inspector.addComboBox("Choose one", new String[]{"A", "B", "C"});
}
// The inspector will be on the right side of the window
f.getContentPane().add(sp, BorderLayout.LINE_END);
// Show the window
f.setVisible(true);
}
// Main method
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
// Inspector class itself
private class Inspector {
private final JPanel panel;
private final GridBagConstraints constraints;
private int itemsCount = 0;
public Inspector(JPanel p) {
panel = new JPanel();
p.add(panel);
panel.setLayout(new GridBagLayout());
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1.0;
}
// Adds component which will span across whole row
private void addComponent(Component component) {
constraints.gridx = 0;
constraints.gridwidth = 2;
constraints.gridy = itemsCount;
panel.add(component, constraints);
itemsCount++;
}
// Adds descriptive label on the left and component on the right side of the row
private void addNamedComponent(String description, Component component) {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(new JLabel(description), constraints);
constraints.gridx = 1;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(component, constraints);
itemsCount++;
}
public void addSeparator() {
// (little hacky)
addComponent(new JPanel());
}
public void addTitle(String title) {
addComponent(new JLabel(title));
}
public void addButton(String actionName) {
addComponent(new Button(actionName));
}
public void addCheckBox(String description) {
addNamedComponent(description, new JCheckBox());
}
public void addSpinner(String description) {
addNamedComponent(description, new JSpinner());
}
public void addTextField(String description, String text) {
addNamedComponent(description, new JTextField(text));
}
public void addComboBox(String description, String[] options) {
JComboBox<String> comboBox = new JComboBox<>();
ComboBoxModel<String> model = new DefaultComboBoxModel<>(options);
comboBox.setModel(model);
addNamedComponent(description, comboBox);
}
public void finish() {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 2;
constraints.weighty = 1.0;
panel.add(new JPanel(), constraints);
}
}
}

Related

Spaces between elements in GridLayout and GridBagLayout

I am trying to create a grid of text fields which I envision would look like this:
I am trying to use Swing in order to do this but am having trouble creating the grid. I have tried both GridBagLayout and GridLayout in order to accomplish this but have had the same issue with both - I am unable to remove spaces between the text fields.
The above image is using grid bag layout. I have tried to change the insets as well as the weights of each text field but have not been able to get rid of the spaces between the fields.
The grid layout is slightly better:
But it has the same problem. I tried adding each text field to a JPanel and then created an empty border for each panel but this also did not work.
I have attached the code for both implementations. I am not committed to using a JTextField so if there is some other element that a user can type into I would be willing to try that out as well. Any help getting rid of the spaces between each text field would be greatly appreciated!
GridBagLayoutDemo
class GridBagLayoutDemo {
public static void addComponentsToPane(Container pane) {
GridBagLayout gbl = new GridBagLayout();
pane.setLayout(gbl);
GridBagConstraints c = new GridBagConstraints();
int rows = 2;
int cols = 2;
for(int i = 0; i < (rows + 1) * 3; i++){
JTextField textField = new JTextField(1);
textField.setFont( new Font("Serif", Font.PLAIN, 30) );
JPanel tempPanel = new JPanel();
tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
tempPanel.add(textField);
c.gridx = i % (rows + 1);
c.gridy = i / (cols + 1);
c.gridheight = 1;
c.gridwidth = 1;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.HORIZONTAL;
pane.add(tempPanel, c);
}
gbl.setConstraints(pane, c);
c.insets = new Insets(0,0,0,0);
}
public void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("GridBagLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridBagLayoutDemo demo = new GridBagLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
GridLayoutDemo
class GridLayoutDemo {
public void createAndShowGUI() {
JFrame frame = new JFrame("GridLayout");
//frame.setOpacity(0L);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel parentPanel = new JPanel();
GridLayout layout = new GridLayout(3, 3, 0, 0);
layout.setHgap(0);
layout.setVgap(0);
parentPanel.setLayout(layout);
for(int i = 0 ; i < 9; i++){
JTextField textField = new JTextField();
textField.setHorizontalAlignment(JTextField.CENTER);
// JPanel tempPanel = new JPanel();
//textField.setBounds(0, 0, 10 , 10);
//textField.setFont( new Font("Serif", Font.PLAIN, 18));
//tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
//tempPanel.add(textField);
// tempPanel.add(textField);
parentPanel.add(textField);
}
frame.add(parentPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridLayoutDemo demo = new GridLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
I think you will find that this is a issue with the MacOS look and feel, as it adds a empty border around the text fields to allow for the focus highlight
You can see it highlighted below
The simplest way to remove it, is to remove or replace the border, for example...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
int rows = 3;
int cols = 3;
for (int index = 0; index < (rows * cols); index++) {
int row = index % rows;
int col = index / cols;
gbc.gridy = row;
gbc.gridx = col;
JTextField textField = new JTextField(4);
textField.setText(col + "x" + row);
textField.setBorder(new LineBorder(Color.DARK_GRAY));
add(textField, gbc);
}
}
}
}

How to Create JPanels in a Loop and insert them in JPanel Array [] []

Hi guys I'm using Eclipse and I'm trying to create a Connect4 Game Grid , which is an JPanel gridArray [6] [7]. I later add the different Panels for buttons and the grid into a main panel and add it into my frame.
My Problem:
I want to fill the gridArray JPanel with Pictures of an empty field(white color) but first of all i want to create a new Panel and insert it into my gridArray through a loop until gridArray has all 42 Panels inside it and is fully filled. I have my Code below but somehow it doesnt work, although my logic should be fine.
I tried it with using a helper Function to create a new JPanel and call the function for each loop in fillGrid();, basically calling it 42 times but it still wont work...
I will gladly appreciate some help!
package connect4;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class GridTest extends JFrame {
JFrame mainWindow;
JPanel buttonPanel, mainPanel;
JPanel gridPanel;
JPanel emptyPanel;
JPanel panel1;
ImageIcon emptyBox;
JPanel[][] gridArray;
JLabel emptyLabel;
JButton arrow1,arrow2,arrow3,arrow4,arrow5,arrow6,arrow7;
public GridTest() {
createGameGrid();
fillGrid();
}
public void createGameGrid() {
//creating window and mainpanel
mainWindow = new JFrame("Connect 4");
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
//defining top panel with 7 buttons;
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 7));
arrow1 = new JButton("V");
arrow2 = new JButton("V");
arrow3 = new JButton("V");
arrow4 = new JButton("V");
arrow5 = new JButton("V");
arrow6 = new JButton("V");
arrow7 = new JButton("V");
buttonPanel.add(arrow1);
buttonPanel.add(arrow2);
buttonPanel.add(arrow3);
buttonPanel.add(arrow4);
buttonPanel.add(arrow5);
buttonPanel.add(arrow6);
buttonPanel.add(arrow7);
//create Grind Panel
gridPanel = new JPanel();
gridPanel.setLayout(new GridLayout(6,7));
mainPanel.add(buttonPanel, BorderLayout.NORTH);
mainPanel.add(gridPanel, BorderLayout.SOUTH);
mainWindow.add(mainPanel);
mainWindow.pack();
mainWindow.setLocationRelativeTo(null);
mainWindow.setVisible(true);
}
private JPanel greateOnePanel(){
//here we need to insert the icon which is in empty box into a newly created panel
//ifirst wanted to insert black panels do ensure it works as intended but it doesnt
JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
panel.setSize(50,50);
return panel;
}
//here we need to fill the grid with the panels created above from left to right...
public void fillGrid() {
for(int j = 0; j < 6; j++) {
for (int k = 0; k < 7; k++) {
gridPanel.add(greateOnePanel());
}
}
}
public static void main(String[] args) {
new GridTest();
}
}
i tried it with this method using gridArray, but it throws NullPointer Exeptions and wont fill the grid with simple textlabels "Hallo" (just for testing purposes)
public void fillGrid() {
for(int j = 0; j < 6; j++) {
for (int k = 0; k < 7; k++) {
JLabel label = new JLabel("Hallo");
gridArray[j][k] = new JPanel();
gridArray[j][k].setSize(50, 50);
gridArray[j][k].setBackground(Color.RED);
gridArray[j][k].add(label);
gridPanel.add(gridArray[j][k]);
}
}
}
Here is a short, self contained, code that should help with various aspects of the task.
There is no need for a panel in each cell. The only thing it helped with was setting a BG color. That can be done in a label as long as the background is set to opaque.
This code defines a SquareLabel which overrides getPreferredSize() to return the maximum of preferred width and height as the value of both (usually it is the width).
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class SquareLabelGrid {
int rows = 6;
int cols = 7;
JLabel[][] labelArray = new JLabel[cols][rows];
Font bigFont = new Font(Font.SANS_SERIF, Font.BOLD, 30);
Insets labelInsets;
SquareLabelGrid() {
JPanel gameBoard = new JPanel(new GridLayout(rows, cols));
// a border to make the cell boundaries more clear and add
// some space around the text
Border border = new CompoundBorder(
new LineBorder(Color.BLACK),new EmptyBorder(4,4,4,4));
for (int yy = 0; yy < rows; yy++) {
for (int xx = 0; xx < cols; xx++) {
JLabel l = getColoredSquareLabel(xx, yy);
labelArray[xx][yy] = l;
gameBoard.add(l);
l.setBorder(border);
}
}
JOptionPane.showMessageDialog(null, gameBoard);
}
private JLabel getColoredSquareLabel(int x, int y) {
SquareLabel label = new SquareLabel(
String.format("%1s,%1s", (x+1), (y+1)));
label.setFont(bigFont);
label.setOpaque(true); // so we can see the BG color
label.setBackground(Color.ORANGE); // I prefer orange!
// make the GUI less 'crowded'
label.setBorder(new EmptyBorder(4,4,4,4));
return label;
}
public static void main(String[] args) {
Runnable r = () -> {
new SquareLabelGrid();
};
SwingUtilities.invokeLater(r);
}
}
class SquareLabel extends JLabel {
SquareLabel(String label) {
super(label);
}
/* This will create a square component that accounts for the
size of the String / Icon it contains. No guesswork! */
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
int w = d.width;
int h = d.height;
int sz = w > h ? w : h;
return new Dimension(sz, sz);
}
}
The problem is that you have not initialized the grid array .
Otherwise it will throw Null pointer exception.
JPanel[][] gridArray = new JPanel[6][8];
Also set the preferred size of main panel to make the grids visible .
mainPanel.setPreferredSize(new Dimension(400, 200));
Here is what i can see when I run your code with the modifications mentioned here .
Also please execute it from main with following code .
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GridTest();
}
});
}

Trying to show a JTable and a JTabbedPane in the same Container

I am trying to make a JFrame for displaying the data that my beta-testers are to send me (this part I have already done), and a JTabbedPane for the charts (for their use). //I am hoping for something that, ignoring stuff like the look-and-feel (and coloring; I was too lazy to color the picture all the way), would look something like this:
. //I would have to use CardLayout for the JComboBox to display a different table and a different JTabbedPane for the newly-selected mode; that means two tables and two JTabbedPanes.
I have tried to make a small (extremely-simplified!) example of this setup, a JFrame with only a (very simple!) JTabbedPane and a small JTable. The example works if I give my JPanel (that houses both components) a BorderLayout, but as soon as I give it a GridLayout (or a GridBagLayout //the very Layout I will end up using), only the last component displays no matter what I try! Why is this?
If it would help any (it might, given how much of a newbie I am to this), here is the example code:
JPanelLayoutTest.java
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
public class JPanelLayoutTest extends JFrame {
private JPanel aPanel;
private JTabbedPane tabbedPane;
private JTable someTable;
public JPanelLayoutTest(String title) throws HeadlessException {
super(title);
aPanel = setupPanel();
}
private JPanel setupPanel()
{
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
//making the panel have two columns and one row
JPanel panel = new JPanel(gridBag);
//add someTable to top
someTable = new JTable(new SampleTableModel());
/*JPanel somePanel = new JPanel();
somePanel.add(new JScrollPane(someTable));*/
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridheight = 1;
constraints.gridwidth = 1;
gridBag.setConstraints(new JScrollPane(someTable), constraints);
add(new JScrollPane(someTable));
//add tabbedPane to bottom
tabbedPane = new JTabbedPane();
tabbedPane.addTab("some component", new JLabel("some text"));
/*JPanel someOtherPanel = new JPanel();
someOtherPanel.add(tabbedPane);*/
constraints.gridy = 1;
gridBag.setConstraints(tabbedPane, constraints);
add(tabbedPane);
//add(tabbedPane);
return panel;
}
public void turnOnWindow()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
//setSize(400,200);
pack();
}
public static void main(String[] args) {
JPanelLayoutTest frame = new JPanelLayoutTest("JPanel Layout Test");
frame.turnOnWindow();
}
}
//Pardon the indentation; I wish this forum had support for the [code][/code] tag
SampleTableModel.java
import javax.swing.table.AbstractTableModel;
public class SampleTableModel extends AbstractTableModel {
//declaring the static arrays that will be the data for the table
private final String[] columnNames = {"Account", "Full Name", "Balance"};
private final int[] acctNumbers = {1000443749, 190238420, 928355};
private final String[] fullNames = {"Mike Warren", "Jack Smith", "Sarah Brown"};
private final double[] acctBalances = {193.38, 289.28, 21034.29};
public SampleTableModel()
{
// I do nothing in here; there is no reason to.
}
#Override
public int getColumnCount() { return columnNames.length; }
#Override
public int getRowCount() { return acctNumbers.length; }
#Override
public Object getValueAt(int row, int column) {
switch (column)
{
case 0:
return new Integer(acctNumbers[row]);
case 1:
return fullNames[row];
case 2:
return new Double(acctBalances[row]);
default:
return null; //there should be no way the code would ever reach here
}
}
#Override
public String getColumnName(int index) { return columnNames[index]; }
//Again, forgive my horrible indentation near the end here...
}
Instead of:
private JPanel setupPanel()
{
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
//making the panel have two columns and one row
JPanel panel = new JPanel(gridBag);
//add someTable to top
someTable = new JTable(new SampleTableModel());
/*JPanel somePanel = new JPanel();
somePanel.add(new JScrollPane(someTable));*/
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridheight = 1;
constraints.gridwidth = 1;
gridBag.setConstraints(new JScrollPane(someTable), constraints);
add(new JScrollPane(someTable));
//add tabbedPane to bottom
tabbedPane = new JTabbedPane();
tabbedPane.addTab("some component", new JLabel("some text"));
/*JPanel someOtherPanel = new JPanel();
someOtherPanel.add(tabbedPane);*/
constraints.gridy = 1;
gridBag.setConstraints(tabbedPane, constraints);
add(tabbedPane);
//add(tabbedPane);
return panel;
}
I think you will have better luck building your panel as an extention to the JPanel:
EDIT: Forgot to mention that this code is very reusable and allows to to pass in other objects into the JPanel...save you a ton of work as it allows you to overload constructors for different scenarios.
//You can call new objects such as:
new MyPanel(data, otherComponent);
public class MyPanel extends JPanel{
String data;
public MyPanel(String someData, SomeOtherClass aClass){
this.data = someData;
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
JPanel panel = new JPanel(gridBag);
//New addition
constraints.gridx = 0;
constraints.gridy = 0;
//add components to the JPanel with your grid (constraints)
add(new JScrollPane(someTable), constraints)
//New addition
constraints.gridx = 0;
constraints.gridy = 1;
//add components to the JPanel with your grid (constraints)
add(tabbedPane , constraints);
}
public String getData(){
return this.data;
}
}
This follows the MVC pattern (which i recommend looking into if you plan on designing more swing). I know it really helped me!
Your Problem
When using a GridBagLayout (and many other layouts), you need to pass the constraints you wish to use for a particular component, otherwise the layout manager will use its default values.
For example, you are doing...
gridBag.setConstraints(new JScrollPane(someTable), constraints);
add(new JScrollPane(someTable));
But the component you are adding is not the component your applied the constraints to. Instead, do something more like...
add(new JScrollPane(someTable), constraints);
A (possible) better solution
Break your UI down into sections. Each section has its own unique requirements (I see three sections).
I see a GridLayout as the base layout, onto which you want to add three additional panels, which represent three sections of your UI.
This commonly known as compound layouts as you building a series of layouts to produce your final result

JPanel disappearing from window

The SSCCE below is a class that extends JPanel. The JPanel is the basic outline of a calendar (I've stripped it way down for simplicity's sake), and it consists of JButton components, a JLabel, and a JTable. When I add this frame to a window (i.e. JDialog), it appears as normal. However, when I add another component with it, it disappears. Why is this happening, and how can I make this not happen?
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class CalendarPanel extends JPanel {
private static JDialog dialog = new JDialog();
public static void main(String[] args) {
setDialogProperties();
addComponentsToDialog();
dialog.setVisible(true);
}
private static void setDialogProperties() {
dialog.setModal(true);
dialog.setResizable(false);
dialog.setSize(new Dimension(330, 400));
dialog.setDefaultCloseOperation(2);
dialog.setLocationRelativeTo(null);
}
private static void addComponentsToDialog() {
CalendarPanel calendar = new CalendarPanel();
JPanel panel = new JPanel();
panel.add(calendar);
dialog.add(panel);
//dialog.add(new JLabel("Hello"));
}
private static final long serialVersionUID = 1L;
private JLabel lblMonth;
private JButton btnPrev, btnNext;
private JTable tblCalendar;
private DefaultTableModel mtblCalendar;
private JScrollPane stblCalendar;
private static GridBagLayout gridBag = new GridBagLayout();
private GridBagConstraints constraints = new GridBagConstraints();
public CalendarPanel() {
super(gridBag);
createControls();
addControlsToPanel();
addHeaders();
setTableProperties();
}
private void createControls() {
lblMonth = new JLabel("January");
btnPrev = new JButton("<");
btnNext = new JButton(">");
mtblCalendar = new DefaultTableModel() {
public boolean isCellEditable(int rowIndex, int mColIndex) {
return false;
}
};
tblCalendar = new JTable(mtblCalendar);
stblCalendar = new JScrollPane(tblCalendar);
stblCalendar.setPreferredSize(new Dimension(300, 247));
}
private void addControlsToPanel() {
GridBagLayout topGridBag = new GridBagLayout();
JPanel topPanel = new JPanel(topGridBag);
JPanel labelPanel = new JPanel();
labelPanel.add(lblMonth);
labelPanel.setPreferredSize(new Dimension(180, 20));
constraints.gridx = 1;
topGridBag.setConstraints(labelPanel, constraints);
constraints.gridx = 2;
topGridBag.setConstraints(btnNext, constraints);
topPanel.add(btnPrev);
topPanel.add(labelPanel);
topPanel.add(btnNext);
gridBag.setConstraints(topPanel, constraints);
constraints.gridy = 1;
gridBag.setConstraints(stblCalendar, constraints);
this.add(topPanel);
this.add(stblCalendar);
}
private void addHeaders() {
String[] headers = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
for (int i = 0; i < 7; i++) {
mtblCalendar.addColumn(headers[i]);
}
}
private void setTableProperties() {
tblCalendar.getTableHeader().setReorderingAllowed(false);
tblCalendar.setRowHeight(38);
mtblCalendar.setColumnCount(7);
mtblCalendar.setRowCount(6);
}
}
JDialogs and all top-level windows use BorderLayout by default. When you add a component to it (actually its contentPane) without specifying the position, you add it to the BorderLayout.CENTER position by default. You are covering up the previously added component whenever you add a new one. You will want to learn about the layouts available for your use and then use them to their best advantage.
e.g.,
dialog.add(panel);
dialog.add(new JLabel("Hello", SwingConstants.CENTER), BorderLayout.SOUTH);
}
Next you'll want to avoid setting the sizes of anything and to be sure to pack() your top level windows that allow this.

jscrollpane to scrolling a panel

i have to writing an applet, in left side i must use an panel to contain a list of vehicles that can be a list of buttons,what is the problem, number of the vehicles are not given !!!
so, i need to scrolling panel when number of vehicles is too much,
i do this for jframe, but it didn't work correct with panel, please help me with an example
the code i use to scrolling panel is :
public class VehicleList extends JPanel {
private ArrayList<VehicleReport> vehicles;
private ArrayList<JButton> v_buttons = new ArrayList<JButton>();
public void showList(ArrayList<Vehicles> vehicles)
{
this.vehicles = vehicles;
//...
add(getScrollpane());
setSize(155,300);
}
public JScrollPane getScrollpane()
{
JPanel panel = new JPanel();
panel.setPreferredSize(new DimensionUIResource(150, 300));
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints constraint = new GridBagConstraints();
panel.setLayout(gridbag);
constraint.fill = GridBagConstraints.HORIZONTAL;
JLabel title = new JLabel("Vehiles list");
constraint.gridwidth = 2;
constraint.gridx = 0;
constraint.gridy = 0;
constraint.ipady = 230;
gridbag.setConstraints(title, constraint);
panel.add(title);
// end of set title
constraint.gridwidth = 1;
int i=1;
for(JButton jb : v_buttons )
{
constraint.gridx =0;
constraint.gridy = i;
gridbag.setConstraints(jb, constraint);
panel.add(jb);
JLabel vehicle_lable = new JLabel("car" + i);
constraint.gridx = 1;
constraint.gridy = i;
gridbag.setConstraints(vehicle_lable, constraint);
panel.add(vehicle_lable);
i++;
}
JScrollPane jsp = new JScrollPane(panel);
return jsp;
}
}
in jaframe after add jscrollpane to jframe i place this
pack();
setSize(250, 250);
setLocation(100, 300);
and it work clearly!!!!
You also don't show us the layout manager of the VehicleList JPanel. In case you aren't setting it, it defaults to FlowLayout, unlike JFrame (which you mentioned this does work in), whose content pane defaults to BorderLayout. So maybe you just need to change the relevant code from:
//...
add(getScrollpane());
to
//...
setLayout(new BorderLayout());
add(getScrollpane(), BorderLayout.CENTER);
You need to set the scrolling policy on the horizontal and vertical:
public void setHorizontalScrollBarPolicy(int policy)
public void setVerticalScrollBarPolicy(int policy)
Using:
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
And:
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
JScrollPane.VERTICAL_SCROLLBAR_NEVER
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
So for example:
jscrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

Categories

Resources