I'm creating a chess game where the main panel is using BorderLayout, there is a panel at NORTH for buttons, a panel at CENTER for the board itself (set to GridLayout) and a sidebar at East.
I have made the JFrame unresizable and I'd like the chessboard to fit the panels in so that the East panel is a lot wider (maybe 200 pixels) and the board remains a square. I can't figure out how to change the sizes of these components individually.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class GameWindow extends JFrame {
private final JPanel playArea = new JPanel(new BorderLayout(3,3));
private final JButton[][] boardSquares = new JButton[8][8];
private final JPanel board;
private final JPanel sidebar = new JPanel();
private final JLabel message = new JLabel("Game by ...");
public GameWindow() {
playArea.setBorder(new EmptyBorder(5, 5, 5, 5));
JToolBar tools = new JToolBar();
tools.setFloatable(false);
playArea.add(tools, BorderLayout.PAGE_START);
tools.add(new JButton("New Game"));
tools.add(new JButton("Save"));
tools.add(new JButton("Restore"));
tools.addSeparator();
tools.add(new JButton("Resign"))
tools.addSeparator();
tools.add(message);
board = new JPanel(new GridLayout(0, 8));
board.setBorder(new LineBorder(Color.BLACK));
playArea.add(board, BorderLayout.CENTER);
playArea.add(sidebar, BorderLayout.EAST);
Insets buttonMargin = new Insets(0,0,0,0);
for (int i = 0; i < boardSquares.length; i++) {
for (int j = 0; j < boardSquares[i].length; j++) {
JButton square = new JButton();
square.setMargin(buttonMargin);
if ((i+j)%2 == 0) {
square.setBackground(Color.WHITE);
}
else {
square.setBackground(Color.BLACK);
}
board.setSize(600, 600);
board.add(boardSquares[j][i] = square);
}
}
}
public final JComponent getChessBoard() {
return board;
}
public final JComponent getGui() {
return playArea;
}
public static void main(String[] args) {
GameWindow window = new GameWindow();
JFrame frame = new JFrame("Checkers");
frame.setResizable(false);
frame.add(window.getGui());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setSize(800, 800);
frame.setVisible(true);
}
}
Firstly, since JDK 1.4, Java is encouraging the use of BorderLayout constants as BorderLayout.PAGE_START, BorderLayout.LINE_START, BorderLayout.CENTER, BorderLayout.LINE_END and BorderLayout.PAGE_END over the latter used by you.
Secondly you can simply override, the getPreferredSize() of the said JPanel, in order for it to give, some size that you feel like will work for your use case. Use of setPreferredSize() is restricted, since, not all LayoutManagers use to respect the Dimension specified by it.
Hence you could do something like:
private final JPanel sidebar = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
You can try this modified code:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class GameWindow extends JFrame {
private final JPanel playArea = new CustomPanel(710, 710);
private final JButton[][] boardSquares = new JButton[8][8];
private final JPanel board;
private final JPanel sidebar = new CustomPanel(100, 100);
private final JLabel message = new JLabel("Game by ...");
public GameWindow() {
playArea.setLayout(new BorderLayout(3,3));
playArea.setBorder(new EmptyBorder(5, 5, 5, 5));
JToolBar tools = new JToolBar();
tools.setFloatable(false);
playArea.add(tools, BorderLayout.PAGE_START);
tools.add(new JButton("New Game"));
tools.add(new JButton("Save"));
tools.add(new JButton("Restore"));
tools.addSeparator();
tools.add(new JButton("Resign"));
tools.addSeparator();
tools.add(message);
board = new CustomPanel(600, 600);
board.setLayout(new GridLayout(0, 8));
board.setBorder(new LineBorder(Color.BLACK));
playArea.add(board, BorderLayout.CENTER);
playArea.add(sidebar, BorderLayout.LINE_START);
Insets buttonMargin = new Insets(0,0,0,0);
for (int i = 0; i < boardSquares.length; i++) {
for (int j = 0; j < boardSquares[i].length; j++) {
JButton square = new JButton();
square.setOpaque(true);
square.setMargin(buttonMargin);
if ((i+j)%2 == 0) {
square.setBackground(Color.WHITE);
}
else {
square.setBackground(Color.BLACK);
}
board.add(boardSquares[j][i] = square);
}
}
}
private class CustomPanel extends JPanel {
private int width;
private int height;
public CustomPanel(int width, int height) {
this.width = width;
this.height = height;
setOpaque(true);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
}
public final JComponent getChessBoard() {
return board;
}
public final JComponent getGui() {
return playArea;
}
public static void main(String[] args) {
GameWindow window = new GameWindow();
JFrame frame = new JFrame("Checkers");
frame.setResizable(false);
frame.setContentPane(window.getGui());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
}
Moreover, before setting the background of JButton, it would be wise to call button.setOpaque(true) property.
It's not difficult to set the size of a JPanel. Just call setPreferredSize(). In your case to resize your East JPanel, call:
sidebar.setPreferredSize(new Dimension(200, 200));
After that, your LayoutManager will set the size of your JPanel to 200,200.
To your other JPanel, board: It's impossible to make a Component (like a JPanel) remaining a square. They always fit into rectangles. You would need to make your own subclass of JComponent and only paint everything in the square, and leave the rest transparent. Therefore, overwrite the method JComponent.paintComponent(Graphics).
Related
I'm new to using Java Swing and am looking to produce a GUI that resembles something like this:
I am pretty close but having an issue where a JLabel pushes up on the grid design like so:
How can I avoid this happening? I place the grid into a GridBagLayout panel and the JLabel into another GridBag panel(plan on putting a JToolbar here too), then add them to the main frame.
GridBagLayout tileLayout = new GridBagLayout();
GridBagConstraints tileLayoutConstraints = new GridBagConstraints();
JPanel tilePanel = new JPanel(tileLayout);
JPanel selectionPanel = new JPanel(tileLayout);
TileButton[][] tileAccessMatrix = new TileButton[4][4];
public BoardUILayer() {
setSize(1920, 1080);
buildBoardTiles();
buildResourcePrompt();
add(selectionPanel, BorderLayout.SOUTH);
add(tilePanel, BorderLayout.CENTER);
}
private void buildBoardTiles() {
for (int r = 0; r < tileAccessMatrix.length; r++) {
for (int c = 0; c < tileAccessMatrix[r].length; c++) {
TileButton temp = new TileButton(r, c);
tileAccessMatrix[r][c] = temp;
tileLayoutConstraints.ipadx = 115;
tileLayoutConstraints.ipady = 115;
tileLayoutConstraints.gridx = r;
tileLayoutConstraints.gridy = c;
temp.addActionListener(temp);
tilePanel.add(temp, tileLayoutConstraints);
}
}
}
public void buildResourcePrompt() {
final JLabel resourceTextLabel = new JLabel("What resource would you like?");
tileLayoutConstraints.ipadx = 0;
tileLayoutConstraints.ipady = 400;
tileLayoutConstraints.gridx = 50;
tileLayoutConstraints.gridy = 50;
selectionPanel.add(resourceTextLabel, tileLayoutConstraints);
}
I created a GUI based on your drawing. This was one of the most complex GUI's I have ever created in Swing. The challenge was keeping the JButton sizes constant.
Maybe a MigLayout would work better for you.
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Netbeans section.
I created 11 inner JPanels to construct this GUI.
JFrame
main JPanel
inner JPanel
turnButton JPanel
turn JPanel
buttonGrid JPanel
resource JPanel
resourceLabel JPanel
resourceButton JPanel
manual JPanel
outerEastButton JPanel
eastButton JPanel
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class RandomGameView implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new RandomGameView());
}
#Override
public void run() {
JFrame frame = new JFrame("Random Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.add(createManualPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
JPanel upperPanel = createTurnButtonPanel();
JPanel lowerPanel = createResourcePanel();
JPanel innerPanel = createUpperPanel(upperPanel, lowerPanel);
panel.add(innerPanel, BorderLayout.NORTH);
panel.add(lowerPanel, BorderLayout.SOUTH);
return panel;
}
private JPanel createUpperPanel(JPanel upperPanel, JPanel lowerPanel) {
Dimension upperSize = upperPanel.getPreferredSize();
Dimension lowerSize = lowerPanel.getPreferredSize();
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
int difference = lowerSize.width - upperSize.width;
int left = difference / 2;
int right = difference - left;
panel.setBorder(BorderFactory.createEmptyBorder(0, left, 0, right));
panel.add(upperPanel);
return panel;
}
private JPanel createTurnButtonPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(createTurnPanel(), BorderLayout.NORTH);
panel.add(createButtonGrid(), BorderLayout.SOUTH);
return panel;
}
private JPanel createTurnPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
Font font = panel.getFont().deriveFont(Font.BOLD, 36f);
JLabel playerLabel = new JLabel("Player's Turn");
playerLabel.setFont(font);
panel.add(playerLabel);
return panel;
}
private JPanel createButtonGrid() {
JPanel panel = new JPanel(new GridLayout(0, 4, 2, 2));
panel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
JButton[] buttonArray = new JButton[16];
Dimension buttonSize = new Dimension(100, 100);
for (int index = 0; index < buttonArray.length; index++) {
buttonArray[index] = new JButton("Empty");
buttonArray[index].setPreferredSize(buttonSize);
panel.add(buttonArray[index]);
}
return panel;
}
private JPanel createResourcePanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(createResourceLabelPanel(), BorderLayout.NORTH);
panel.add(createResourceButtonPanel(), BorderLayout.CENTER);
return panel;
}
private JPanel createResourceLabelPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
Font font = panel.getFont().deriveFont(Font.BOLD, 36f);
JLabel label = new JLabel("Select a Resource");
label.setFont(font);
panel.add(label);
return panel;
}
private JPanel createResourceButtonPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 30, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton[] resourceButton = new JButton[5];
Dimension buttonSize = new Dimension(100, 100);
for (int index = 0; index < resourceButton.length; index++) {
resourceButton[index] = new JButton("Empty");
resourceButton[index].setPreferredSize(buttonSize);
panel.add(resourceButton[index]);
}
return panel;
}
private JPanel createManualPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(10, 20, 300, 20));
Font font = panel.getFont().deriveFont(Font.BOLD, 36f);
JLabel label = new JLabel("Manual");
label.setHorizontalAlignment(JLabel.CENTER);
label.setFont(font);
panel.add(label, BorderLayout.NORTH);
JTextArea textArea = new JTextArea(5, 20);
panel.add(textArea, BorderLayout.CENTER);
JPanel eastButtonPanel = createEastButtonPanel();
JPanel innerPanel = createOuterEastButtonPanel(textArea, eastButtonPanel);
panel.add(innerPanel, BorderLayout.SOUTH);
return panel;
}
private JPanel createOuterEastButtonPanel(JTextArea textArea,
JPanel eastButtonPanel) {
Dimension eastButtonPanelSize = eastButtonPanel.getPreferredSize();
Dimension textAreaSize = textArea.getPreferredSize();
int difference = textAreaSize.width = eastButtonPanelSize.width;
int left = difference / 2;
int right = difference - left;
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
panel.setBorder(BorderFactory.createEmptyBorder(0, left, 0, right));
panel.add(eastButtonPanel);
return panel;
}
private JPanel createEastButtonPanel() {
JPanel panel = new JPanel(new GridLayout(0, 2, 2, 2));
panel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
JButton[] resourceButton = new JButton[4];
Dimension buttonSize = new Dimension(50, 50);
for (int index = 0; index < resourceButton.length; index++) {
resourceButton[index] = new JButton();
resourceButton[index].setPreferredSize(buttonSize);
panel.add(resourceButton[index]);
}
return panel;
}
}
You can do it with MigLayout and multiple JPanel.
MigLayout is very easy to use.
Firstly, create a JPanel and add your components to that JPanel.
Secondly, create another JPanel and add your other components to that JPanel.
MigLayout has rows and columns.
new MigLayout("","[][][]"/*for ex: 3 columns*/,"[][]" /*for ex 2 rows*/)
this.add(aComponent, "cell 2 1" /*for ex: that component added to third column and second row.*/);
For more information: http://www.miglayout.com/whitepaper.html
I know this problem has probably already been solved before but I don't really know how to describe the problem well, so I have a hard time finding it.
The problem I have is that I have a canvas that is attached to a panel and that panel is attached to a main panel and that to the frame. When I run the code the canvas does nothing. However if I dont add the button panel it works.
this is my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ColorFrame extends JFrame {
private static final int FRAMEWIDTH = 400;
private static final int FRAMEHEIGHT = 400;
private int aORec = 4;
private Canvas canvas;
private JPanel mainPanel;
private JPanel panel;
private JPanel buttonPanel;
private JButton lessButton;
private JButton moreButton;
public ColorFrame() {
mainPanel = new JPanel();
panel = new JPanel();
canvas = new painter();
panel.add(canvas);
mainPanel.add(panel, BorderLayout.CENTER);
createComponents();
add(mainPanel);
setSize(FRAMEWIDTH,FRAMEHEIGHT);
setDefaultCloseOperation(3);
}
private void createComponents() {
buttonPanel = new JPanel();
lessButton = new JButton("Less");
moreButton = new JButton("More");
ActionListener bL = new ButtonListener();
lessButton.addActionListener(bL);
moreButton.addActionListener(bL);
buttonPanel.add(moreButton);
buttonPanel.add(lessButton);
mainPanel.add(buttonPanel, BorderLayout.NORTH);
}
class painter extends Canvas {
#Override
public void paint(Graphics g) {
for (int i = 0; i < aORec; i++) {
int tempWidth = (int)(Math.random() * (FRAMEWIDTH-0));
int tempHeight = (int)(Math.random() * (FRAMEHEIGHT -0));
g.drawRect(tempWidth,tempHeight,20,20);
}
}
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == moreButton) {
aORec =+ aORec;
canvas.repaint();
} else {
if (aORec != 1) {
aORec -= (aORec*0.5);
canvas.repaint();
} else {
System.out.println("There are not enough rectangles to be drawn.");
}
}
}
}
}
Main panel is created by
mainPanel = new JPanel();
Components are being added to the main panel as
mainPanel.add(panel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.NORTH);
but no LayoutManager was set, so the default FlowLayout is used, not BorderLayout. Create the panel by
mainPanel = new JPanel(new BorderLayout());
or add the statement
mainPanel.setLayout(new BorderLayout());
This is also valid for panel (otherwise it will not be resized, that is, stay with size zero)
(BorderLayout is the default for JFrame(
The problem: I have no control on implementing more into the histogram package, so I create an array of buttons and overlay them on top of the histogram using JLayeredPane. However, I cannot get both the histogram plot and the buttons panels to scale when the JFrame is enlarged or contracted.
The JLayedPane is composed of 2 JPanels, see MWE.
To repeat the issue, just run program and extend JFrame.
I have read the following on SO posts; jlayeredpane-with-gridlayout, jlayeredpane-with-a-layoutmanager, jlayeredpane-not-resizing-with-jframe, resize-jframe-to-jpanels-inside-jlayeredpane, automatic-content-resizing-of-jlayeredpane,
as well as the Oracle page on JLayeredPane which has some examples
As useful as these links were, I still cannot get both JPanels to extend/contract with the JFrame.
Question: Is there a way to get both JPanels in the JLayeredPane to rescale without implementing a new layout? If new layout is needed, would someone please provide a MWE on how to do such?
public class FrameDemo extends JPanel {
private JLayeredPane layeredPane;
private final int width = 800;
private final int height = 800;
private String[] layerStrings = { "Yellow (0)", "Magenta (1)", "Cyan (2)", "Red (3)", "Green (4)", "Blue (5)" };
private Color[] layerColors = { Color.yellow, Color.magenta, Color.cyan, Color.red, Color.green, Color.blue };
public FrameDemo() {
setLayout(new BorderLayout());
init();
addPanels();
add(layeredPane, BorderLayout.CENTER);
}
private void init() {
this.layeredPane = new JLayeredPane();
this.layeredPane.setPreferredSize(new Dimension(width, height));
this.layeredPane.setBorder(BorderFactory.createTitledBorder("Histogram should go here"));
this.layeredPane.setLayout(new BorderLayout());
}
private void addPanels() {
this.layeredPane.add(createHistogramPanel(), BorderLayout.CENTER, new Integer(1));
this.layeredPane.add(createButtonPanel(), BorderLayout.CENTER, new Integer(0));
this.layeredPane.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
Dimension size = layeredPane.getSize(); // get size
createHistogramPanel().setSize(size); // push size through
createButtonPanel().setSize(size); // push size trhough
// otherChildOfLayers.setSize(size); // push size trhough
layeredPane.revalidate(); // revalidate to see updates
layeredPane.repaint(); // "Always invoke repaint after
// revalidate"
}
});
}
private JPanel createHistogramPanel() {
JPanel histpanel = new JPanel();
histpanel.setLayout(new GridLayout(2, 3));
for (int i = 0; i < layerStrings.length; i++) {
JLabel label = createColoredLabel(layerStrings[i], layerColors[i]);
histpanel.add(label);
}
histpanel.setOpaque(false);
histpanel.setBounds(10, 10, width, height);
return histpanel;
}
private JLabel createColoredLabel(String text, Color color) {
JLabel label = new JLabel("");
label.setVerticalAlignment(JLabel.TOP);
label.setHorizontalAlignment(JLabel.CENTER);
label.setOpaque(true);
label.setBackground(color);
label.setForeground(Color.black);
label.setBorder(BorderFactory.createLineBorder(Color.black));
label.setPreferredSize(new Dimension(120, 120));
return label;
}
private JPanel createButtonPanel() {
ButtonGroup buttons = new ButtonGroup();
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(2, 3));
for (int i = 0; i < 6; i++) {
final int placer = i + 1;
JButton freshButton = new JButton();
freshButton.addActionListener(e -> {
System.out.println("Button " + placer + " clicked");
});
freshButton.setText("Button " + (i + 1));
freshButton.setOpaque(true);
freshButton.setContentAreaFilled(false);
freshButton.setBorderPainted(false);
freshButton.setBounds(new Rectangle(132, 75 + (i * 20), 40, 20));
buttonPanel.add(freshButton, null);
buttons.add(freshButton);
}
buttonPanel.setOpaque(false);
buttonPanel.setBounds(10, 10, width, height);
return buttonPanel;
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new FrameDemo();
newContentPane.setOpaque(true); // content panes must be opaque
frame.setContentPane(newContentPane);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Your code won't work because in componentResized you're creating new panels and applying the size to them. You need to resize the existing panels added to the layered pane. This could be done by assigning histogramPanel and buttonPanel as instance variables.
I have the GUI displaying properly for the most part, except for one thing. The TitledBorder("Numeric Type") does not display the entire title for the right JPanel. I believe it has something to do with the BorderLayout Manager. Instead of displaying "Numeric Type" within the border, just "Numeric..." displays. Any help will be greatly appreciated.
public class P3GUI extends JFrame {
private JLabel originalList;
private JTextField originalSort;
private JLabel sortedList;
private JTextField newSort;
private JPanel panel;
private JButton performSort;
private JRadioButton ascending;
private JRadioButton descending;
private ButtonGroup sort;
private JRadioButton integer;
private JRadioButton fraction;
private ButtonGroup numType;
private JPanel inputPanel, outputPanel, calculatePanel, radioPanel;
private JPanel left, right;
public P3GUI () {
super("Binary Search Tree Sort");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
originalList = new JLabel("Original List");
originalSort = new JTextField(20);
inputPanel = new JPanel();
inputPanel.add(originalList);
inputPanel.add(originalSort);
sortedList = new JLabel("Sorted List");
newSort = new JTextField(20);
newSort.setEditable(false);
outputPanel = new JPanel();
outputPanel.add(sortedList);
outputPanel.add(newSort);
panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(inputPanel);
panel.add(outputPanel);
add(panel, BorderLayout.NORTH);
performSort = new JButton("Perform Sort");
calculatePanel = new JPanel();
calculatePanel.add(performSort);
add(calculatePanel, BorderLayout.CENTER);
ascending = new JRadioButton("Ascending");
descending = new JRadioButton("Descending");
sort = new ButtonGroup();
sort.add(ascending);
sort.add(descending);
integer = new JRadioButton("Integer");
fraction = new JRadioButton("Fraction");
numType = new ButtonGroup();
numType.add(integer);
numType.add(fraction);
radioPanel = new JPanel();
radioPanel.setLayout(new FlowLayout());
left = new JPanel();
left.setLayout(new GridLayout(2,1));
left.setBorder(BorderFactory.createTitledBorder("Sort Order"));
left.add(ascending);
left.add(descending);
right = new JPanel();
right.setLayout(new GridLayout(2,1));
right.setBorder(BorderFactory.createTitledBorder("Numeric Type"));
right.add(integer);
right.add(fraction);
radioPanel.add(left);
radioPanel.add(right);
add(radioPanel, BorderLayout.SOUTH);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new P3GUI().setVisible(true);
}
});
}
}
The problem is that the right JPanel is too small to display the entire title, and so it gets truncated. I'd suggest placing the bottom two JPanels into another that uses GridLayout, and then place them in such a way that they expand to fit the bottom of your GUI. When spread out, the title has a much greater chance of being fully displayed (but not a guarantee, mind you!).
For example, if you make the main GUI use a BorderLayout, and add this GridLayout using JPanel into the BorderLayout.CENTER position, it will fill it completely. Then the top components, the TextFields and JButton can be added to another JPanel, say one that uses a GridBagLayout, and add that to the main JPanel's BorderLayout.PAGE_START position.
For example, the following code produces this GUI:
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class P3GUI2 extends JPanel {
private static final int COLS = 20;
private JTextField originalSort = new JTextField(COLS);
private JTextField newSort = new JTextField(COLS);
private JButton performSort = new JButton("Perform Sort");
private JRadioButton ascending = new JRadioButton("Ascending");
private JRadioButton descending = new JRadioButton("Descending");
private ButtonGroup sort = new ButtonGroup();
private JRadioButton integer = new JRadioButton("Integer");
private JRadioButton fraction = new JRadioButton("Fraction");
private ButtonGroup numType = new ButtonGroup();
public P3GUI2() {
JPanel topPanel = new JPanel(new GridBagLayout());
topPanel.add(new JLabel("Original List:"), createGbc(0, 0));
topPanel.add(originalSort, createGbc(1, 0));
topPanel.add(new JLabel("Sorted List:"), createGbc(0, 1));
topPanel.add(newSort, createGbc(1, 1));
performSort.setMnemonic(KeyEvent.VK_P);
JPanel btnPanel = new JPanel();
btnPanel.add(performSort);
JPanel sortOrderPanel = createTitlePanel("Sort Order");
JPanel numericPanel = createTitlePanel("Numeric Type");
sortOrderPanel.add(ascending);
sortOrderPanel.add(descending);
sort.add(ascending);
sort.add(descending);
numericPanel.add(integer);
numericPanel.add(fraction);
numType.add(integer);
numType.add(fraction);
JPanel radioPanels = new JPanel(new GridLayout(1, 0, 3, 3));
radioPanels.add(sortOrderPanel);
radioPanels.add(numericPanel);
setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
setLayout(new BorderLayout(3, 3));
add(topPanel, BorderLayout.PAGE_START);
add(btnPanel, BorderLayout.CENTER);
add(radioPanels, BorderLayout.PAGE_END);
}
private JPanel createTitlePanel(String title) {
JPanel panel = new JPanel(new GridLayout(0, 1, 3, 3));
panel.setBorder(BorderFactory.createTitledBorder(title));
return panel;
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = x == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
gbc.insets = new Insets(3, 3, 3, 3);
gbc.weightx = 1.0;
gbc.weighty = 1.0;
return gbc;
}
private static void createAndShowGui() {
P3GUI2 mainPanel = new P3GUI2();
JFrame frame = new JFrame("Binary Search Tree Sort");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Or you could place the above btnPanel into the main one BorderLayout.CENTER and then place the radioPanels into the main one BorderLayout.PAGE_END. This will display a GUI of the same appearance but it will expand differently if re-sized.
The preferred size of the panel (as determined by the layout manager) does not consider the size of the text in the TitledBorder so the title can get truncated.
Here is a custom JPanel that can be used with a TitleBorder. The getPreferredSize() method has been customized to use the maximum width of:
the default getPreferredSize() calculation
the width of the text in the TitledBorder
Here is a simple example:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class TitledBorderPanel extends JPanel
{
/**
** The preferred width on the panel must consider the width of the text
** used on the TitledBorder
*/
#Override
public Dimension getPreferredSize()
{
Dimension preferredSize = super.getPreferredSize();
Border border = getBorder();
int borderWidth = 0;
if (border instanceof TitledBorder)
{
Insets insets = getInsets();
TitledBorder titledBorder = (TitledBorder)border;
borderWidth = titledBorder.getMinimumSize(this).width + insets.left + insets.right;
}
int preferredWidth = Math.max(preferredSize.width, borderWidth);
return new Dimension(preferredWidth, preferredSize.height);
}
private static void createAndShowGUI()
{
JPanel panel = new TitledBorderPanel();
panel.setBorder( BorderFactory.createTitledBorder("File Options Command List:") );
panel.setLayout( new BoxLayout(panel, BoxLayout.Y_AXIS) );
panel.add( new JLabel("Open") );
panel.add( new JLabel("Close") );
// panel.add( new JLabel("A really wierd file option longer than border title") );
JFrame frame = new JFrame("TitledBorderPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
I want to add multiple jpanels to jpanel.So i added a root panel to jscrollpane.and then added all individual jpanels to this root panel.I made jscrollpane's scrolling policy as needed.i.e HORIZONTAL_SCROLLBAR_AS_NEEDED,VERTICAL_SCROLLBAR_AS_NEEDED.
But the problem is all individual panels are not shown inside root panel.
Code:
JScrollPane scPanel=new JScrollPane();
JPanel rootPanel=new JPanel();
rootPanel.setLayout(new FlowLayout());
JPanel indPanel = new JPanel();
rootPanel.add(indPanel);
JPanel indPanel2 = new JPanel();
rootPanel.add(indPanel2);
//.....like this added indPanals to rootPanel.
scPanel.setViewPortView(rootPanel);
//scPanel.setHorizontalScrollPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);
And one more thing is, as i scroll the scrollbar the panels are going out of jscrollpane area.
I am not able to see all individual panels,
Please suggest me.
Edit: code snippet from double post:
MosaicFilesStatusBean mosaicFilesStatusBean = new MosaicFilesStatusBean();
DefaultTableModel tableModel = null;
tableModel = mosaicFilesStatusBean.getFilesStatusBetweenDates(startDate, endDate);
if (tableModel != null) {
rootPanel.removeAll();
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
for (int tempRow = 0; tempRow < tableModel.getRowCount(); tempRow++) {
int fileIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 0).toString());
String dateFromTemp = tableModel.getValueAt(tempRow, 3).toString();
String dateToTemp = tableModel.getValueAt(tempRow, 4).toString();
int processIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 5).toString());
int statusIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 6).toString());
String operatingDateTemp = tableModel.getValueAt(tempRow, 7).toString();
MosaicPanel tempPanel =
new MosaicPanel(fileIdTemp, dateFromTemp, dateToTemp, processIdTemp, statusIdTemp, operatingDateTemp);
rootPanel.add(tempPanel);
}
rootPanel.revalidate();
}
The main reason, why you couldn't see your JPanel is that you are using FlowLayout as the LayoutManager for the rootPanel. And since your JPanel added to this rootPanel has nothing inside it, hence it will take it's size as 0, 0, for width and height respectively. Though using GridLayout such situation shouldn't come. Have a look at this code example attached :
import java.awt.*;
import javax.swing.*;
public class PanelAddition
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Panel Addition Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridLayout(0, 1));
JScrollPane scroller = new JScrollPane();
CustomPanel panel = new CustomPanel(1);
contentPane.add(panel);
scroller.setViewportView(contentPane);
frame.getContentPane().add(scroller, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
for (int i = 2; i < 20; i++)
{
CustomPanel pane = new CustomPanel(i);
contentPane.add(pane);
contentPane.revalidate();
contentPane.repaint();
}
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PanelAddition().createAndDisplayGUI();
}
});
}
}
class CustomPanel extends JPanel
{
public CustomPanel(int num)
{
JLabel label = new JLabel("" + num);
add(label);
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(200, 50));
}
}
Don't use FlowLayout for the rootPanel. Instead consider using BoxLayout:
JPanel rootPanel=new JPanel();
// if you want to stack JPanels vertically:
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
Edit 1
Here's an SSCCE that's loosely based on your latest code posted:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class PanelsEg extends JPanel {
private static final int MAX_ROW_COUNT = 100;
private Random random = new Random();
private JPanel rootPanel = new JPanel();
public PanelsEg() {
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(rootPanel);
scrollPane.setPreferredSize(new Dimension(400, 400)); // sorry kleopatra
add(scrollPane);
add(new JButton(new AbstractAction("Foo") {
#Override
public void actionPerformed(ActionEvent arg0) {
foo();
}
}));
}
public void foo() {
rootPanel.removeAll();
// rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS)); // only need to set layout once
int rowCount = random.nextInt(MAX_ROW_COUNT);
for (int tempRow = 0; tempRow < rowCount ; tempRow++) {
int fileIdTemp = tempRow;
String data = "Data " + (tempRow + 1);
MosaicPanel tempPanel =
new MosaicPanel(fileIdTemp, data);
rootPanel.add(tempPanel);
}
rootPanel.revalidate();
rootPanel.repaint(); // don't forget to repaint if removing
}
private class MosaicPanel extends JPanel {
public MosaicPanel(int fileIdTemp, String data) {
add(new JLabel(data));
}
}
private static void createAndShowGui() {
PanelsEg mainPanel = new PanelsEg();
JFrame frame = new JFrame("PanelsEg");
frame.setDefaultCloseOperation(JFrame.EXIT_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();
}
});
}
}
This SSCCE works, in that it easily shows removing and adding JPanels to another JPanel that is held by a JScrollPane. If you're still having a problem, you should modify this SSCCE so that it shows your problem.