I have this gui; and when the height is not big enough the panes will overlap each other. I have to set it at least 200, so I can completely see the two rows; but when it is set at 200, then I have like a big empty row at the end, and I don't want that. How could I fix this? Thanks.
import java.awt.FlowLayout;
import javax.swing.*;
import java.awt.*;
public class MyFrame extends JFrame {
JButton panicButton;
JButton dontPanic;
JButton blameButton;
JButton newsButton;
JButton mediaButton;
JButton saveButton;
JButton dontSave;
public MyFrame() {
super("Crazy App");
setSize(400, 150);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel row1 = new JPanel();
panicButton = new JButton("Panic");
dontPanic = new JButton("No Panic");
blameButton = new JButton("Blame");
newsButton = new JButton("News");
//adding first row
GridLayout grid1 = new GridLayout(4, 2, 10, 10);
setLayout(grid1);
FlowLayout flow1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
row1.setLayout(flow1);
row1.add(panicButton);
row1.add(dontPanic);
row1.add(blameButton);
row1.add(newsButton);
add(row1);
//adding second row
JPanel row2 = new JPanel();
mediaButton = new JButton("Blame");
saveButton = new JButton("Save");
dontSave = new JButton("No Save");
GridLayout grid2 = new GridLayout(3, 2, 10, 10);
setLayout(grid2);
FlowLayout flow2 = new FlowLayout(FlowLayout.CENTER, 10, 10);
row2.setLayout(flow2);
row2.add(mediaButton);
row2.add(saveButton);
row2.add(dontSave);
add(row2);
setVisible(true);
}
public static void main(String[] args) {
MyFrame frame = new MyFrame();
}
}
The original code set the layout for one panel on two separate occasions. For clarity, set it once in the constructor.
The 2nd layout specified 3 rows
Call pack() on the top-level container to have the GUI reduce to the minum sze needed for the components.
End result
import java.awt.FlowLayout;
import javax.swing.*;
import java.awt.*;
public class MyFrame17 extends JFrame {
JButton panicButton;
JButton dontPanic;
JButton blameButton;
JButton newsButton;
JButton mediaButton;
JButton saveButton;
JButton dontSave;
public MyFrame17() {
super("Crazy App");
setLayout(new GridLayout(2, 2, 10, 10));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel row1 = new JPanel();
panicButton = new JButton("Panic");
dontPanic = new JButton("No Panic");
blameButton = new JButton("Blame");
newsButton = new JButton("News");
FlowLayout flow1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
row1.setLayout(flow1);
row1.add(panicButton);
row1.add(dontPanic);
row1.add(blameButton);
row1.add(newsButton);
add(row1);
//adding second row
JPanel row2 = new JPanel();
mediaButton = new JButton("Blame");
saveButton = new JButton("Save");
dontSave = new JButton("No Save");
FlowLayout flow2 = new FlowLayout(FlowLayout.CENTER, 10, 10);
row2.setLayout(flow2);
row2.add(mediaButton);
row2.add(saveButton);
row2.add(dontSave);
add(row2);
pack();
setVisible(true);
}
public static void main(String[] args) {
MyFrame17 frame = new MyFrame17();
}
}
Further tips
Don't extend frame, just use an instance of one.
Build the entire GUI in a panel which can then be added to a frame, applet, dialog..
When developing test classes, give them a more sensible name than MyFrame. A good word to add is Test, then think about what is being tested. This is about the layout of buttons, so ButtonLayoutTest might be a good name.
GUIs should be started on the EDT.
Related
So I tried to create an empty border and was required to import javax.swing.border.EmptyBorder;
However I had already imported javax.swing.*;
How come I was required to import the prior import? Doesn't the .* import everything from the swing package.
My source code is listed below:
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
/*
public class Gui extends JFrame {
//row1
JPanel row1 = new JPanel();
JButton reset = new JButton("Reset");
JButton play = new JButton("Play");
//row2
JPanel row2 = new JPanel();
JLabel option = new JLabel("Guess: ", JLabel.RIGHT);
JTextField text1 = new JTextField("0");
JTextField text2 = new JTextField("0");
JTextField text3 = new JTextField("0");
//row3
JPanel row3 = new JPanel();
JLabel answerL = new JLabel("Answer: ", JLabel.RIGHT);
JTextField answerB = new JTextField("", 0);
*/
public Gui(){
/* super("Guess My Number");
setSize(500, 800);
GridLayout masterLayout = new GridLayout(4, 1);
setLayout(masterLayout);
FlowLayout layout1 = new FlowLayout(FlowLayout.LEFT);
row1.setLayout(layout1);
row1.add(reset);
row1.add(play);
add(row1);
GridLayout layout2 = new GridLayout(1, 4, 30, 30);
row2.setLayout(layout2);*/
row2.setBorder(new EmptyBorder(0,100,0,200));
/*row2.add(option);
row2.add(text1);
row2.add(text2);
row2.add(text3);
add(row2);
GridLayout layout3 = new GridLayout(1,1, 10, 10);
row3.setLayout(layout3);
row3.add(answerL);
row3.add(answerB);
add(row3);
setVisible(true);
}
public static void main(String[] args){
Gui game = new Gui();
}
}
*/
There's no relationship between nested packages in Java.
javax.swing.* will only import classes directly found in javax.swing, javax.swing.border is considered a different unrelated package altogether from a language standpoint.
I am thoroughly confused. I have a pretty decent understanding of how each layout manger works and what each one is used for, but I'm not understanding what combination of layout managers and JPanels are necessary to make what I need work.
What I am trying to accomplish
I have a top bar, and a bottom bar of a container panel NORTH and SOUTH of a BorderLayout.
Within the Center panel, I want an unknown number of buttons 1 or more. Regardless of how many buttons there are they all need to be the same size, if there are dozens then scrolling should start happening once the buttons pass the window size limit.
What I am getting
Depending on the combination of layout mangers and how many nested JPanels I use and all sorts of trouble shooting, I get one massive button filling the entire CENTER element. I get 2 buttons that are the right size, but spread way apart (gap filling the CENTER space), or I get a dozen buttons that are the right size with no scroll.
I can solve any one of these, but then the other breaks. IE if I get a bunch of correctly sized buttons that properly scroll, then when I replace them with a single button its one massive button. Or if I get a single properly sized button then the larger quantity won't scroll etc.
My Code
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.io.*;
public class TestCode extends JFrame {
private final JFrame frame;
public TestCode(){
frame = new JFrame();
JLabel title = new JLabel("Test Title");
JPanel windowContainer = new JPanel();
JPanel topPanel = new JPanel();
final JPanel middlePanel = new JPanel();
JPanel bottomPanel = new JPanel();
JButton searchButton = new JButton("Search");
JButton browseButton = new JButton("Browse...");
JButton testButton = new JButton("Button 1");
JButton exitButton = new JButton("Exit");
final JTextField searchBar = new JTextField("Search database...");
topPanel.setLayout(new GridLayout(2,0));
topPanel.add(title);
title.setHorizontalAlignment(JLabel.CENTER);
topPanel.setPreferredSize(new Dimension(getWidth(), 100));
// This is a subset of the top section. Top part is two panels, bottom panel is two cells (grid)
JPanel topPanelSearch = new JPanel();
topPanelSearch.setLayout(new GridLayout(0,2));
topPanelSearch.add(searchBar);
topPanelSearch.add(searchButton);
topPanel.add(topPanelSearch);
// PROBLEM AREA STARTS
// middlePanel.setLayout(new FlowLayout());
middlePanel.setLayout(new GridLayout(0, 1, 10, 10));
// middlePanel.setLayout(new BoxLayout(middlePanel, BoxLayout.PAGE_AXIS));
JPanel innerContainer = new JPanel();
innerContainer.setLayout(new BoxLayout(innerContainer, BoxLayout.PAGE_AXIS));
// innerContainer.setLayout(new FlowLayout());
// innerContainer.setLayout(new GridLayout(0, 1, 10, 10));
for(int i = 0; i < 2; i++){
JButton button = new JButton("Button ");
button.setPreferredSize(new Dimension(400, 100));
JPanel test = new JPanel();
test.add(button);
innerContainer.add(test);
}
JScrollPane midScroll = new JScrollPane(innerContainer);
middlePanel.add(midScroll);
// PROBLEM AREA ENDS
bottomPanel.setLayout(new GridLayout(0, 3));
bottomPanel.setPreferredSize(new Dimension(getWidth(), 100));
bottomPanel.add(testButton);
bottomPanel.add(browseButton);
bottomPanel.add(exitButton);
windowContainer.setLayout(new BorderLayout());
windowContainer.add(topPanel, BorderLayout.NORTH);
windowContainer.add(middlePanel, BorderLayout.CENTER);
windowContainer.add(bottomPanel, BorderLayout.SOUTH);
frame.add(windowContainer);
frame.setTitle("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(480, 800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args){
TestCode test = new TestCode();
}
}
Visual of some of the fail results
I want the leftmost picture, but buttons should be stacked neatly (like the middle picture) when there are only a few results, and scrollable when there are lots.
What am I doing wrong?
Try with GridBagLayout and a filler component that takes the remaining vertical space and therefore forces the buttons upwards.
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.Box.Filler;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class GridbagButtons extends JFrame {
private final JScrollPane jscrpButtons;
private final JPanel jpButtons;
public GridbagButtons() {
setLayout(new BorderLayout());
jpButtons = new JPanel(new GridBagLayout());
jscrpButtons = new JScrollPane(jpButtons);
add(jscrpButtons, BorderLayout.CENTER);
// add a custom number of buttons
int numButtons = 10;
for (int i = 0; i < numButtons; i++) {
JButton jbButton = new JButton("Button");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = i;
jpButtons.add(jbButton, gbc);
}
// add a vertical filler as last component to "push" the buttons up
GridBagConstraints gbc = new GridBagConstraints();
Filler verticalFiller = new Filler(
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, Integer.MAX_VALUE));
gbc.gridx = 0;
gbc.gridy = numButtons;
gbc.fill = java.awt.GridBagConstraints.VERTICAL;
gbc.weighty = 1.0;
jpButtons.add(verticalFiller, gbc);
setSize(300, 200);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GridbagButtons().setVisible(true);
}
});
}
}
hello goodevening to all i have a problem on my program with the ScrollPane in my JList i cant put an JScrollPane in my list because i am using a panel instead of Container this is my code so far its all runnable the problem is if you enter a high number in the number of times the some output will not be able to see because of the size of my list . so this is the code
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MultCen extends JFrame implements ActionListener
{
public static void main(String args [])
{
MultCen e = new MultCen();
e.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
e.setVisible(true);
e.setSize(300,450);
}
JTextField t1 = new JTextField();
JTextField t2 = new JTextField();
JButton b = new JButton("Okay");
JButton c = new JButton("Clear");
JList list = new JList();
JLabel lab = new JLabel();
DefaultListModel m = new DefaultListModel();
public MultCen()
{
JPanel panel = new JPanel();
panel.setLayout(null);
JLabel l = new JLabel("Enter a number :");
JLabel l1 = new JLabel("How many times :");
l.setBounds(10,10,130,30);
l1.setBounds(10,40,130,30);
t1.setBounds(140,10,130,25);
t2.setBounds(140,40,130,25);
b.setBounds(60,90,75,30);
c.setBounds(150,90,75,30);
list.setBounds(30,140,220,220);
panel.add(t1);
panel.add(t2);
panel.add(l);
panel.add(l1);
panel.add(list);
panel.add(b);
panel.add(c);
getContentPane().add(panel);
b.addActionListener(this);
c.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == b)
{
int t3 = Integer.parseInt(t1.getText());
int t4 = Integer.parseInt(t2.getText());
m.addElement("The multiplication Table of "+t3);
for (int cc =1 ; cc <=t4; cc++ )
{
lab.setText(t3+"*"+cc+" = "+(t3*cc));
m.addElement(lab.getText());
list.setModel(m);
}
}
if(e.getSource() == c)
{
t1.setText("");
t2.setText("");
m.removeAllElements();
}
}
}
JScrollPane does not work with null Layout. Use BoxLayout or any other resizeable layout instead. This is the limitation of setLayout(null).
Use Layout managers. You've asked a lot of questions here and I'm sure a few you have been advised not to use null layout. Again here is the tutorial Laying out components Within a container. Learn to use them so you don't run into the million possible problems on the road ahead. This kind of problem being one of them.
here's an example of how you could achieve the same thing with layout managers, and some empty borders for white space.
With Layout Manager
Without Layout Manger
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MultCen extends JFrame {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MultCen e = new MultCen();
e.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
e.setVisible(true);
e.pack();
}
});
}
JTextField t1 = new JTextField(10);
JTextField t2 = new JTextField(10);
JButton b = new JButton("Okay");
JButton c = new JButton("Clear");
JLabel lab = new JLabel();
DefaultListModel m = new DefaultListModel();
public MultCen() {
JPanel topPanel = new JPanel(new GridLayout(2, 2, 0, 5));
JLabel l = new JLabel("Enter a number :");
JLabel l1 = new JLabel("How many times :");
topPanel.add(l);
topPanel.add(t1);
topPanel.add(l1);
topPanel.add(t2);
JPanel buttonPanel = new JPanel();
buttonPanel.add(b);
buttonPanel.add(c);
buttonPanel.setBorder(new EmptyBorder(10, 0, 10, 0));
JList list = new JList();
JScrollPane scroll = new JScrollPane(list);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroll.setPreferredSize(new Dimension(300, 300));
JPanel panel = new JPanel(new BorderLayout());
panel.add(topPanel, BorderLayout.NORTH);
panel.add(buttonPanel, BorderLayout.CENTER);
panel.add(scroll, BorderLayout.SOUTH);
panel.setBorder(new EmptyBorder(10, 15, 10, 15));
getContentPane().add(panel);
}
}
Side Notes
Run Swing apps from the Event Dispatch Thread. See Initial Threads
When you do decide to use layout managers, just pack() your frame instead of setSize()
Use better variable names.
See Extends JFrame vs. creating it inside the the program
I'm trying to use a grid layout to make a GUI window. I add all my components and it compiles but when it runs it doesn't show anything. I'm trying to make a simple layout grouped and stacked like this.
{introduction message}
{time label
time input text}
{gravity label
gravity input text}
{answer label
answer text box}
{calculate button clear button}
Here is my code
import javax.swing.*;
import java.awt.*;
public class TurnerRandyFallingGUI extends JFrame
{
final int WINDOW_HEIGHT=500;
final int WINDOW_WIDTH=500;
public TurnerRandyFallingGUI()
{
setTitle("Falling Distance Calculator");
setSize(WINDOW_WIDTH,WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(1, 5));
//labels
JLabel introMessage = new JLabel("Welcome to the Falling distance"+
"calculator");
JLabel timeLabel = new JLabel("Please enter the amount of time "+
"in seconds the object was falling.");
JLabel gravityLabel = new JLabel("Enter the amount of gravity being "+
"forced onto the object");
JLabel answerLabel = new JLabel("Answer");
//text fields
JTextField fTime = new JTextField(10);
JTextField gForce = new JTextField(10);
JTextField answerT = new JTextField(10);
//buttons
JButton calculate = new JButton("Calculate");
JButton clr = new JButton("clear");
//panels
JPanel introP = new JPanel();
JPanel timeP = new JPanel();
JPanel gravityP = new JPanel();
JPanel answerP = new JPanel();
JPanel buttonsP = new JPanel();
//adding to the panels
//intro panel
introP.add(introMessage);
//time panel
timeP.add(timeLabel);
timeP.add(fTime);
//gravity panel
gravityP.add(gravityLabel);
gravityP.add(gForce);
//answer panel
answerP.add(answerLabel);
answerP.add(answerT);
//button panel
buttonsP.add(calculate);
buttonsP.add(clr);
setVisible(true);
}
public static void main(String[] args)
{
new TurnerRandyFallingGUI();
}
}
You've added nothing to the JFrame that your class above extends. You need to add your components to containers whose hierarchy eventually leads to the top level window, to the this if you will. In other words, you have no add(someComponent) or the functionally similar this.add(someComponent)method call in your code above.
Consider adding all of your JPanels to a single JPanel
Consider adding that JPanel to the JFrame instance that is your class by calling add(thatJPanel).
Even better would be to not extend JFrame and just to create one when needed, but that will likely be the subject of another discussion at another time.
Before setVisible (true) statement add following statements:
add (introP);
add (timeP);
add (gravityP);
add (answerP);
add (buttonsP);
There is nothing in your JFrame. That is the reason
import javax.swing.*;
import java.awt.*;
public class TurnerRandyFallingGUI extends JFrame
{
final int WINDOW_HEIGHT=500;
final int WINDOW_WIDTH=500;
public TurnerRandyFallingGUI()
{
//labels
JLabel introMessage = new JLabel("Welcome to the Falling distance"+
"calculator");
JLabel timeLabel = new JLabel("Please enter the amount of time "+
"in seconds the object was falling.");
JLabel gravityLabel = new JLabel("Enter the amount of gravity being "+
"forced onto the object");
JLabel answerLabel = new JLabel("Answer");
//text fields
JTextField fTime = new JTextField(10);
JTextField gForce = new JTextField(10);
JTextField answerT = new JTextField(10);
//buttons
JButton calculate = new JButton("Calculate");
JButton clr = new JButton("clear");
//panels
JPanel introP = new JPanel();
JPanel timeP = new JPanel();
JPanel gravityP = new JPanel();
JPanel answerP = new JPanel();
JPanel buttonsP = new JPanel();
//adding to the panels
//intro panel
introP.add(introMessage);
//time panel
timeP.add(timeLabel);
timeP.add(fTime);
//gravity panel
gravityP.add(gravityLabel);
gravityP.add(gForce);
//answer panel
answerP.add(answerLabel);
answerP.add(answerT);
//button panel
buttonsP.add(calculate);
buttonsP.add(clr);
setLayout(new GridLayout(5, 1));
this.add(introP);
this.add(timeP);
this.add(gravityP);
this.add(answerP);
this.add(buttonsP);
setTitle("Falling Distance Calculator");
this.pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.validate();
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TurnerRandyFallingGUI();
}
});
}
}
Consider the following
In GridLayout, the first parameter is Rows, Second is columns
Never set the size of JFrame manually. Use pack() method to decide
the size
Use SwingUtilities.InvokeLater() to run the GUI in another thread.
When I run this program, the window blocks out the buttons in panel2 when I use setSize to determine window size.
In addition, if I use frame.pack() instead of setSize(), all components are on one horizontal line but I'm trying to get them so that panel1 components are on one line and panel2 components are on a line below them.
Could someone explain in detail the answers to both of these problems?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Exercise16_4 extends JFrame{
// FlowLayout components of top portion of calculator
private JLabel jlbNum1 = new JLabel("Number 1");
private JTextField jtfNum1 = new JTextField(4);
private JLabel jlNum2 = new JLabel("Number 2");
private JTextField jtfNum2 = new JTextField(4);
private JLabel jlbResult = new JLabel("Result");
private JTextField jtfResult = new JTextField(8);
// FlowLayout Components of bottom portion of calculator
private JButton jbtAdd = new JButton("Add");
private JButton jbtSubtract = new JButton("Subtract");
private JButton jbtMultiply = new JButton("Multiply");
private JButton jbtDivide = new JButton("Divide");
public Exercise16_4(){
JPanel panel1 = new JPanel();
panel1.setLayout(new FlowLayout(FlowLayout.CENTER, 3, 3));
panel1.add(jlbNum1);
panel1.add(jtfNum1);
panel1.add(jlNum2);
panel1.add(jtfNum2);
panel1.add(jlbResult);
panel1.add(jtfResult);
JPanel panel2 = new JPanel();
panel2.setLayout(new FlowLayout(FlowLayout.CENTER, 3, 10));
panel1.add(jbtAdd);
panel1.add(jbtSubtract);
panel1.add(jbtMultiply);
panel1.add(jbtDivide);
add(panel1, BorderLayout.NORTH);
add(panel2, BorderLayout.CENTER);
}
public static void main(String[] args){
Exercise16_4 frame = new Exercise16_4();
frame.setTitle("Caculator");
frame.setSize(400, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setResizable(false);
frame.setVisible(true);
}
}
You're problem is likely a typographical error in that you're adding all components to panel1 and none to panel2:
// you create panel2 just fine
JPanel panel2 = new JPanel();
panel2.setLayout(new FlowLayout(FlowLayout.CENTER, 3, 10));
// but you don't use it! Change below to panel2.
panel1.add(jbtAdd);
panel1.add(jbtSubtract);
panel1.add(jbtMultiply);
panel1.add(jbtDivide);
Add the buttons to panel2, and then call pack() before setVisible(true). Do not set the size of the GUI.