Strange rendering issue with Java Swing libaray - java

Background
I want to create a GUI application using the java swing library. For layout I require it to be a GridLayout as the program outline requires this.
Aim
To render a panel with text inside it.
What I have tired
Using setBounds to move the text - this worked and the text did render, however it does not work with the GridLayout therefore does not meet the required specs.
Reading atricles and documentation on GridLayout and rendering of JLabels - Tried the examples - failed.
Using intellij debugger - results show the JLabel is not null, and the text is set to the correct value, along with the enabled and visible properties being true.
Increasing and decreasing GirdLayout rows and columns - failed.
Altering the size of the panel - failed.
Changing the foreground colour to something like green - failed.
Code
public class MainPanel extends JPanel {
public MainPanel(JFrame frame) {
setBounds(40,40,200,200);
setBackground(Color.BLUE);
JLabel label = new JLabel("Hello World", SwingConstants.CENTER);
label.setFont(new Font("Tahoma", Font.PLAIN, 25));
label.setVisible(true);
add(label);
setLayout(new GridLayout(1, 1));
}
}
Result
Conclusion
As you can see, the panel does render (the blue square), however there is no text inside of it. I'm rather confused as code very similar to this has worked on aother project, and there is no obvious reason this shouldn't work.

Your code is essentially OK with the provisos I mentioned. Proof: (obviously you can separate out your own class as a top level one later):
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class F extends JFrame {
private void setGui() {
try {
setLocation(0, 100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(new MainPanel());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
EventQueue.invokeAndWait(() -> {
F f = new F();
f.setGui();
f.setSize(200, 200);
f.setVisible(true);
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MainPanel extends JPanel {
public MainPanel() {
setLayout(new GridLayout(1, 1));
setBounds(40,40,200,200);
setBackground(Color.BLUE);
JLabel label = new JLabel("Hello World", SwingConstants.CENTER);
label.setFont(new Font("Tahoma", Font.PLAIN, 25));
add(label);
}
}

Related

Java - My action event doesn't work

I'm learning Java and Swing, but my JButton doesn't work.
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Programma {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e){
e.printStackTrace();
}
JFrame frame = new JFrame("DIG");
JPanel panel = new JPanel();
JButton button = new JButton("Click Me");
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.setBounds(100, 100, 130, 35);
panel.add(button);
frame.add(panel);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JLabel label = new JLabel("Hello World");
label.setVisible(true);
panel.add(label);
}
});
}
}
The frame and button are visible, nut when I click it, the label doesn't appear. How can I fix this?
Do I write this before the other component like JPanel, JButton, etc., or do I write this at the end of code:
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
What is the difference ?
By the way, button.setBounds(100, 100, 130, 35) doesn't work, either.
I see some issues in your code:
button.setBounds(100, 100, 130, 35); that line will be ignored and you shouldn't be manually be determining the position of the components. See Null layout is evil and Why is it frowned upon to use a null layout in swing? altough you're not using null layout, there is explained why you shouldn't be manually determining the positions of the components.
You're running everything in your program in the main method, that will be hard to maintain later.
You're calling frame.setVisible(true) before you've added all your elements to it, that will cause you random issues.
You're not running your program on the Event Dispatch Thread (EDT), you can solve this by starting your program with the following code, which places it in the EDT. It's recommended as Swing is not thread safe.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Your constructor here
}
});
}
You're setting the size of the JFrame with setSize(...), instead call frame.pack() and override the getPreferredSize() method of the JPanel.
After all the above has been said, you need to call revalidate() and repaint() on your ActionListener so your program paints its new state.
This program follows all the above recommendations and produces the following outputs (before clicking and after clicking the button 3 times), I on purpose to not make the images so large, made the GUI shorter (200 x 200 instead of 400 x 400)
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Programma {
private JFrame frame;
private JPanel panel;
private JButton button;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Programma().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame("DIG");
panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
button = new JButton("Click Me");
panel.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JLabel label = new JLabel("Hello World");
panel.add(label);
panel.revalidate();
panel.repaint();
}
});
frame.add(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Do i write this before the other componente like JPanel,JButton... or do i write this at the end of code ?
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
What is the difference ?
Altough I answered this on the recommendations, the difference is that if you call setVisible before adding all your elements to the frame, then you'll find yourself with some random issues where the components are not all visible until you pass your mouse over them (or where they should be). frame.pack() and setVisible should be the last ones to be called in your program, and frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); can be at the start or the end, it doesn't affects, but I prefer to have it at the end too.
button.setBounds(100, 100, 130, 35); doesn't work too.
Well, that's because of you're using a layout manager (and that's the right way to do your GUIs) instead of a null-layout (which you shouldn't be using anyway) (See point #1).
Edit
What is the difference between frame.setSize(); and frame.setpack() ?
If you read the docs for 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.
So, it will calculate the minimum size for your JFrame where all the elements are visible and in their preferred size while setSize will only set the window size, but if you place a JScrollBar inside it for example this will reduce the window size, because of that, that's why you should override the getPreferredSize(...) method of your container, so it will calculate its preferred size including the width of the JScrollBar or some other elements that could modify its size. See Should I avoid the use of setPreferred|Maximum|MinimumSize in Swing? (the general consensus says yes)
When you add components dynamically to panel, you need to repain it.
Do this
panel.revalidate();
after
panel.add(label);

Java Swing Moving Away From Null Layout

I built a great GUI using the frowned upon null layout (I defined a lot of constants and used a window resize listener to make it easy). Everything worked perfectly until I started using a new computer. Now, the component's are not positioned properly (from the picture you can see that the components are offset down and right). After researching the problem I learned that layout managers make sure that the components are positioned properly throughout different machines. Because of this, I would like to start rebuilding the GUI in an actual layout manager. The problem is that I often feel limited in the way I position components when attempting to use an actual layout manager.
For anyone who is curious, I was originally using a dell inspiron laptop with windows 10, and have moved to an Asus Laptop (I don't know the actual model, but the touch screen can detach from the keyboard), also with windows 10.
My question:
Which layout manager would be the fastest and easiest to build the GUI shown in the picture above (out of the stock Swing Layouts and others). I would like this layout to respect the components' actual sizes for only a few but not all of the components. Using this layout, how would I go about positioning the inventory button (the hammer at the bottom left) so that the bottom left corner of the inventory button is 5 pixels up and right from the bottom left corner of the container, even after resizing the container?
Thanks in advance. All help is appreciated.
EDIT: The "go find a key" and "Attempt to force the door open" options should have their sizes respected.
The simplest solution that comes to my mind is a BorderLayout for the main panel. Add the textarea to NORTH / PAGE_START. Make another BorderLayout containing the inventory button (WEST / LINE_START) and the location label (EAST / LINE_END). Add that to SOUTH / PAGE_END of the main BorderLayout. Then just add a BoxLayout with vertical alignment to the main BorderLayout's CENTER containing the two buttons. Here's a tutorial for the standard layout managers.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class Example {
public Example() {
JTextArea textArea = new JTextArea("There is a locked door");
textArea.setRows(5);
textArea.setBorder(BorderFactory.createLineBorder(Color.GRAY));
textArea.setEditable(false);
WhiteButton button1 = new WhiteButton("Go find a key") {
#Override
public Dimension getMinimumSize() {
return new Dimension(200, 25);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 25);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(200, 25);
}
};
WhiteButton button2 = new WhiteButton("Attempt to force the door open");
button2.setMargin(new Insets(0, 60, 0, 60));
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
buttonPanel.add(button1);
buttonPanel.add(Box.createVerticalStrut(5));
buttonPanel.add(button2);
WhiteButton inventoryButton = new WhiteButton(
new ImageIcon(new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB)));
JLabel locationLabel = new JLabel("Location: 0");
locationLabel.setVerticalAlignment(JLabel.BOTTOM);
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.add(inventoryButton, BorderLayout.WEST);
southPanel.add(locationLabel, BorderLayout.EAST);
JPanel mainPanel = new JPanel(new BorderLayout(0, 5));
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.add(textArea, BorderLayout.NORTH);
mainPanel.add(buttonPanel);
mainPanel.add(southPanel, BorderLayout.SOUTH);
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
private class WhiteButton extends JButton {
public WhiteButton() {
setBackground(Color.WHITE);
}
public WhiteButton(String text) {
this();
setText(text);
}
public WhiteButton(ImageIcon icon) {
this();
setIcon(icon);
setBorder(BorderFactory.createLineBorder(Color.GRAY));
}
}
}

Event dispatch thread exception?

Here is my code, I run it on eclipse and it displays the frame the button and the field, using the button should return the value of the equation typed in the field fe. When i put 2+2 in the field and click "oblicz" it should return 4 but it does not, and it drops some weird exception. Am I missing something?
static JTextField pole1;
public static void main(String[]args)
{
JFrame frame = new JFrame("applet 1.0");
frame.setSize(700, 600);
frame.setLocation(300, 100);
frame.setResizable(false);
frame.setLayout(null);
frame.setVisible(true);
// pole
pole1 = new JTextField();
pole1.setBounds(10, 10, 230, 50);
Font F1 = new Font("Comic Sans",Font.BOLD,20);
pole1.setFont(F1);
pole1.setHorizontalAlignment(JTextField.RIGHT);
frame.add(pole1);
// button
JButton button = new JButton("oblicz");
button.setBounds(10, 80, 100, 70);
button.setBorder(null);
frame.add(button);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
{
String str = pole1.getText();
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = str;
try
{
pole1.setText(String.valueOf(engine.eval(foo)));
}
catch (ScriptExecption e)
{
}
}
}
});
Your code as written worked for me.
However, I made some changes to your code to use Swing more effectively.
I removed all the code from the main method and replaced it with a call to the SwingUtilities invokeLater method. The invokeLater method puts the creation and use of the Swing components on the Event Dispatch thread. Oracle and I demand that all Swing applications start on the Event Dispatch thread.
I put the JTextField and JButton on a JPanel. Do not add Swing components other than JPanel or other panel type components to a JFrame.
I separated the creation of a JFrame from the creation of a JPanel. Divide and conquer. Separation of concerns makes the code easier to read and test.
I created the JPanel and JFrame before I made it visible. Call the JFrame methods in the order I posted.
I removed the null layout and the absolute positioning of the Swing components. Swing was designed to be used with Swing layout managers. Learn them. Use them.
I used a couple of empty JPanel borders to add some white space around the components.
I fixed some syntax problem in your action listener. In my Eclipse IDE, I deleted your try / catch block and let Eclipse generate the try / catch block. I added a printStackTrace method call so that any exception would print out as a stack trace.
Here's the code.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class JavascriptCalculator implements Runnable {
private JButton button;
private JTextField pole1;
public static void main(String[] args) {
SwingUtilities.invokeLater(new JavascriptCalculator());
}
#Override
public void run() {
JFrame frame = new JFrame("Applet 1.0");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.getRootPane().setDefaultButton(button);
frame.setVisible(true);
}
private JPanel createPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.setLayout(new BorderLayout());
// pole
JPanel polePanel = new JPanel();
polePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
pole1 = new JTextField(20);
Font f1 = new Font("Comic Sans", Font.BOLD, 20);
pole1.setFont(f1);
pole1.setHorizontalAlignment(JTextField.RIGHT);
polePanel.add(pole1);
panel.add(polePanel, BorderLayout.CENTER);
// button
button = new JButton("oblicz");
panel.add(button, BorderLayout.SOUTH);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String str = pole1.getText().trim();
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = str;
try {
pole1.setText(String.valueOf(engine.eval(foo)));
} catch (ScriptException e) {
e.printStackTrace();
}
}
});
return panel;
}
}

Parts of JComponents incompatible with Ubuntu?

I have a program that outputs the calculation result in a JFrame that contains a JPanel (for extensibility), which contains a JLabel, which displays the said output (which is a string).
I found JLabel's default font to be rather small and hard to read, and so increased the font size and replaced it with a Windows specific font, but didn't think much of it since I checked with a font that doesn't exist, and noticed the program worked fine even if the font doesn't exist. (on both Windows 7 and 8)
However, when run on Ubuntu, the result was a JFrame that was the minimal size.
So now I'm wondering if this is an example of some incompatibility on JVM, or a problem with the copy of Ubuntu it was run on.
The following code should replicate the problem on Ubuntu (or maybe Linux in general) if this is a JVM issue.
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public Main(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel("SOME TEXT");
lbl.setFont(new Font("font that doesnt exist", Font.PLAIN, 20));
JPanel pnl = new JPanel();
pnl.add(lbl);
frame.add(pnl, BorderLayout.CENTER);
frame.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
}
public static void main (String[] args)
{
Main main = new Main();
}
}
PS the Ubuntu computer is not mine, so I can't exactly test as I want
Testing on Ubuntu 14, Java 7, font substitution appears to work in the usual way. Note the need to invoke pack() and then setVisible(), as well as to start the UI on the EDT.
import java.awt.Font;
import java.awt.GridLayout;
import java.io.File;
import javax.swing.*;
public class TestFrame extends JFrame {
public TestFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridLayout(0, 1));
JLabel label1 = new JLabel("Some big, bold, serif text.");
label1.setFont(new Font(Font.SERIF, Font.BOLD, 24));
this.add(label1);
JLabel label2 = new JLabel("Some big, bold, default text.");
label2.setFont(new Font("42", Font.BOLD, 24));
this.add(label2);
this.pack();
this.setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestFrame().setVisible(true); }
});
}
}

Place buttons and text on new line and move them to the bottom of the screen in java

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.

Categories

Resources