JTextField is stacking on top of JTextArea - java

I'm working on a small GUI project that builds a book manger to mange a book. In my layout, I want a textArea to display information about my book, a text JLabel underneath my textArea and a JTextArea for me to input information same column of JLabel and 1 row next to Label. However when I run my program, textArea and Label is completely cover over my textArea.
How can I fix this problem. Thanks!!
import java.awt.*;
import javax.swing.*;
public class Design extends JFrame {
JButton button1;
JTextArea outputArea;
JLabel stockLabel, bookPriceLabel;
JTextField stockTextField, priceTextField;
JPanel panel;
GridBagConstraints gc;
public Design(){
super("Book Info");
gc = new GridBagConstraints ();
panel = new JPanel();
outputArea = new JTextArea(20, 50);
stockLabel = new JLabel ("Books In Stock");
bookPriceLabel = new JLabel("Book Price");
stockTextField = new JTextField(10);
button1 = new JButton ("button1");
panel.setLayout(new GridBagLayout());
panel.setSize(600, 600);
gc.anchor = GridBagConstraints.NORTHWEST;
gc.weightx = 1;
gc.weighty = 1;
panel.add(outputArea, gc);
gc.gridx = 2;
gc.gridy = 2;
panel.add(stockLabel, gc);
gc.gridx = 3;
gc.gridy = 2;
panel.add(stockTextField, gc);
this.getContentPane().add(panel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600,600);
setVisible(true);
setLocationRelativeTo(null);
}
public static void main (String args[]){
Design frame = new Design();
}
}

You could apply a gridWidth constraint to the JTextArea which would allow it to span multiple columns.
Remember, GridBagLayout is still based around the concept of a grid (rows and columns), but which provides a lot of flexibility to customise how components fill and span through out that grid
Maybe something like...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Design extends JFrame {
JButton button1;
JTextArea outputArea;
JLabel stockLabel, bookPriceLabel;
JTextField stockTextField, priceTextField;
JPanel panel;
GridBagConstraints gc;
public Design() {
super("Book Info");
gc = new GridBagConstraints();
panel = new JPanel();
outputArea = new JTextArea(20, 50);
stockLabel = new JLabel("Books In Stock");
bookPriceLabel = new JLabel("Book Price");
stockTextField = new JTextField(10);
button1 = new JButton("button1");
panel.setLayout(new GridBagLayout());
gc.anchor = GridBagConstraints.NORTHWEST;
gc.gridx = 0;
gc.gridy = 0;
gc.weightx = 1;
gc.weighty = 1;
gc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(new JScrollPane(outputArea), gc);
gc.weightx = 0;
gc.weighty = 0;
gc.anchor = GridBagConstraints.WEST;
gc.gridwidth = 1;
gc.gridx = 0;
gc.gridy = 2;
panel.add(stockLabel, gc);
gc.gridx++;
gc.gridy = 2;
panel.add(stockTextField, gc);
this.getContentPane().add(panel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
setLocationRelativeTo(null);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Design frame = new Design();
}
});
}
}
See How to Use GridBagLayout for more details
Some general feedback:
There's no point in calling setSize on a component which will be added to a container which using a layout manager, the action will simply be ignored and the layout manager will call setSize with what it wants to use
JTextArea really should be contained within a JScrollPane, you'll get some weird results if you don't (it will want to grow as the text occupies more space)
Prefer JFrame#pack over JFrame#setSize, this will take into account the frame borders, wrapping the frame around the contents
You really should avoid extending directly from top level containers like JFrame, apart from locking you into a single use case, you're really not adding any new functionality to the frame. Instead, start with something like a JPanel, build you core UI ontop of that and then, when you need to, add that to what ever container you want

Related

GridBagLayout not working inside JPanel *Updated*

First post, and tried to research this as much as possible but finally gave up and decided to ask.
I am building a recipe book program, and on one page it has the list of recipes. When you select a recipe it will appear on the left side as labels. The issue is on my page I have two JPanels. One hosts the list of recipes, the other is labels for displaying the information. On the side that has the labels I cant get them to move, or alter or anything inside the JPanel.
I feel this has a simple solution but I am too inexperienced to see. Anyway thanks for the help in advance.
////Form Panel Class
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class FormPanel extends JPanel {
private JScrollPane pane;
private JPanel pane2;
// viewing of information
private JLabel nameLabel1;
private JLabel nameLabel2;
private JLabel nameLabel3;
public FormPanel() {
nameLabel1 = new JLabel("Label1");
nameLabel2 = new JLabel("Recipe Name: ");
nameLabel3 = new JLabel("Tag Lines: ");
pane = new JScrollPane();
pane2 = new JPanel();
layoutComponents();
pane.setPreferredSize(new Dimension(200, 450));
pane2.setBorder(BorderFactory.createTitledBorder("Recipes"));
pane2.setPreferredSize(new Dimension(375, 450));
}
public void layoutComponents() {
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
///////////////////////////////////////
// First Row
gc.gridy = 0;
gc.weightx = 1;
gc.weighty = 1;
gc.gridx = 1;
gc.anchor = GridBagConstraints.FIRST_LINE_START;
add(pane2, gc);
////////////////////////////////////////////
///////////////////////////////////////
// First Row
gc.gridy = 0;
gc.weightx = 2;
gc.weighty = 1;
gc.gridx = 1;
gc.anchor = GridBagConstraints.FIRST_LINE_END;
gc.insets = new Insets(5, 5, 5, 5);
add(pane, gc);
////////////////////////////////////////////
GridBagConstraints gc2 = new GridBagConstraints();
//
gc2.gridy = 0;
gc2.weightx = 1;
gc2.weighty = 1;
gc2.gridx = 0;
gc2.fill = GridBagConstraints.PAGE_START;
pane2.add(nameLabel2, gc2);
////////////////////////////////////////////
gc2.gridy = 1;
gc2.weightx = 1;
gc2.weighty = 1;
gc2.gridx = 0;
gc2.fill = GridBagConstraints.CENTER;
pane2.add(nameLabel3, gc2);
////////////////////////////////////////////
gc2.gridy = 2;
gc2.weightx = 1;
gc2.weighty = 1;
gc2.gridx = 0;
gc2.fill = GridBagConstraints.SOUTH;
pane2.add(nameLabel1, gc2);
}
}
//Mainframe Class
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
public class Mainframe extends JFrame {
private FormPanel formPanel;
private JTabbedPane tabPane;
public Mainframe() {
super("My Digital Cookbook");
setLayout(new BorderLayout());
formPanel = new FormPanel();
tabPane = new JTabbedPane();
add(tabPane, BorderLayout.PAGE_START);
tabPane.addTab("New Recipe", formPanel);
setMinimumSize(new Dimension(500, 600));
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
//Application Class
import javax.swing.SwingUtilities;
public class Application {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run(){
System.out.println(SwingUtilities.isEventDispatchThread());
new Mainframe();
}
});
}
}
The lower three labels might have wonkey weights and what not just due to trying to get them to move but they all just stay in a straight line near the top of the Jpanel.
Additionally I don't think I needed to re-declare my gridbagconstraints but I decided to try for debugging attempts.
**Update -I now have posted a much simpler version of my program with the error still existing. I apologize that I don't have it smaller due to lack of flexible skills.

Java Swing: JScrollPane containing JTextArea filled with text gets very small when moved to 2nd monitor

I have a Java Swing GUI that consists of some JScrollPanes containing JTextAreas that get filled with data so that the scrollbars appear. Once the scrollbars appear, when I move the window to my second monitor, the JScrollPane gets very small so that I can no longer see the text it contains.
Example:
Here is the window on my main monitor with the JScrollPane filled with text:
Here is the window after I filled it with text and moved it to the second monitor:
Here is a small example program that demonstrates the problem:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class Main extends JFrame {
public Main() {
Test theGui = new Test();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
add(theGui);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main();
}
});
}
}
class Test extends JPanel {
private static final int PADDING = 3;
private JLabel label;
private JTextArea textarea;
private JScrollPane scrollpane;
private GridBagConstraints gbc;
public Test() {
super(new GridBagLayout());
label = new JLabel("Fill this text box with text so the scrollbars appear, then move the window to 2nd monitor:");
textarea = new JTextArea(10, 40);
scrollpane = new JScrollPane(textarea);
gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.insets = new Insets(PADDING, PADDING, PADDING, PADDING);
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 4;
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
add(scrollpane, gbc);
}
}
Note that the JScrollPane only gets very small when moving to the other monitor when it is filled with text. If there is no text in it, it seems to stay the right size.
My question is, how can I prevent the JScrollPane from getting very small when I move the window to my second monitor?
GridBagLayout will revert to the components minimumSize property when the available space for the component is less then the components preferredSize.
You can override this by using the GridBagConstraints, weightx/weighty properties, for example.
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1;
gbc.weighty = 1;
add(scrollpane, gbc);

How do I use GridBagConstraints setRows and setColumns?

How do I use setRows and setColumns to change the amount of rows and columns in my window?
Here's a copy of my code and where I tried to implement the set rows and columns:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.*;
#SuppressWarnings("unused")
public class GUI
{
public static void main(String[] args)
{
new GUI();
}
public GUI()
{
JFrame AG = new JFrame("Adventure Game");
AG.setExtendedState(JFrame.MAXIMIZED_BOTH);
AG.setResizable(true);
AG.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p=new JPanel();
p.setLayout (new GridBagLayout());
AG.add(p);
GridBagConstraints GBC = new GridBagConstraints();
GridLayout.setRows(100);//heres the set rows<<<<<<<<<<<<<<<<<<<
GridLayout.setColumns(100);//heres the set columns<<<<<<<<<<<<<<<<<<<
AG.getContentPane().add(p, BorderLayout.NORTH);
JButton saveButton =new JButton("Save");
JButton loadButton =new JButton("Load");
JButton optionsButton = new JButton("Options");
JLabel textBox= new JLabel("Story line will go here.");
JLabel label11 = new JLabel("Test 1");
GBC.gridx = 0;
GBC.gridy = 1;
p.add(label11,GBC);
JLabel label12 = new JLabel("Test 2");
GBC.gridx = 0;
GBC.gridy = 2;
p.add(label12,GBC);
JLabel label13 = new JLabel("Test 3");
GBC.gridx = 0;
GBC.gridy = 3;
p.add(label13,GBC);
JLabel label14 = new JLabel("Test 4");
GBC.gridx = 0;
GBC.gridy = 5;
p.add(label14,GBC);
AG.setVisible(true);
}
}
GridBagConstraints work with the GridBagLayout, not the GridLayout. Your call to GridLayout doesn't do anything.
To set the rows and columns with GridBagConstraints, you need to use GBC.gridx = ...; and GBC.gridy = ...;
If you are trying to place gaps between your buttons, empty GridBag cells are not the way to do it; use the insets of your GridBagConstraints for that.
To make a component in a GridBagLayout disappear without the other components shifting around, place the button in a JPanel with a CardLayout, and make sure you add that JPanel to your GridBagLayout instead of the button:
private JButton optionalButton;
private void buildWindow() {
// ...
optionalButton = new JButton("Optional Action");
JPanel optionalButtonPanel = new JPanel(new CardLayout());
optionalButtonPanel.add(optionalButton, "BUTTON");
optionalButtonPanel.add(new JLabel(), "BLANK");
// ...
}
private void setOptionalButtonVisible(boolean visible) {
Container optionalButtonPanel = optionalButton.getParent();
CardLayout layout = (CardLayout) optionalButtonPanel.getLayout();
layout.show(optionalButtonPanel, visible ? "BUTTON" : "BLANK");
}
CardLayout always displays one and only one of its components, but it sizes its associated container to fit all the components, including the invisible ones.

Java GridBagLayout - How to position my components gap-less and one by one?

I'm using GridBagLayout to place my GUI components by the following code, wanting the components lay one by one in a column, without any gaps :
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestGUI extends JFrame{
public TestGUI(){
JPanel bigPanel = new JPanel(new GridBagLayout());
JPanel panel_a = new JPanel();
JButton btnA = new JButton("button a");
panel_a.add(btnA);
JPanel panel_b = new JPanel();
JButton btnB = new JButton("button b");
panel_b.add(btnB);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weighty = 1D;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.NORTH;
bigPanel.add(panel_a, c);
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
bigPanel.add(panel_b, c);
this.add(bigPanel);
}
public static void main(String[] args) {
TestGUI gui = new TestGUI();
gui.setVisible(true);
gui.pack();
}
}
I wish the panels will be shown one by one in the column. but now i got this :
As i am going to add some more components in the bigPanel, and required some more customization to the layout, so i need to use GridBagLayout instead of other Layout.
You need to add an extra component so that it will fill the rest of the available space and push the two button-panels to the top. When you will add more components, you can of course remove that component.
Another option (without requiring an extra component) would have been to set weighty=1.0 for the panel_b and anchor=NORTH, but then you would have to change that when you add more components.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestGUI extends JFrame {
public TestGUI() {
JPanel bigPanel = new JPanel(new GridBagLayout());
JPanel panel_a = new JPanel();
JButton btnA = new JButton("button a");
panel_a.add(btnA);
JPanel panel_b = new JPanel();
JButton btnB = new JButton("button b");
panel_b.add(btnB);
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
bigPanel.add(panel_a, c);
bigPanel.add(panel_b, c);
c.weighty = 1.0;
// Temporary panel to fill the rest of the bigPanel
bigPanel.add(new JPanel(), c);
this.add(bigPanel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TestGUI gui = new TestGUI();
gui.pack();
gui.setVisible(true);
}
});
}
}

Java GridBagLayout

I've been tasked with designing a basic UI in Java using Swing but I'm stuck with laying it out. I want to create something similar to this but my attempts at using GridBagLayout have resulted in something very messy. Can anyone offer some tips on how I can lay out my GUI like this?
I have a JTabbedPane to which I add two tabs, and to each of those two tabs I add a JPanel containing my controls.
I would recommend that
the overall GUI use BorderLayout,
the JTable be in a JScrollPane and this should be placed BorderLayout.CENTER.
The top JPanel holding labels, fields, and buttons be placed BorderLayout.PAGE_START.
The top JPanel also can use BorderLayout and can hold the buttons in the BorderLayout.PAGE_END position.
The buttons would be held by a GridLayout(1, 0, x, 0) using JPanel where x is the gap between buttons
The labels and JTextFields be in a JPanel that uses GridBagLayout and that is placed in the top JPanel in the BorderLayout.CENTER position.
that you not follow these recommendations blindly but instead that you experiment with and play with different combinations of nested JPanels, each using its own layout.
that you also check out this link
Here's what I would recommend:
Use a JPanel pTextBox with GridLayout(3, 2) to hold all of your labels + textboxes
Use a JPanel pButtons with GridLayout(1, 3) or BoxLayout(horizontal) hold all of your buttons
Use a JPanel pAll with BoxLayout(vertical) to hold pTextBox, pButtons and the Table.
Use struts, glues, and min/max/prefererd sizes to adjust spacing / resizing behaviour.
Also check out: http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html to compare exactly what you are looking for.
There is a component, the JTable, that wants to occupy all the available space in the window. That means that a BorderLayout will be needed, with a JScrollPane that contains the JTable in the BorderLayout.CENTER of that BorderLayout. The other components will be inside another JPanel in the BorderLayout.PAGE_START
In this new JPanel, there is no component that needs to adjust its size vertically, so i don't see the necessity of a BorderLayout. I would compose it with a vertical BoxLayout. Insert in this panel two more, one GridBagLayout for the labels and text fields, and below one FlowLayout for the buttons, with center alignment and some horizontal gap. I prefer FlowLayout insetad of GridLayout for the buttons because if you resize the main panel, with a FlowLayout the buttons will keep the same distance between them.
Here's some code...I couldn't get the JTextFields to display correctly so you'll have to fix that.
Main:
import javax.swing.SwingUtilities;
public class Main {
public static void main(String [] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Panel panel = new Panel();
}
});
}
}
Panel:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
public class Panel extends JPanel{
private JFrame frame;
private JLabel label1;
private JLabel label2;
private JLabel label3;
private JTextField textField1;
private JTextField textField2;
private JTextField textField3;
private JButton button1;
private JButton button2;
private JButton button3;
private JTable table;
public Panel() {
label1 = new JLabel("label1");
label2 = new JLabel("label2");
label3 = new JLabel("label3");
textField1 = new JTextField("textField1", 20);
textField2 = new JTextField("textField2", 20);
textField3 = new JTextField("textField3", 100);
button1 = new JButton("Hello");
button2 = new JButton("Goodbye");
button3 = new JButton("Love");
table = new JTable(20,20);
frame = new JFrame("My application");
frame.setSize(1000, 1000);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setVisible(true);
this.setOpaque(true);
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.weightx = 1;
gc.weighty =1;
gc.fill = GridBagConstraints.NONE;
gc.gridx = 0;
gc.gridy = 0;
// gc.anchor = GridBagConstraints.WEST;
add(label1, gc);
gc.gridx = 2;
gc.gridy = 0;
//gc.anchor = GridBagConstraints.EAST;
add(textField1, gc);
gc.gridx = 0;
gc.gridy = 1;
//gc.anchor = GridBagConstraints.WEST;
add(label2, gc);
gc.gridx = 2;
gc.gridy = 1;
//gc.anchor = GridBagConstraints.EAST;
add(textField2, gc);
gc.gridx = 0;
gc.gridy = 2;
//gc.anchor = GridBagConstraints.WEST;
add(label3, gc);
gc.gridx = 2;
gc.gridy = 2;
//gc.anchor = GridBagConstraints.EAST;
add(textField3, gc);
gc.gridx = 0;
gc.gridy = 3;
//gc.anchor = GridBagConstraints.WEST;
add(button1, gc);
gc.gridx = 1;
gc.gridy = 3;
gc.anchor = GridBagConstraints.CENTER;
add(button2, gc);
gc.gridx = 2;
gc.gridy = 3;
// gc.anchor = GridBagConstraints.EAST;
add(button3, gc);
gc.gridx = 1;
gc.gridy = 4;
gc.anchor = GridBagConstraints.CENTER;
add(table, gc);
frame.add(this);
}
}

Categories