Stack swing elements from top to bottom - java

Consider the following figure:
I need to develop a swing GUI the looks like this. I simply named them jLabel's but there a few images and jLabels in it. The default awt background visible is a JPanel and each red background visible is a serperate JPanel. Now I need them to get stacked as shown above. I tried a number of LayoutManagers and still it doesn't work.
The important point here is that the number of red colored divs are not constant. If there is only one red colored div then it must be displayed at the top, not at the center. As far as i know GridBagLayout should work, but it centers the single red colored jpanel available. All the layout managers are centering them but not stacking them from top to bottom.

Even with anchor set to NORTH then the panels will still be centered. You could work around it by adding a dummy panel to fill the remaining space. Personally I'd stay well away from GridBagLayout though.
JFrame frame = new JFrame();
JPanel content = new JPanel();
content.setBorder(BorderFactory.createLineBorder(Color.red));
frame.setContentPane(content);
frame.getContentPane().setLayout(new GridBagLayout());
frame.setSize(400, 300);
for (int i = 0; i < 3; i++) {
JPanel panel = new JPanel();
panel.add(new JLabel("label1"));
panel.add(new JLabel("label2"));
panel.add(new JLabel("label3"));
panel.setBorder(BorderFactory.createLineBorder(Color.red));
GridBagConstraints con = new GridBagConstraints();
con.gridy = i;
con.gridx = 0;
con.anchor = GridBagConstraints.NORTHWEST;
con.ipady = 10;
frame.getContentPane().add(panel, con);
}
// dummy panel to use up the space (force others to top)
frame.getContentPane().add(
new JPanel(),
new GridBagConstraints(0, 3, 1, 1, 1, 1,
GridBagConstraints.NORTHWEST,
GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 0), 0,
0));
frame.setVisible(true);
GroupLayout example (my favourite layout manager).
JFrame frame = new JFrame();
JPanel content = new JPanel();
frame.setContentPane(content);
frame.getContentPane().setLayout(
new BoxLayout(content, BoxLayout.Y_AXIS));
frame.setSize(400, 300);
GroupLayout gLayout = new GroupLayout(content);
content.setLayout(gLayout);
ParallelGroup hGroup = gLayout.createParallelGroup();
gLayout.setHorizontalGroup(hGroup);
SequentialGroup vGroup = gLayout.createSequentialGroup();
gLayout.setVerticalGroup(vGroup);
for (int i = 0; i < 3; i++) {
JPanel panel = new JPanel();
panel.add(new JLabel("label1"));
panel.add(new JLabel("label2"));
panel.add(new JLabel("label3"));
panel.setBorder(BorderFactory.createLineBorder(Color.red));
hGroup.addComponent(panel);
vGroup.addComponent(panel, GroupLayout.PREFERRED_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
vGroup.addGap(10);
}
frame.setVisible(true);

you can use Vertical BoxLayout, for example:
http://www.java-tips.org/java-se-tips/javax.swing/how-to-use-swing-boxlayout.html

nobody tell us that all JComponents must be visible, for example
from code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class AddComponentsAtRuntime {
private JFrame f;
private JPanel panel;
private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack;
public AddComponentsAtRuntime() {
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel(new GridLayout(0, 1));
f.add(panel, "Center");
f.add(getCheckBoxPanel(), "South");
f.setLocation(200, 200);
f.pack();
f.setVisible(true);
}
private JPanel getCheckBoxPanel() {
checkValidate = new JCheckBox("validate");
checkValidate.setSelected(false);
checkReValidate = new JCheckBox("revalidate");
checkReValidate.setSelected(false);
checkRepaint = new JCheckBox("repaint");
checkRepaint.setSelected(false);
checkPack = new JCheckBox("pack");
checkPack.setSelected(false);
JButton addComp = new JButton("Add New One");
addComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel b = new JPanel(new GridLayout(0, 4));
b.setBackground(Color.red);
b.setBorder(new LineBorder(Color.black, 2));
//b.setPreferredSize(new Dimension(600, 20));
for (int i = 0; i < 4; i++) {
JLabel l = new JLabel("label" + i + 1);
b.add(l);
if (i == 2) {
l.setVisible(false);
}
}
panel.add(b);
makeChange();
System.out.println(" Components Count after Adds :" + panel.getComponentCount());
}
});
JButton removeComp = new JButton("Remove One");
removeComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int count = panel.getComponentCount();
if (count > 0) {
panel.remove(0);
}
makeChange();
System.out.println(" Components Count after Removes :" + panel.getComponentCount());
}
});
JPanel panel2 = new JPanel();
panel2.add(checkValidate);
panel2.add(checkReValidate);
panel2.add(checkRepaint);
panel2.add(checkPack);
checkPack.setSelected(true);
panel2.add(addComp);
panel2.add(removeComp);
return panel2;
}
private void makeChange() {
if (checkValidate.isSelected()) {
panel.validate();
}
if (checkReValidate.isSelected()) {
panel.revalidate();
}
if (checkRepaint.isSelected()) {
panel.repaint();
}
if (checkPack.isSelected()) {
f.pack();
}
}
public static void main(String[] args) {
AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime();
}
}

You should try the MigLayout it is simple yet powerful. Below I tell miglayout to grow elements, and fill all possible space, then after each element I tell it to go to a new line (wrap). You can find examples and tutorial on MigLayout page http://www.miglayout.com/:
import net.miginfocom.swing.MigLayout;
public class PanelLearning extends JPanel {
public PanelLearning() {
setLayout(new MigLayout("", "[grow, fill]", ""));
for (int i = 0; i < 3; i++) {
JPanel panel = new JPanel();
panel.add(new JLabel("label1"));
panel.add(new JLabel("label2"));
panel.add(new JLabel("label3"));
panel.setBorder(BorderFactory.createLineBorder(Color.red));
add(panel, "span, wrap");
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Login");
frame.setVisible(true);
frame.setContentPane(new PanelLearning());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
}

Make sure GridBagConstraints.anchor = GridBagConstraints.NORTH when you add components to the panel.

Related

How to avoid components pushing up/down on one another

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

How to get the TitledBorder's title to display properly in the GUI

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();
}
});
*/
}
}

Put 4 JLabel at corners of a JFrame

As the title said, I'm trying to put 4 different JLabels at each of the corners of a JFrame. I want them to stay there forever even if I try to resize the JFrame
I've tried using a layout manager but I just can't get it right.
ImageIcon icon;
JLabel labelNW = new JLabel();
JLabel labelNE = new JLabel();
JLabel labelSW = new JLabel();
JLabel labelSE = new JLabel();
URL buttonURL = InputOutputTest.class.getResource("images/square_dot.gif");
if(buttonURL != null){
icon = new ImageIcon(buttonURL);
labelNW.setIcon(icon);
labelNE.setIcon(icon);
labelSW.setIcon(icon);
labelSE.setIcon(icon);
}
window.add(labelNW, BorderLayout.NORTH);
//window.add(labelNE, BorderLayout.EAST);
//window.add(labelSW, BorderLayout.WEST);
window.add(labelSE, BorderLayout.SOUTH);
This code takes care of the north and south of the left side. I'm probably approaching this wrong though.
I also tried GridLayout (2,2) but they weren't at the corners and there's a huge gap on the right side.
You will want to nest JPanels each using its own layout. In fact you could do this by nesting JPanels that all use BorderLayout.
Going to check if GridBagLayout can do it in one shot.... hang on...
Yep GridBagLayout does it too:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class GridBagExample {
public static void main(String[] args) {
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(
0, 0, 0, 0), 0, 0);
mainPanel.add(new JLabel("Left Upper"), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.NORTHEAST;
mainPanel.add(new JLabel("Right Upper"), gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.SOUTHWEST;
mainPanel.add(new JLabel("Left Lower"), gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.SOUTHEAST;
mainPanel.add(new JLabel("Right Lower"), gbc);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}
Edit
Now for the BorderLayout example:
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class BorderLayoutExample {
public static void main(String[] args) {
JPanel northPanel = new JPanel(new BorderLayout());
northPanel.add(new JLabel("North East"), BorderLayout.EAST);
northPanel.add(new JLabel("North West"), BorderLayout.WEST);
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.add(new JLabel("South East"), BorderLayout.EAST);
southPanel.add(new JLabel("South West"), BorderLayout.WEST);
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(northPanel, BorderLayout.NORTH);
mainPanel.add(southPanel, BorderLayout.SOUTH);
JFrame frame = new JFrame("BorderLayout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
I find that only GroupLayout gives me the control I need for precisely laid out components. This should do the trick. You need to make sure the gap in between has a very large Maximum value (i.e. Short.MAX_VALUE), but you can set the minimum and preferred sizes to whatever you want.
public class LabelFrame extends JFrame {
public LabelFrame() {
JPanel contentPane = new JPanel();
JLabel labelNW = new JLabel();
JLabel labelNE = new JLabel();
JLabel labelSW = new JLabel();
JLabel labelSE = new JLabel();
URL buttonURL = InputOutputTest.class.getResource("images/square_dot.gif");
if(buttonURL != null){
icon = new ImageIcon(buttonURL);
labelNW.setIcon(icon);
labelNE.setIcon(icon);
labelSW.setIcon(icon);
labelSE.setIcon(icon);
}
GroupLayout layout = new GroupLayout(contentPane);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(Alignment.LEADING)
.addComponent(labelNW)
.addComponent(labelSW))
.addGap(20,50,Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(labelNE)
.addComponent(labelSE))
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(Alignment.LEADING)
.addComponent(labelNW)
.addComponent(labelNE))
.addGap(20,50,Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(labelSW)
.addComponent(labelSE))
);
contentPane.setLayout(layout);
setContentPane(contentPane);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
LabelFrame frame = new LabelFrame();
frame.setVisible(true);
}
});
}
}
I've tried using a layout manager..
Layout managers are wonderful at what they do, but are perhaps the wrong tool for this job. Consider using a custom border instead. Here is an example.

Unwanted line between labels and radio group in Java

In my project, I use Swing controls. I had used a label together with a button group, but there is an unwanted line. Please help. There is a label associated with each radio button group. The unwanted line is there.how to add the labels and corresponding radio button group to the same panel
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//import java.util.Arrays;
public class Online extends JFrame {
static JRadioButton[] choice = new JRadioButton[6];
JFrame jtfMainFrame, jtfMainFrame1;
public void createWindow() {
jtfMainFrame = new JFrame("Online Examination");
jtfMainFrame.setSize(800, 500);
jtfMainFrame.setLocation(200, 150);
jtfMainFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JPanel pa = new JPanel();
JPanel panlabels = new JPanel(new GridLayout(0, 1, 0, 60));
JPanel pancontrols = new JPanel(new GridLayout(0, 1, 0, 60));
JPanel panEast = new JPanel();
JPanel pan = new JPanel(new FlowLayout());
JLabel qLabel = new JLabel("Question.");
qLabel.setOpaque(true);
qLabel.setForeground(Color.blue);
qLabel.setBackground(Color.lightGray);
JLabel aLabel = new JLabel("Question.");
aLabel.setOpaque(true);
aLabel.setForeground(Color.blue);
aLabel.setBackground(Color.lightGray);
JLabel bLabel = new JLabel("a.");
bLabel.setOpaque(true);
bLabel.setForeground(Color.blue);
bLabel.setBackground(Color.lightGray);
JLabel cLabel = new JLabel("b.");
cLabel.setOpaque(true);
cLabel.setForeground(Color.blue);
cLabel.setBackground(Color.lightGray);
JLabel dLabel = new JLabel("c.");
dLabel.setOpaque(true);
dLabel.setForeground(Color.blue);
dLabel.setBackground(Color.lightGray);
JLabel eLabel = new JLabel("d.");
eLabel.setOpaque(true);
eLabel.setForeground(Color.blue);
eLabel.setBackground(Color.lightGray);
panlabels.add(aLabel, BorderLayout.WEST);
panlabels.add(bLabel, BorderLayout.CENTER);
panlabels.add(cLabel, BorderLayout.CENTER);
panlabels.add(dLabel, BorderLayout.CENTER);
panlabels.add(eLabel, BorderLayout.CENTER);
//panlabels.add(fLabel, BorderLayout.WEST);
//fLabel.setVisible(false);
JLabel ques = new JLabel("q");
ques.setBackground(Color.red);
choice[1] = new JRadioButton("a");
choice[1].setBackground(Color.red);
choice[2] = new JRadioButton("b");
choice[2].setBackground(Color.red);
choice[3] = new JRadioButton("c");
choice[3].setBackground(Color.red);
choice[4] = new JRadioButton("d");
choice[4].setBackground(Color.red);
ButtonGroup bGroup = new ButtonGroup();
pancontrols.add(ques, BorderLayout.WEST);
for (int i = 1; i < 5; i++) {
// pancontrols.add(aLabel,BorderLayout.WEST);
bGroup.add(choice[i]);
pancontrols.add(choice[i], BorderLayout.WEST);
}
choice[4].setVisible(true);
panEast.add("West", panlabels);
panEast.add("West", pancontrols);
pa.add("Center", panEast);
pa.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Select your answer"));
//getContentPane().add(label);
//to be deleted pa.add("South", pan);
pa.setBackground(Color.pink);
jtfMainFrame.add(pa);
jtfMainFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
jtfMainFrame.setVisible(true);
}
public static void main(String[] args) {
Online r = new Online();
r.createWindow();
}
}
First, your naming convention for the choice labels is off. qLabel="questions", aLabel="questions", bLabel="a", cLabel="b", etc. I would suggest you fix that to eliminate confusion and make your code more readable (ie only have one label that is a question).
Second, your use of panEast.add("West",panlabels); and the other two statements is generally not suggested. Read up on BorderLayout to find the more accepted method of doing this:
http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html
As for your problem, I have rewritten your code so things do line up, I will try to point out what I commented out to help:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//import java.util.Arrays;
public class Online extends JFrame {
static JRadioButton[] choice = new JRadioButton[6];
JFrame jtfMainFrame, jtfMainFrame1;
public void createWindow() {
jtfMainFrame = new JFrame("Online Examination");
jtfMainFrame.setSize(800, 500);
jtfMainFrame.setLocation(200, 150);
jtfMainFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JPanel pa = new JPanel();
//JPanel panlabels = new JPanel(new GridLayout(0, 1, 0, 60));
JPanel pancontrols = new JPanel(new GridLayout(0, 2, 0, 60));
JPanel panEast = new JPanel();
JPanel pan = new JPanel(new BorderLayout());
JLabel qLabel = new JLabel("Question.");
qLabel.setOpaque(true);
qLabel.setForeground(Color.blue);
qLabel.setBackground(Color.lightGray);
JLabel aLabel = new JLabel("Question.");
aLabel.setOpaque(true);
aLabel.setForeground(Color.blue);
aLabel.setBackground(Color.lightGray);
JLabel bLabel = new JLabel("a.");
bLabel.setOpaque(true);
bLabel.setForeground(Color.blue);
bLabel.setBackground(Color.lightGray);
JLabel cLabel = new JLabel("b.");
cLabel.setOpaque(true);
cLabel.setForeground(Color.blue);
cLabel.setBackground(Color.lightGray);
JLabel dLabel = new JLabel("c.");
dLabel.setOpaque(true);
dLabel.setForeground(Color.blue);
dLabel.setBackground(Color.lightGray);
JLabel eLabel = new JLabel("d.");
eLabel.setOpaque(true);
eLabel.setForeground(Color.blue);
eLabel.setBackground(Color.lightGray);
//panlabels.add(fLabel, BorderLayout.WEST);
//fLabel.setVisible(false);
JLabel ques = new JLabel("q");
ques.setBackground(Color.red);
choice[1] = new JRadioButton("a");
choice[1].setBackground(Color.red);
choice[2] = new JRadioButton("b");
choice[2].setBackground(Color.red);
choice[3] = new JRadioButton("c");
choice[3].setBackground(Color.red);
choice[4] = new JRadioButton("d");
choice[4].setBackground(Color.red);
ButtonGroup bGroup = new ButtonGroup();
//pancontrols.add(new JLabel(""));
pancontrols.add(ques, BorderLayout.WEST);
for (int i = 1; i < 5; i++) {
// pancontrols.add(aLabel,BorderLayout.WEST);
bGroup.add(choice[i]);
}
pancontrols.add(qLabel);
pancontrols.add(ques);
pancontrols.add(bLabel);
pancontrols.add(choice[1]);
pancontrols.add(cLabel);
pancontrols.add(choice[2]);
pancontrols.add(dLabel);
pancontrols.add(choice[3]);
pancontrols.add(eLabel);
pancontrols.add(choice[4]);
pancontrols.setSize(400,200);
choice[4].setVisible(true);
pa.add(pancontrols);
pa.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Select your answer"));
//getContentPane().add(label);
//to be deleted pa.add("South", pan);
pa.setBackground(Color.pink);
jtfMainFrame.add(pa);
jtfMainFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
jtfMainFrame.setVisible(true);
}
public static void main(String[] args) {
Online r = new Online();
r.createWindow();
}
}
Basically, I removed your unnecessary panels. the only panel you add stuff to now is the pancontrols panel. I changed it to new JPanel(new Gridlayout(0,2,0,60)). With the two column GridLayout you will always have things line up bound wise, due to GridLayout making everything the same size.
Lastly I pulled the adding of choices[] from the loop and did that along with the labels to make sure things line up. I removed all the panels being added except the pancontrols being added to pa, which I assume you want to add more question panels to pa in that case. That covers your question in particular, but there is quite a lot of stuff you should do (ie use choice[0] for example, eliminate unused labels and panels, etc.)

set size and position for button

There are two buttons
left = new JButton("prev");
right = new JButton("next");
I add them to jframe like this
mainframe.add(left,BorderLayout.WEST);
mainframe.add(right,BorderLayout.EAST);
But there have got height the same as mainframe's height. How to set my own width and height?
And how to set their position(not only in the NORTH,WEST,EAST,SOUTH)?.
How to set my own width and height
Don't do that, instead just constrain the size using the NORTH or SOUTH of a JPanel that itself is added to the EAST or WEST of the outer (parent) layout.
Much like this:
import java.awt.*;
import javax.swing.*;
class BorderGUI {
BorderGUI() {
JPanel gui = new JPanel(new BorderLayout(2,2));
JPanel westConstrain = new JPanel(new BorderLayout(2,2));
// LINE_START will be WEST for l-r languages, otherwise EAST
gui.add(westConstrain, BorderLayout.LINE_START);
JPanel westControls = new JPanel(new GridLayout(0,1,2,2));
for (int ii=1; ii<3; ii++) {
westControls.add( new JButton("" + ii) );
}
westConstrain.add(westControls, BorderLayout.PAGE_START);
JPanel eastConstrain = new JPanel(new BorderLayout(2,2));
gui.add(eastConstrain, BorderLayout.LINE_END);
JPanel eastControls = new JPanel(new GridLayout(0,1,2,2));
for (int ii=1; ii<4; ii++) {
eastControls.add( new JButton("" + ii) );
}
// show at the bottom
eastConstrain.add(eastControls, BorderLayout.PAGE_END);
gui.add( new JScrollPane(new JTextArea(6,10)), BorderLayout.CENTER );
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new BorderGUI();
}
});
}
}

Categories

Resources