I have a program that adds bunch of components to a JPanel (in JScrollbar). However, since it adds so many components, most of them don't fit into the visible area (Viewport).
When everything loads and I start to scroll down, I notice that components, as they get into the Viewport area, are aligning and setting their positions. That causes my JScrollPane to be higher than necessary. That makes it "snap" when I get to the end (components abruptly move up (align properly), and so does the viewport).
I tried calling repaint() and validate(), but with no effect whatsoever. What am I doing wrong?
I would suggest posting an SSCCE in order to exactly replicate your specific problem.
I did a short example that may lead you in the right direction.
Basically will just add 225 JButtons to JPanel with GridLayout which in turn is added to JScrollPane.
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class JScrollPaneOfComponents {
/**
* Default constructor for ScrollBarOfComponents.class
*/
public JScrollPaneOfComponents() {
initComponents();
}
/**
* Initialize GUI and components (including ActionListeners etc)
*/
private void initComponents() {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(15, 15));
//create 225 JButtons and add them to JPanel;
for (int i = 0; i < (15*15); i++) {
panel.add(new JButton(String.valueOf((i + 1))) {
//make buttons bigger for demonstartion purposes
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
});
}
JScrollPane scrollpane = new JScrollPane(panel) {
//size the JScrollPane purposelfully smaller than all components
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
//add scrollpane to frame
jFrame.add(scrollpane);
//pack frame (size JFrame to match preferred sizes of added components and set visible
jFrame.pack();
jFrame.setVisible(true);
}
public static void main(String[] args) {
/**
* Create GUI and components on Event-Dispatch-Thread
*/
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
//set nimbus look and feel
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
//create new instance of GUI
JScrollPaneOfComponents test = new JScrollPaneOfComponents();
}
});
}
}
Related
I'm making a frame who needs to show labels in a Scroll Panel, but after I add the labels the scroll don't work.
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(1, 1, 210, 259);
panel.add(scrollPane);
JPanel roomList = new JPanel();
scrollPane.setViewportView(roomList);
roomList.setLayout(null);
int x=0;
for(String l : list) {
JLabel c = new JLabel(l+" "+x);
c.setBounds(new Rectangle(1, 1+x*11, 191, 14));
roomList.add(c);
x++;
}
I'm sure the list has more than 22.
I don't know how to google it!
Your basic problem is, you don't understand how the layout management API works, or how to replace it's functionality when you choose to discard it.
You problem starts here:
roomList.setLayout(null);
There's a lot of work going on in the background which provides a great deal of information to various parts of the API, while on the surface, the layout management API is not complex, the role it plays is.
The JScrollPane will use the component's preferredSize to determine when it should display the scrollbars. Since you've done away with this automated calculation, the JScrollPane has nothing to go on
For more information, have a look at Laying Out Components Within a Container
As a simple example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane(new TestPane());
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
for (int index = 0; index < 100; index++) {
add(new JLabel("Row " + index), gbc);
gbc.gridy++;
}
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(100, 50);
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width <= getWidth();
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}
This example implements the Scrollable interface, this is not always required, but is used, for this example, to provide a hint to the JScrollPane about the preferred size of the viewable area it should use, otherwise it will attempt to use the component's preferredSize.
But, as has already been suggested, there are other, simpler and more optimised solutions available to you.
If your information is simple enough, you can use a JList to list a number of values in a vertical manner, see How to use Lists for more details.
If you information is in a more complex structure, you could use a JTable, which provides a row and column style structure. See How to use tables for more information
Have you tried using jLists instead of JScrollPanes ?
They're very easily implemented, look great and work like a charm.
DefaultListModel model = new DefaultListModel();
for(String l : list) {
model.addElement(l);
}
yourList.setModel(model);
Where list is the list with the room data and yourList is the jList.
I have no purpose for what I'm really doing, just trying things out with Java Swing. What I have right now are these three variables:
int[] gridIterations = {10,10}; //how many JButtons are made each row/column
int[] frameSize = {600,600}; //size of the JFrame
int[] gridSize = {60,60}; //by gridSize, I mean size of the JButtons
I also have a nested for loop which uses these variables to create a grid of JButtons. I would expect the grids to perfectly fit the JFrame, however this is the result:
After some testing I realized that the frame will actually only fit all the JButtons if the size is (615, 631) But I'm wondering, why does it fit only with these parameters, and why, of all numbers, would it be those? To my understanding a simply calculation of 60 * 10 should equal 600 and successfully have all buttons fit into the JFrame, but I am most likely overlooking something. What could that be? Thanks.
A lot comes down to the requirements of the content and the layout manager. Rather then looking "how big" you'd like the frame to be, focus on the amount of space the content needs. The frame will then "pack" around this.
This means that the frame will "content size + frame border size" big.
JFrame#pack takes into consideration the content's preferred size and adds in the frames border insets automatically.
So, the only thing you need to is call JFrame#pack AFTER you finished adding the content to it
So, based on your code:
public class Testing {
public static void main(String[] args) {
JFrame frame = new JFrame("hi");
for (int i = 0; i < 10; i++) {
JButton a = new JButton();
a.setSize(20,20);
a.setLocation(20*i, 0);
frame.getContentPane().add(a);
}
frame.setLayout(null);
frame.pack();
frame.setVisible(true);
}
}
You are using a null layout. JFrame#pack will use the information provided by the layout manager to determine the "preferred" size of the overall content.
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify.
Rather the focusing on the absolute, which would be variable between OS's (and even different PC's with the same OS), focus on the user experience.
As has, already, been demonstrated, you can easily get this to work using a GridLayout
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(10, 10, 0, 0));
for (int index = 0; index < 10 * 10; index++) {
JButton btn = new JButton(String.valueOf(index)) {
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
};
add(btn);
}
}
}
}
If, you need a more complex management (ie depth by breadth), you could use a GridBagLayout instead
Take a look at Laying Out Components Within a Container, How to Use GridLayout and How to Use GridBagLayout for more details ;)
The size of a JFrame includes its insets. This basically means the title bar and borders.
GridLayout will do this perfectly for you with much less effort involved.
class GridButtons implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new GridButtons(4, 5));
}
final int rows;
final int cols;
GridButtons(int rows, int cols) {
this.rows = rows;
this.cols = cols;
}
#Override
public void run() {
JFrame frame = new JFrame();
JPanel grid = new JPanel(new GridLayout(rows, cols));
for (int i = 0; i < (rows * cols); ++i) {
grid.add(new JButton() {
#Override
public Dimension getPreferredSize() {
return new Dimension(60, 60);
}
});
}
frame.setContentPane(grid);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
I'm just starting with Java and I wanted to make a little program that opens a jFrame with a text field in which you can write a number. Then you press a button and another jFrame with a jPanel, which will turn green if the number is even, and black if it's odd. I edited the code of the jPanel so that the color changes depending on the number, but the problem is that it will only work once. If I write "2" and press the button, the jFrame will appear with a green panel, but then if I write another odd number and press it again, the frame will stay green.
How could I solve this so that the background color changes whenever I press the button? I should also say that I made an "if-else", so that you could only open the second jFrame once because I didn't know how to make it close and then open again, so maybe that has to do with the problem. Thanks!
This is the code in the Panel. To make it easier, I tried to just turn it green if a zero was introduced, and now it doesn't even work:
jPanel1 = new javax.swing.JPanel();
if ("0".equals(Taller2.opcion)) {
jPanel1.setBackground(new java.awt.Color(0, 255, 0));
}
else {
jPanel1.setBackground(new java.awt.Color(0, 0, 0));
}
jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(255, 255, 255)));
// Code of sub-components - not shown here
// Layout setup code - not shown here
// Code adding the component to the parent container - not shown here
Here is the pretty basic main class:
public class Taller2 {
/**
* #param args the command line arguments
*/
public static String opcion;
public static boolean panelabierto;
public static void main(String[] args) {
Pregunta a = new Pregunta();
a.setVisible(true);
opcion = null;
panelabierto = false;
}
}
The second jFrame (the one with the jPanel inside) only has the basic code generated by Netbeans on the designer. If you need the code for the jFrame with the text field, I could add it too, although I believe the problem lies within the jPanel.
Don't create more instances of JPanel, simply create one and change it's state.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JFormattedTextField field = new JFormattedTextField(NumberFormat.getInstance());
field.setColumns(4);
setLayout(new GridBagLayout());
add(field);
field.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long value = (Long)field.getValue();
if ((value % 2) == 0) {
setBackground(Color.GREEN);
} else {
setBackground(Color.RED);
}
}
});
setBackground(Color.BLACK);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Are you sure your code is correct? My best guess (without you providing your code) is that your code for checking whether the number is odd or even does not work correctly.
The best way to determine whether a number is odd or even in Java is to use the modulus (%) operator:
if ((num%2)==0) {
// Number is even
} else {
// Number is odd
}
(Replace "num" with the number you want to test.)
I've got a problem with the size of a JFrame:
I want to show content in the Jframe. The content will have the size 640 x 480. But I can not use the method JFrame.setSize(640, 480); because I also want to show the decoration of the window.
My first thought was: Add a panel with the preferred dimension and than use pack();. But this also doesn't work - I only get a really small window.
I think the solution to my problem could be similar to this:
String JFrame Size
How do I make a JFrame a certain size not including the border
Here is my code:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Fenster extends JFrame {
JPanel panel;
Dimension dim;
Fenster(){
dim = new Dimension(640, 480);
panel = new JPanel();
panel.setSize(dim);
panel.setMinimumSize(dim);
panel.setMaximumSize(dim);
panel.setPreferredSize(dim);
panel.setBounds(0, 0, 640, 480);
panel.setDoubleBuffered(true);
JLabel label = new JLabel("bla");
panel.add(label);
this.setLayout(null);
this.getContentPane().add(panel);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
}
this.setLayout(null); is your problem. Let the layout manager do it's job
From the JavaDocs
public void pack() Causes this Window to be sized to fit the
preferred size and layouts of its subcomponents. The resulting width
and height of the window are automatically enlarged if either of
dimensions is less than the minimum size as specified by the previous
call to the setMinimumSize method. If the window and/or its
owner are not displayable yet, both of them are made displayable
before calculating the preferred size. The Window is validated after
its size is being calculated.
Most containers (JComponent, JPanel) have a default, preferred size of 0x0, the layout manager provides this information based on the requirements of the layout manager itself and the contents of the container, but using a null, you effectivly make the container 0x0...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
add(new JLabel("Look ma, no null layouts!"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}
}
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
See Why is it frowned upon to use a null layout in SWING? for more details...
I Have recently started Java programming and am trying to create a login screen. However, I cannot figure out how to create a new line to put my buttons and text on. Also, I would like to move these to the bottom right corner of the JPanel. I apologise for my poor wording and hopefully you can see what I mean from my code. Please help and thank you in advance.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardLayoutDemo implements ItemListener {
JPanel cards;
final static String BUTTONPANEL = "Card with JButtons";
public void addComponentToPane(Container pane) {
JPanel card1 = new JPanel();
card1.add(new JLabel("Username:"));
card1.add(new JTextField("Username", 10));
card1.add(new JButton("Login")); //end line here
//New line
card1.add(new JLabel("Password:"));
card1.add(new JTextField("Password", 10));
card1.add(new JButton("Register")); //end line here
//New line
card1.add(new JCheckBox());
card1.add(new JLabel("Remember credentials"));
cards = new JPanel(new CardLayout());
cards.add(card1, BUTTONPANEL);
pane.add(cards, BorderLayout.BOTTOM_RIGHT);// Add cards to bottom right hand corner.
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, (String)evt.getItem());
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Login");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CardLayoutDemo demo = new CardLayoutDemo();
demo.addComponentToPane(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
UIManager.put("swing.boldMetal", Boolean.FALSE);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
As shown here, you can position your top-level container in the lower, right portion of the screen. Substitute your own components for the placeholder mentioned in getPreferredSize(). Also, consider a JToolBar, which can float on many implementations.
Addendum: I want to move the buttons to the bottom right corner of the JPanel, not move the JPanel to the bottom of the screen.
Specifying FlowLayout.RIGHT for your card1 produces the result shown. Substitute your panel having CardLayout in the content pane's BorderLayout.CENTER.
public void addComponentToPane(Container pane) {
JPanel card1 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
…
pane.add(new JPanel() {
#Override // placeholder for actual content
public Dimension getPreferredSize() {
return new Dimension(800, 200);
}
}, BorderLayout.CENTER);
pane.add(cards, BorderLayout.PAGE_END);
}
Addendum: Here's an update to your example.
public void addComponentToPane(Container pane) {
…
pane.add(cards, BorderLayout.PAGE_END);
}
…
private static void createAndShowGUI() {
JFrame frame = new JFrame("Login");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Move frame to lower right corner of screen
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds();
int x = (int) rect.getMaxX() - frame.getWidth();
int y = (int) rect.getMaxY() - frame.getHeight();
frame.setLocation(x, y);
CardLayoutDemo demo = new CardLayoutDemo();
demo.addComponentToPane(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
Suggestion:
There is no such constraint BorderLayout.BOTTOM_RIGHT with BorderLayout.
BorderLayout.SOUTH : place the component at the bottom of container
BorderLayout.EAST : Place the component at the right side of container
BorderLayout.NORTH : place the component at the top of container
BorderLayout.WEST : place the component at the right side of container
BorderLayout.CENTER: place the component at the middle of container
If you want to orient your component as you wish, where the
component will appear in order, positioned in relative to each
other, responsive with Main Container's re-size, the you need to
learn about Layout Manager first.
Learn about Event listeners. Instead of implementing an ItemListener to a JPanel/Top level class which doesn't have such listeners, either implement it to a new class with naming convention MyItemListener implements ItemListener and create a new instance to add with addItemListener(listener) function or add them inline using the means of anonymous class.
checkBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
// put your code
}
});
ItemListener is for the Components which works with item i.e CheckBox, ComboBox etc. There are other kind of Even listeners exist too e.g, ActionListener, MouseListener etc
Tutorial Resource:
Writing Event Listeners
Using Layout Managers
I've taken your code and modified it to the following:
package sandbox;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class LoginLayoutDemo
{
JPanel cards;
public void addComponentToPane(Container pane)
{
// Panel for text and fields
JPanel textAndFieldsPanel = new JPanel();
textAndFieldsPanel.setLayout(new GridLayout(2,2));
textAndFieldsPanel.add(new JLabel("Username ", JLabel.RIGHT));
textAndFieldsPanel.add(new JTextField("Username", 10));
textAndFieldsPanel.add(new JLabel("Password ", JLabel.RIGHT));
textAndFieldsPanel.add(new JPasswordField("password", 10));
JPanel controlsPanel = new JPanel();
controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.PAGE_AXIS));
controlsPanel.add(textAndFieldsPanel);
controlsPanel.add(new JCheckBox("Remember credentials"));
JPanel bottomPanel = new JPanel();
bottomPanel.add(controlsPanel);
bottomPanel.add(new JButton("Login")); // end line here
bottomPanel.add(new JButton("Register")); // end line here
cards = new JPanel(new BorderLayout());
// cards.setLayout(new BorderLayout(cards, BoxLayout.LINE_AXIS));
cards.add(bottomPanel, BorderLayout.LINE_END);
pane.add(cards, BorderLayout.PAGE_END); // BOTTOM_RIGHT);// Add cards to bottom right hand
// corner.
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Login");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// CardLayoutDemo demo = new CardLayoutDemo();
new LoginLayoutDemo().addComponentToPane(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args)
{
try
{
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex)
{
ex.printStackTrace();
} catch (IllegalAccessException ex)
{
ex.printStackTrace();
} catch (InstantiationException ex)
{
ex.printStackTrace();
} catch (ClassNotFoundException ex)
{
ex.printStackTrace();
}
UIManager.put("swing.boldMetal", Boolean.FALSE);
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
You really need to learn about LayoutManagers -- the Oracle/Java site has a decent one, and there are others readily available. The thing I think most of them do least well is explain overall what the managers are for and how to design things with them - they tend to plunge right into code.
A LayoutManager is applied to a Container, and tells it how to treat the components that are added to it. FlowLayout and BoxLayout tend to lay things out in a line, either horizontal or vertical at your choice. GridLayout lays things out in a table, with all 'cells' in the grid the same size. BorderLayout has a center section and one section each for N, S, E, and W; N,S stretch horizontally, E,W stretch vertically; all four of these take their other dimension from their contained component, and the center of the BorderLayout stretches in both directions to fill the available space in its container. There is GroupLayout and GridBagLayout, etc., they are all designed to solve some problem or set of problems in UI design, and you need to learn what they do in order to design Swing UIs.
Something that some of the tutorials do but don't really explain: Each container has one layout manager, but the container can be a component in another container, and the enclosing container can have a different layout manager. That's what we've done here; the BorderLayout of the overall frame puts the panel we've built at the bottom, and the right-aligned panel within our panel puts them to the right; that's how they all get to the bottom right.
You may have meant for others of your controls to be on other lines; I'll leave doing that as an exercise for you... Good luck.
One more thing: CardLayout is for situations is where, for some reason, two or more panels are arranged on TOP of each other, i.e., one obscures the other. You have no such need in your UI that I could tell, so I eliminated the CardLayout manager.