I made a small GUI application that only has the presentation tier right now. It constructs the basic GUI, (but no logic added yet). I'm having trouble with laying out controls/components such as text fields and Buttons.
Here's the code:
Main.java
public class Main {
public static void main(String[] args) {
// Make a new Client (TempConverter application)
Client client = new Client();
}
}
Client.java
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Client extends JFrame{
private JPanel panel;
private JTextField inputTextBox;
private JTextField outputTextBox;
private JButton convertButton;
public Client(){
panel = new JPanel();
inputTextBox = new JTextField(6);
outputTextBox = new JTextField(6);
convertButton = new JButton("Convert!");
ConstructGUI();
}
private void ConstructGUI(){
this.setTitle("Temerature Converter");
this.setSize(300, 400);
PanelLayout();
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void PanelLayout(){
this.add(panel);
panel.add(inputTextBox);
panel.add(outputTextBox);
panel.add(convertButton);
}
}
The components all appear next to each other, and it's not that I expected otherwise, but no matter what layout I tried (unless I did it wrong), it doesn't change.
Do I have to override something maybe?
You can use BoxLayout to have them stacked on top of each other.
private void PanelLayout(){
this.add(panel);
//next three lines aligning the components horizontally
inputTextBox.setAlignmentX(Component.CENTER_ALIGNMENT);
outputTextBox.setAlignmentX(Component.CENTER_ALIGNMENT);
convertButton.setAlignmentX(Component.CENTER_ALIGNMENT);
//aligning horizontally end. If you don't want the align them horizontally just remove these three lines.
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(Box.createVerticalGlue());//remove this line if you don't want to center them vertically
panel.add(inputTextBox);
panel.add(outputTextBox);
panel.add(convertButton);
panel.add(Box.createVerticalGlue());//remove this line if you don't want to center them vertically
}
You could use a GridBagLayout or GridLayout depending on what you want to achieve...
public class Client extends JFrame {
private JPanel panel;
private JTextField inputTextBox;
private JTextField outputTextBox;
private JButton convertButton;
public Client() {
panel = new JPanel(new GridBagLayout());
inputTextBox = new JTextField(6);
outputTextBox = new JTextField(6);
convertButton = new JButton("Convert!");
ConstructGUI();
}
private void ConstructGUI() {
this.setTitle("Temerature Converter");
PanelLayout();
}
private void PanelLayout() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
this.add(panel);
panel.add(inputTextBox, gbc);
panel.add(outputTextBox, gbc);
panel.add(convertButton, gbc);
}
}
Have a look at Laying Out Components Within a Container for more details.
I'd also discourage you from extending directly from JFrame, but instead, start by extending from JPanel instead, it will decouple your code and provide better re-usability, among other things
Related
I'm trying to add two JPanels to a Jframe, but it seems that they look like one. I'm trying tow stack them on top of each other like this image.
I thinking I may need to look at layout managers? I just need a little nudge in the right direction.
package projectTwo;
import javax.swing.*;
public class checkFrame
{
public static void main (String[] args)
{
JFrame frame = new JFrame("Compose Message");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
checkPanel bob = new checkPanel();
//frame.add(bob);
frame.getContentPane().add(bob);
frame.setResizable(false);
frame.setSize(750, 500);
frame.setVisible(true);
}
}
package projectTwo;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class checkPanel extends JPanel implements ActionListener
{
private JPanel entry, display;
private JLabel name, checkAmount, payOrderOf, numPrint, numWords;
private JTextField nameT, checkAmountT;
private JButton Submit;
public checkPanel()
{
entryComponents();
checkDisplay();
}
private void entryComponents(){
name = new JLabel("Name:");
checkAmount = new JLabel("Check Amount:");
nameT = new JTextField(20);
nameT.addActionListener(this);
checkAmountT = new JTextField(20);
checkAmountT.addActionListener(this);
Submit = new JButton("Submit");
Submit.addActionListener(this);
add(name);
add(nameT);
add(checkAmount);
add(checkAmountT);
add(Submit);
setPreferredSize(new Dimension(750, 75));
setBackground(new Color(200,200,200));
}
private void checkDisplay(){
payOrderOf = new JLabel("Pay to the Order of: ");
add(payOrderOf);
setBackground(new Color(220,255,225));
}
public void actionPerformed (ActionEvent event)
{
}
}
You should definitely take a look at layout managers. At the moment you are simply adding JPanels to each other without any specification on where they should be.
You have a few options in this case. You could use a GridLayout, but that leads to all the panels being the same size. If you just want two panels below each other, I would suggest using a BorderLayout. I've adjusted your code as follows:
public class checkPanel extends JPanel implements ActionListener
{
private JPanel entry, display;
private JLabel name, checkAmount, payOrderOf, numPrint, numWords;
private JTextField nameT, checkAmountT;
private JButton Submit;
public checkPanel()
{
this.setPreferredSize(new Dimension(750, 75));
entryComponents();
checkDisplay();
this.setLayout(new BorderLayout());
this.add(entry, BorderLayout.NORTH);
this.add(display, BorderLayout.CENTER);
}
private void entryComponents(){
entry = new JPanel();
// You should specify entry's layout as well FlowLayout are used by default
name = new JLabel("Name:");
checkAmount = new JLabel("Check Amount:");
nameT = new JTextField(20);
nameT.addActionListener(this);
checkAmountT = new JTextField(20);
checkAmountT.addActionListener(this);
Submit = new JButton("Submit");
Submit.addActionListener(this);
entry.add(name);
entry.add(nameT);
entry.add(checkAmount);
entry.add(checkAmountT);
entry.add(Submit);
entry.setBackground(new Color(200,200,200));
}
private void checkDisplay(){
display = new JPanel();
// You should specify display's layout as well FlowLayout are used by default
payOrderOf = new JLabel("Pay to the Order of: ");
display.add(payOrderOf);
display.setBackground(new Color(220,255,225));
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
It is in general a good idea to assign a layout to each JPanel you create. The choice of layout depends on how the panel should function.
using Gridbag Layout can help you a lot I would put a separator between panels as well
so I have my Main, and this is done inside of it.
JFrame CF = new JFrame();
CF.setLayout(new BorderLayout());
CF.add(new CarGUI(), BorderLayout.NORTH);
// CF.add(new CarGUI(), BorderLayout.SOUTH);
//' South FlowLayout ' here ^
CF.setSize(600,400);
CF.setVisible(true);
In my CarGUI class I have:
public class CarGUI extends JPanel {
private CarTaxManager manager;
private JLabel lpLabel;
private JTextField searchField;
private JButton searchButton;
public CarGUI(){
FlowLayout NorthLayout = new FlowLayout();
//this.setLayout(new FlowLayout());
this.setLayout(NorthLayout);
lpLabel = new JLabel("License Plate");
searchField = new JTextField(10);
searchButton = new JButton("Search");
add(lpLabel);
add(searchField);
add(searchButton);
}
So basically what has to happen here, is I need to make another flow layout, called 'SouthLayout', and in the main, I need to put it to that one. However, the flowlayout has to be done inside CarGUI. I can't seem to get this working.
EDIT:
What it has to look like eventually:
So I'll be needing two FlowLayouts in total. One for the top, and one at the bottom. Neither of them include the TextPane in the middle.
This all comes in a borderLayout in the main.
Thanks in advance!
Sounds like a good candidate for BorderLayout
I've modified your code to get a good start at implementing it, given what you have shown us:
public class CarGUI extends JPanel {
private CarTaxManager manager;
private JLabel lpLabel;
private JTextField searchField;
private JButton searchButton;
public CarGUI(){
setLayout(new BorderLayout());
JPanel north = new JPanel();
north .setLayout(new FlowLayout());
lpLabel = new JLabel("License Plate");
searchField = new JTextField(10);
searchButton = new JButton("Search");
north.add(lpLabel);
north.add(searchField);
north.add(searchButton);
add(north, BorderLayout.NORTH);
JPanel center = new JPanel();
center.setLayout(new FlowLayout());
//TODO add components to center
add(center, BorderLayout.CENTER);
JPanel south= new JPanel();
south.setLayout(new FlowLayout());
//TODO add components to south
add(south, BorderLayout.SOUTH);
}
I think a BorderLayout would work well. The big text field could be in the center and you could have the buttons and menus above and below it. Of course, A simple BoxLayout would also do the job fine. Here is a simple example on how to achieve this with a BorderLayout.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class CarGUI extends JFrame {
public CarGUI() {
initGUI();
}
public void initGUI() {
setLayout(new BorderLayout());
setSize(600, 400);
initNorthGUI();
initCenterGUI();
initSouthGUI();
setVisible(true);
}
private void initNorthGUI() {
JPanel northPanel = new JPanel();
northPanel.setLayout(new FlowLayout());
northPanel.add(new JLabel("License Plate"));
northPanel.add(new JTextField(10));
northPanel.add(new JButton("Search"));
add(northPanel, BorderLayout.PAGE_START);
}
private void initCenterGUI() {
JLabel centerPanel = new JLabel("Center");
centerPanel.setBorder(BorderFactory.createLineBorder(Color.black));
add(centerPanel, BorderLayout.CENTER);
}
private void initSouthGUI() {
JPanel southPanel = new JPanel();
southPanel.setLayout(new FlowLayout());
southPanel.add(new JButton("Some Button"));
southPanel.add(new JComboBox());
add(southPanel, BorderLayout.PAGE_END);
}
public static void main(String args[]) {
CarGUI c = new CarGUI();
}
}
Each individual 'JPanel', or any other container, can have its own layout manager. So if you want a different layout in part of your application, add a JPanel with the layout you need.
okay ... my question is rather straight forward so I doubt ill need to add any code but I will if need be.
Whenever I create a GUI frame and add a couple of panels to it and run my application, the contents are not displayed until I either re-size the window or minimize it on the toolbar then restore it. What could be the cause of that and how can I solve it?
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public final class Calculator extends JFrame
{
//initialise various variables for use within the program
//BUTTONS
private final JButton additionButton = new JButton("+");
private final JButton subtractionButton = new JButton("-");
private final JButton divisionButton = new JButton("/");
private final JButton multiplicationButton = new JButton("*");
//PANELS
private JPanel operatorPanel;
private JPanel operandPanel;
//LABELS
private JLabel operationLabel;
//constructor to initialise the frame and add components into it
public Calculator()
{
super("Clancy's Calculator");
setLayout(new BorderLayout(5, 10));
setSize(370, 200);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
//create a message label to display the operation that has just taken place
operationLabel = new JLabel("YOU HAVE PERFORMED SOME OPERATION",SwingConstants.CENTER);
add(getOperatorPanel(), BorderLayout.NORTH);
add(getOperandPanel(), BorderLayout.CENTER);
add(operationLabel, BorderLayout.SOUTH);
}
//setter method for the operator panel
public void setOperatorPanel()
{
operatorPanel = new JPanel();
operatorPanel.setLayout(new FlowLayout());
operatorPanel.add(additionButton);
operatorPanel.add(subtractionButton);
operatorPanel.add(multiplicationButton);
operatorPanel.add(divisionButton);
}
//getter method for the operator panel
public JPanel getOperatorPanel()
{
setOperatorPanel();
return operatorPanel;
}
//setter method for operands panel
public void setOperandPanel()
{
operandPanel = new JPanel();
operandPanel.setLayout(new GridLayout(3, 2, 5, 5));
//LABELS
JLabel operandOneLabel = new JLabel("Enter the first Operand: ");
JLabel operandTwoLabel = new JLabel("Enter the second Operand: ");
JLabel answerLabel = new JLabel("ANSWER: ");
//TEXT FIELDS
JTextField operandOneText = new JTextField(); //retrieves one operand
JTextField operandTwoText = new JTextField(); //retrieves another operand
JTextField answerText = new JTextField(); //displays answer
answerText.setEditable(false); //ensure the answer field is not editable
operandPanel.add(operandOneLabel);
operandPanel.add(operandOneText);
operandPanel.add(operandTwoLabel);
operandPanel.add(operandTwoText);
operandPanel.add(answerLabel);
operandPanel.add(answerText);
}
//getter method for operand panel
public JPanel getOperandPanel()
{
setOperandPanel();
return operandPanel;
}
/** main method */
public static void main(String[] args)
{
new Calculator();
}
}
I notice you're programatically setting a new layout manager. Whenever you add, remove or change a java gui, you need to call invalidate() or revalidate() to make java re-create the GUI. See if calling invalidate() before setVisible(true) fixes the problem
For some reason i am having problems centering my panel vertically that is located inside another panel. I do exactly as the examples i studied but still no luck.
Down there is my code. Despite using setAlignmentY(0.5f) on my container panel, it still wont center when i resize the window.
Also the components inside container panel wont center either, despite setAligenmentX(0.5f).
I wonder if there is a solution for this, I pretty much tried everything out there but couldnt find a solution.
JLabel idLabel;
JLabel passLabel;
JTextField id;
JTextField pass;
JButton enter;
JPanel container;
public JournalLogin()
{
//setLayout(new FlowLayout());
//setPreferredSize(new Dimension(500, 500));
//setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));
container = new JPanel();
container.setLayout(new MigLayout());
container.setAlignmentX(0.5f);
container.setAlignmentY(0.5f);
container.setPreferredSize(new Dimension(300, 300));
container.setBorder(BorderFactory.createTitledBorder("Login"));
add(container);
idLabel = new JLabel("ID:");
idLabel.setAlignmentX(0.5f);
container.add(idLabel);
id = new JTextField();
id.setText("id");
id.setAlignmentX(0.5f);
id.setPreferredSize(new Dimension(80, 20));
container.add(id, "wrap");
setAlignmentX and Y are not the way to go about doing this. One way to center a component in a container is to have the container use GridBagLayout and to add the component without using any GridBagConstraints, a so-called default addition. There are other ways as well.
For example to alter Nick Rippe's example (1+ to him):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.*;
public class UpdatePane2 extends JPanel {
private static final int PREF_W = 300;
private static final int PREF_H = 200;
public UpdatePane2() {
JPanel innerPanel = new JPanel();
innerPanel.setLayout(new BorderLayout());
innerPanel.add(new JLabel("Hi Mom", SwingConstants.CENTER),
BorderLayout.NORTH);
innerPanel.add(new JButton("Click Me"), BorderLayout.CENTER);
setLayout(new GridBagLayout());
add(innerPanel);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("UpdatePane2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new UpdatePane2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Alignments tend to be pretty picky in Swing - they do [usually] work... but if all you're looking for is a panel that's centered, I'd recommend using Boxes in the BoxLayout (My personal favorite LayoutManager). Here's an example to get you started:
import java.awt.Dimension;
import javax.swing.*;
public class UpdatePane extends JPanel{
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
//Create Buffers
Box verticalBuffer = Box.createVerticalBox();
Box horizontalBuffer = Box.createHorizontalBox();
verticalBuffer.add(Box.createVerticalGlue()); //Top vertical buffer
verticalBuffer.add(horizontalBuffer);
horizontalBuffer.add(Box.createHorizontalGlue()); //Left horizontal buffer
//Add all your content here
Box mainContent = Box.createVerticalBox();
mainContent.add(new JLabel("Hi Mom!"));
mainContent.add(new JButton("Click me"));
horizontalBuffer.add(mainContent);
horizontalBuffer.add(Box.createHorizontalGlue()); //Right horizontal buffer
verticalBuffer.add(Box.createVerticalGlue()); //Bottom vertical buffer
// Other stuff for making the GUI
verticalBuffer.setPreferredSize(new Dimension(300,200));
JFrame frame = new JFrame();
frame.add(verticalBuffer);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
You will need to get the LayoutManager to center the layout for you. Currently it looks like the implementation of "MigLayout" does not honor the Alignment. Try changing it or creating a subclass.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class File
{
private JFrame frame1;
private JPanel panel1;
private JPanel panel2;
private JLabel labelWeight;
private JLabel labelHeight;
File()
{
frame1 = new JFrame();
panel1 = new JPanel();
panel2 = new JPanel();
labelWeight = new JLabel("Weight :");
labelHeight = new JLabel("Height :");
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
panel1.setLayout(new FlowLayout());
panel1.add(labelWeight);
panel2.setLayout(new FlowLayout());
panel2.add(labelHeight);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
frame1.setLayout(new BoxLayout(frame1,BoxLayout.X_AXIS));
panel1.setAlignmentY(0);
panel2.setAlignmentY(0);
frame1.add(panel1);
frame1.add(panel2);
frame1.setSize(400, 200);
frame1.setDefaultCloseOperation(frame1.EXIT_ON_CLOSE);
frame1.setVisible(true);
}
public static void main (String args[])
{
new File();
}
}
It gives BoxLayout Sharing error at runtime
Generally, LayoutManagers are set on a JPanel. I guess JFrame implements this method to forward it to the content pane of the frame. I would suggest you try:
Container contentPane = frame1.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane,BoxLayout.X_AXIS));
If you still have problems take a look at the Swing tutorial on How to Use Box Layout for working examples.
Swing components should be created in the Event Dispatch Thread. Try this in your main():
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new File();
}
});
But your problem may be the same as this question.