so I have this problem. I wrote this code in Java Eclipse SDK 4.2.1. I haven't wrote it all here, actionPerformed method is irrelevant now and it is called from Main once. The problem is sometimes when I run it, one of the components just fills the whole window and overlaps all others. I tried changing sizes by random numbers for example from 400 to 350 and sometimes it worked and then it broke again. I'm probably missing something, I just don't know what. I searched other forums, but found nothing about it.
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class Window extends JFrame implements ActionListener
{
JTextField field1;
JTextField field2;
public Window()
{
super("Main Window");
setVisible(true);
setSize(500, 500);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Initialize();
}
private void Initialize()
{
field1 = new JTextField();
field2 = new JTextField();
field1.setBounds(0, 0, 400, 100);
field2.setBounds(0,100,400,100);
add(field1);
add(field2);
field1.setBackground(Color.PINK);
field1.setForeground(Color.RED);
field2.setBackground(Color.PINK);
field2.setForeground(Color.RED);
JButton button = new JButton("Create");
button.setBounds(0, 200, 400, 100);
add(button);
button.setBackground(Color.BLACK);
button.setForeground(Color.YELLOW);
button.addActionListener(this);
}
Your problem is that your code does not respect the layout manager being used as you're trying to add components as if the layout being used were null when in fact it isn't. The solution is to read up on and learn about layout managers, and use them; this includes avoiding calling setBounds(...). Note that a JFrame's contentPane uses BorderLayout by default. This information should help you get started. Also note that a wrong solution is to use a null layout. So if anyone suggests this, I urge you to ignore them.
Related
I am writing a small program just for personal use to double check strategies on a mobile based game. I created a Board class and frame and whatnot, then I created a new Panel class in my package (I use Eclipse). I figured it would be as simple as creating the two and implementing the Panel and adding it to the main frame of the Board class. Alas, I was mistaken.
TubePanel - my secondary panel
package ballSort;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
import javax.swing.JLabel;
public class TubePanel extends JPanel {
/**
* Create the panel.
*/
public TubePanel() {
setBackground(new Color(47, 79, 79));
setBounds(10, 10, 30, 40);
}
}
**This is an excerpt from my main Board class.... **
panel_1 = new JPanel();
panel_1.setBounds(118, 164, 726, 466);
frame.getContentPane().add(panel_1);
JButton btnNewButton_1 = new JButton("X");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
});
btnNewButton_1.setFont(new Font("Tahoma", Font.PLAIN, 89));
btnNewButton_1.setBounds(10, 122, 85, 124);
frame.getContentPane().add(btnNewButton_1);
}
public void Create(int tubes) {
TubePanel tube = new TubePanel();
panel_1.add(tube);
System.out.println(tube);
System.out.println(panel_1);
}
Am I the idiot here? This should've worked, as far as I'm concerned, but clearly I know not the ways of the Java. [Only been coding java for 4 years.] Anyway the problem is that it doesn't show the tubePanel.
It doesn't give any errors either so I had to use Sysout to see if there was anything wrong with it and panel_1 for a comparison...
ballSort.TubePanel[,10,10,30x40,**invalid**,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
javax.swing.JPanel[,118,164,726x466,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
Aside from the invalid (to which I tried to follow it to its root, I couldn't figure it out) there's nothing different from panel_1 compared to tube.
Any help is much appreciated.
Refer to the lesson entitled Laying Out Components Within a Container from trail Creating a GUI With JFC/Swing which is part of Oracle's Java tutorials.
The default layout of the content pane of a JFrame is BorderLayout. When you add a component to the content pane, it gets added to the center area of the BorderLayout. The center area (and all other areas) of BorderLayout can only contain a single component. So when you add two components to the center area, only one will be displayed. Refer to method add(Component, Object) in class java.awt.Container
So study the layout managers and decide which is suitable.
I'm a geek and I have started learning Java this year. I have a problem at next code: the program is running but, unfortunately, don't want to stop and to show my window with buttons. I don't understand, way? Please, give me some ideas, I have tried all, but in vain!
package arbitru;
import java.awt.FlowLayout;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
public class TogleButon {
public static void main(String[] args) {
JFrame window=new JFrame("Name");
JPanel Panou=(JPanel) window.getContentPane();
Panou.setLayout(new FlowLayout());
JToggleButton button1=new JToggleButton("Button 1", true);
Panou.add(button1);
JToggleButton button2=new JToggleButton("Button 2", false);
Panou.add(button2);
JToggleButton button3=new JToggleButton("Button 3", false);
Panou.add(button3);
ButtonGroup Group_button=new ButtonGroup();
Group_button.add(button1);
Group_button.add(button2);
Group_button.add(button3);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
A quick fix for your problem is to call pack() before calling setVisible().
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack(); // Add this line.
window.setVisible(true);
The method pack() will size the JFrame such that it is big enough to display its contained components at their preferred sizes.
Nonetheless you should be aware that your code is not good. You shouldn't construct your GUI in the main() method. For learning Swing I recommend Creating a GUI With JFC/Swing
I have tried setLocation(x,y) and setLocationRelativeTo(null) by setting Layout of JFrame as null but that didn't work out.While searching I found this questions being already asked by two or three people but they have done through setLocation() and setLocationRelativeTo(null).
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.FlowLayout;
public class StartMenu{
JPanel startPanel;
JLabel title;
JButton startTest;
JButton exit;
JFrame menuFrame;
public StartMenu(){
menuFrame = new JFrame("Start Menu");
menuFrame.setLayout(null);
startPanel = new JPanel();
title = new JLabel("Adaptive Test",JLabel.CENTER);
title.setLocation(20,20);
startPanel.add(title);
startTest = new JButton("Start");
startTest.setLocation(40,40);
startPanel.add(startTest);
exit = new JButton("Exit");
exit.setLocation(100,100);
startPanel.add(exit);
menuFrame.setContentPane(startPanel);
menuFrame.setVisible(true);
menuFrame.setSize(500, 500);
menuFrame.setResizable(false);
menuFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Your JFrame's layout is set to null, but the startPanel's one is not. So first of all, use:
startPanel.setLayout(null);
Now, instead of component.setLocation(x, y), use component.setBounds(x, y, width, height), so you also set a size for them.
But as has been said in the comments, it would be preferable to use layout managers instead of null layout.
First you set to null the JFrame istead of the JPanel, so you have to use
startPanel.setLayout(null);
then you should use setBounds istead of setLocation becouse if you just set the location with a null layout manager you'll probably will see nothing on your panel, becouse all dimensions are initialized to 0 by default.
so, you can rewrite your software like this:
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class StartMenu{
JPanel startPanel;
JLabel title;
JButton startTest;
JButton exit;
JFrame menuFrame;
public StartMenu(){
menuFrame = new JFrame("Start Menu");
menuFrame.setLayout(null);
startPanel = new JPanel();
startPanel.setLayout(null);
title = new JLabel("Adaptive Test",JLabel.CENTER);
title.setBounds(20,20, 100, 30);
startPanel.add(title);
startTest = new JButton("Start");
startTest.setBounds(50,50, 100, 30);
startPanel.add(startTest);
exit = new JButton("Exit");
exit.setBounds(100,100, 100 ,30);
startPanel.add(exit);
menuFrame.setContentPane(startPanel);
menuFrame.setVisible(true);
menuFrame.setSize(500, 500);
menuFrame.setResizable(false);
menuFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Like this you get something working but it isn't a very good programming practice to set by hand all the location and sizes in your software becouse it will not work good on different systems (thus it will not be portable) and you will also find yourself in a debugging nightmare when your software will start growing with tens if not hundreds of graphics elements.
My suggestion is to use the gridBagLayout, it me seem obscure at first, but trust me, it's not so!
I am trying to create a simple JFrame menu where there is a nice background, which works, along with some text. The text is a bit buggy. Here is how it looks (http://imgur.com/nRpzA30)
As you can see, only one line of the text appears not the second line.
Along with that. Two GUI's appear when I run the program. One is completley empty, and one looks like the picture above.
Finally I can't use the method logo.setHorizontalAlignment(JLabel.NORTH); without getting an error, same with a few others. The two I tested and worked were only .CENTER, and .LEFT.
Any help would be great!
Oh and almost forgot, here's my code :)
package character;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
/**
* Created by Niknea on 6/28/14.
*/
public class characterSelector extends JFrame{
JPanel cselectorText;
JFrame cselectorButtons;
JLabel logo, characterName, label;
JButton previous, next;
public characterSelector(String title){
super(title);
this.createCharacterSelector();
this.setSize(1920, 1033);
this.setResizable(true);
this.setVisible(true);
}
public void createCharacterSelector(){
try {
label = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/resources/Grass_Background.jpg"))));
cselectorButtons = new JFrame();
logo = new JLabel("SoccerKidz [REPLACE W/ COOL LOGO]");
characterName = new JLabel("<Character Name>");
logo.setPreferredSize(new Dimension(50, 50));
logo.setFont(new Font(logo.getFont().getName(), Font.HANGING_BASELINE, 50));
characterName.setFont(new Font(characterName.getFont().getName(), Font.HANGING_BASELINE, 50));
cselectorButtons.add(logo);
cselectorButtons.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cselectorButtons.setContentPane(label);
cselectorButtons.setLayout(new BorderLayout());
characterName.setForeground(Color.CYAN);
characterName.setHorizontalAlignment(JLabel.CENTER);
cselectorButtons.add(characterName);
logo.setForeground(Color.CYAN);
logo.setHorizontalAlignment(JLabel.LEFT);
cselectorButtons.add(logo);
cselectorButtons.pack();
cselectorButtons.setLocationRelativeTo(null);
cselectorButtons.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
Thanks again! :)
As you can see, only one line of the text appears not the second line.
You set the layout of cselectorButtons to BorderLayout. Then you add JLabel("<Character Name>");, which is fine. But then you add JLabel("SoccerKidz [REPLACE W/ COOL LOGO]");. Here's what's happening. With BorderLayout, when you just add(component), generally you want to specify a BorderLayout.[POSITION] as the second argument to the add. If you don't, every component that you add, without the position specified, will be added the the BorderLayout.CENTER implicitly by default. The problem with this is each position can only have one component. So in your case, the first label gets kicked out the center, only showing the second one you added.
Two GUI's appear when I run the program. One is completley empty, and one looks like the picture above.
When look at your code. Your class is a JFrame in which you add nothing to, and this.setVisible(true). And also you a JFrame cselectorButtons; in which you do add components and also cselectorButtons.setVisible(true);. Can you guess which one is the one you're seeing that's not empty. Don't extends JFrame. Just use the instance one you currently are using.
Finally I can't use the method logo.setHorizontalAlignment(JLabel.NORTH); without getting an error.
It doesn't take much to take a look at the API for JLabel. That being said, what makes you think aligning something horizontally, should include an option to position to the north. Doesn't make sense
public void setHorizontalAlignment(int alignment)
Sets the alignment of the label's contents along the X axis.
Parameters:
alignment - One of the following constants defined in SwingConstants: LEFT, CENTER (the default for image-only labels), RIGHT, LEADING (the default for text-only labels) or TRAILING.
I suggest you take a look at Layout out Components Within a Container and A Visual Guide to Layout Managers for other possibly layout managers you can use, if BorderLayout doesn't suit you. Also keep in mind you can nest different panels with different layout managers to get your desired result. But first you need to learn how they work.
UPDATE
I made some changes, which works. I'm also looking at your pastebin code, and can't really see any difference. You may want to investigate my code to try and look for differences
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* Created by Niknea on 6/28/14.
*/
public class CharacterSelector {
JPanel cselectorText;
JFrame cselectorButtons;
JLabel logo, characterName, label;
JButton previous, next;
public CharacterSelector() {
createCharacterSelector();
}
public void createCharacterSelector() {
try {
label = new JLabel(new ImageIcon(ImageIO.read(getClass()
.getResource("/resources/Grass_Background.jpg"))));
cselectorButtons = new JFrame();
logo = new JLabel("SoccerKidz [REPLACE W/ COOL LOGO]");
characterName = new JLabel("<Character Name>");
logo.setPreferredSize(new Dimension(50, 50));
logo.setFont(new Font(logo.getFont().getName(),
Font.HANGING_BASELINE, 50));
characterName.setFont(new Font(characterName.getFont().getName(),
Font.HANGING_BASELINE, 50));
cselectorButtons.add(logo);
cselectorButtons.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cselectorButtons.setContentPane(label);
cselectorButtons.setLayout(new BorderLayout());
characterName.setForeground(Color.CYAN);
characterName.setHorizontalAlignment(JLabel.CENTER);
cselectorButtons.add(characterName);
logo.setForeground(Color.CYAN);
logo.setHorizontalAlignment(JLabel.LEFT);
cselectorButtons.add(logo, BorderLayout.NORTH);
cselectorButtons.pack();
cselectorButtons.setLocationRelativeTo(null);
cselectorButtons.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new CharacterSelector();
}
});
}
}
I'm trying to design a JButton (an "Ok" button) that to look good has to be horizontally centered in the containing JFrame.
I'm using the GUI Builder with the Free Form layout (GroupLayout).
I've taken several GUI builder tutorials (http://netbeans.org/kb/docs/java/quickstart-gui.html) but haven't found this topic. In other gui builders (delphi) this can be done by removing the anchors from both edges.
GroupLayout does support centering of components. It is a very capable
layout manager. I personally put it after the MigLayout manager and before
the FormLayout manager.
In the following three examples, we have a panel and a button. The button
is horizontally centered.
Centering with NetBeans Builder
To center a component using a Netbeans Builder, we need to create
horizontal resizable gaps from both sides of the button.
The green area of the screenshot is a currently selected gaps. The strings
inside the gaps suggest that it is a resizable gap.
The gaps are automatically added when we place components on the form.
To define a gap to be resizable, we right click on the gap and select
the "Edit Layout Space" option. We get the following dialog:
To get a resizable gap, we check the Resizable check box.
Centering manually by using a parallel group
Components can be centered in the parallel group by passing
the GroupLayout.Alignment.CENTER parameter.
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.CENTER;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GroupLayoutCenter extends JFrame {
public GroupLayoutCenter() {
initUI();
setTitle("Centered button");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateGaps(true);
gl.setAutoCreateContainerGaps(true);
JPanel pnl = new JPanel();
pnl.setBorder(BorderFactory.createEtchedBorder());
JButton btn = new JButton("Button");
gl.setHorizontalGroup(gl.createParallelGroup(CENTER)
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addComponent(btn)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addComponent(btn)
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GroupLayoutCenter ex = new GroupLayoutCenter();
ex.setVisible(true);
}
});
}
}
Centering manually by using gaps
This solution is what NetBeans generated code does. We place
two resizable gaps to the left and right sides of the button.
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GroupLayoutCenter2 extends JFrame {
public GroupLayoutCenter2() {
initUI();
setTitle("Centered button");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateGaps(true);
gl.setAutoCreateContainerGaps(true);
JPanel pnl = new JPanel();
pnl.setBorder(BorderFactory.createEtchedBorder());
JButton btn = new JButton("Button");
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addGroup(gl.createSequentialGroup()
.addGap(5, 100, Short.MAX_VALUE)
.addComponent(btn)
.addGap(5, 100, Short.MAX_VALUE))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addComponent(btn)
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GroupLayoutCenter2 ex = new GroupLayoutCenter2();
ex.setVisible(true);
}
});
}
}
If you want your component to remain centered in its container if the container is resized, you have several options available to you, but I don't think that GroupLayout is one of them (please correct me if I'm wrong). One way is to change the container's layout to GridBagLayout, and then simply add the JButton into it without any constraints.
Try GridbagLayout See this
Try another LayoutManager!
GroupLayout is very obscure when just looking at the code generated by NetBeans.
If you used DesignGridLayout then what you need is as simple as:
DesignGridLayout layout = new DesignGridLayout(container);
layout.row().center().add(okButton);
javax.swing.Box.Filler can be used to pad space around a component inside a GroupLayout. In NetBeans Matisse (GUI Builder) they're called 'Horizontal Strut' under the 'Swing Fillers' section of the palette. Just put one on either side of your button, size them to fill all the empty space between the button and the edge of the container, and make sure they're both flagged to Auto Resize Horizontally.
As for using another LayoutManager, I know people don't like GroupLayout because it is not conducive to manual coding. That is by design. As the docs say, GroupLayout is intended to be used by GUI builders. So as long as you're ok with tying yourself to using NetBeans & Matisse for the life of your GUI, GroupLayout is really the best option.