JFrame adding Text not working. Two GUI appear - java

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();
}
});
}
}

Related

JTextBox and all following JComponents don't show up

I want do design a simple login format and in order to do so I want two JTextFields for Username/Password and a Login Button. The Login button is display as expected but when I add the JTextField, nothing shows in my JFrame. Would be nice if someone could help a beginner out...
Here's my code (I know it's ugly but this is just a "code sketch"):
package bucketlistpackage;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GameFrame extends JFrame {
public GameFrame(String title) {
super(title); //sets title of frame
startFrame(); //sets details of main frame
final Container logincont = getContentPane(); //creates content pane
JFrame loginframe = new JFrame();
usernameField(loginframe);
loginButton(loginframe);
logincont.add(loginframe);
}
private void usernameField(JFrame loginframe) {
JTextField usernameF = new JTextField("Username", 1);
usernameF.setBounds(50, 50, 50, 20);
loginframe.add(usernameF);
usernameF.setVisible(true);
}
private void startFrame() {
this.setSize(1000, 1000);
this.setVisible(true);
}
private void loginButton(Container cont) {
JButton loginB = new loginButton();
loginB.setSize(300, 150);
loginB.setText("Login");
cont.add(loginB);
}
}
The problem lies on how you are adding component to one another in your case.
You are adding a JFrame to a Container, when in all case it should be the other way around.
The other problem is that you are not using Layouts to manage the components positions on the JFrame.
Another problem as well is that you are not refreshing the windows after adding all the stuff on it.
A bit of a resume on how Java works with native UIs:
Java creates a new thread for the UI. So if you open the debugger you will see AWT threads as well as the main threads and others. This means that you have to manage this in a correct way, because after the application starts SWING and the functions you determine for reactions will lay the ground on how it will behave. Your main thread will die, but the visual threads will keep active.
If you are just starting to program I would encourage you to practice a bit more native java language before moving to SWING or AWT. This libraries can be really painful and tricky to use.
The other thing is SWING library follows a hierarchy for the components:
JFrame > JPanels > Components
In your code you have already worked with all of them but in a disorganized way. JFrame is the main application window, where the graphics will be displayed (can also be a Canvas or whatever class you want to use for that matter). JPanels are organizers, you can use different layouts to organize whatever is inside it. And finally the Components are well... everything! A component can be a JTextField, but it can also be a JPanel, or JButton.
The idea with SWING is to create multiple Panels and organize the end components inside them, using the help of the different layouts to see whats the best approach to make them attractive in many different window sizes.
Finally, if you are using Eclipse, there is a plugin called WindowBuilder which might help you. I don't recommend you using it if you are very new to Java since it will make you depend a lot on it instead of learning how to actually code with SWING.
Hope this helps!!!
Btw, to fix the code above I would do something like this:
public GameFrame(String title) {
super(title); //sets title of frame
startFrame(); //sets details of main frame
final Container logincont = getContentPane(); //creates content pane
logincont.setLayout(new BorderLayout());
usernameField(logincont, BorderLayout.NORTH);
loginButton(logincont, BorderLayout.CENTER);
this.revalidate();
this.repaint();
}
private void usernameField(Container loginframe, String direction) {
JTextField usernameF = new JTextField("Username");
// usernameF.setBounds(50, 50, 50, 20);
loginframe.add(usernameF, direction);
usernameF.setVisible(true);
}
private void startFrame() {
this.setSize(1000, 1000);
this.setVisible(true);
}
private void loginButton(Container cont, String direction) {
JButton loginB = new JButton();
loginB.setSize(300, 150);
loginB.setText("Login");
cont.add(loginB, direction);
}

Java swing - wrong size

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.

Java swing JComponent "size"

I'm doing a project where i need some custom swing components. So far I have made a new button with a series of images (the Java Metal look doesn't fit with my UI at all). Ive implemented MouseListener on this new component and this is where my problem arises. My widget changes image on hover, click etc except my MouseListener picks up mouse entry into a the entire GridLayout container instead of into the image. So I have an image of about 200*100 and the surrounding container is about 400*200 and the mouseEntered method is fired when it enters that GridLayout section (even blank space parts of it) instead of over the image. How can I make it so that it is only fired when I hover over the image? Ive tried setting size and bounds and other attributes to no avail.
EDIT: Here's a demonstration of my issue. As you can see (sort of, colors are very similar) the bottom right button is highlighted just by entering its section of the GridlLayout. I only want it highlighted when I'm over the image actual, not the GridLayout section.
I Won't add the MouseListener methods because they just involve switching the displayed image.
public customWidget()
{
this.setLayout(new FlowLayout());
try {
imageDef=ImageIO.read(new File("/home/x101/Desktop/buttonDef.png"));
imageClick=ImageIO.read(new File("/home/x101/Desktop/buttonClick.png"));
imageHover=ImageIO.read(new File("/home/x101/Desktop/buttonHover.png"));
current=imageDef;
} catch (IOException e)
{
e.printStackTrace();
}
this.addMouseListener(this);
}
protected void paintComponent(Graphics g)
{
super.paintComponents(g);
g.drawImage(current, 0, 0, current.getWidth(), current.getHeight(), null);
}
EDIT: added code section
As an alternative, consider the The Button API, which includes the method setRolloverIcon() "to make the button display the specified icon when the cursor passes over it."
Addendum: For example,
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ButtonIconTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
private static void createAndShowGui() {
String base = "http://download.oracle.com/"
+ "javase/tutorial/uiswing/examples/components/"
+ "RadioButtonDemoProject/src/components/images/";
ImageIcon dog = null;
ImageIcon pig = null;
try {
dog = new ImageIcon(new URL(base + "Dog.gif"));
pig = new ImageIcon(new URL(base + "Pig.gif"));
} catch (MalformedURLException ex) {
ex.printStackTrace(System.err);
return;
}
JFrame frame = new JFrame("Rollover Test");
JPanel panel = new JPanel();
panel.add(new JLabel(dog));
panel.add(new JLabel(pig));
JButton button = new JButton(dog);
button.setRolloverIcon(pig);
panel.add(button);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
I assume your image contains ONLY 4 'customWidget' objects (in a 2x2 grid).
Your code is working as I would expect. Your MouseListener methods are responding to MouseEvents for 'customWidget' (not the image drawn in 'customWidget'), which is sized to take up 1/4 of the image, so they will respond when it enters the enlarged area. The error is actually in your Test program, because you are allowing the custom button widget to be larger than the image.
If you want a Test program that provides an image similar to yours, you should create a larger grid (say 4x4), and then only place your buttons in every other grid node. Place an empty component into the gaps.
Although I won't answer to your particular question, I hope this helps:
If the components just look wrong maybe you should reuse Swing components and just write a custom Look&Feel or theme.
It would certainly help ensuring the look of the application is consistent and at least you are using the right tool for the task you want to accomplish.
As a sidenote, be aware that Java comes with multiple Look&feels, including Look&Feels made to mimic the native OS theme.
See: http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

How to place JButtons at a certain coordinate in a JFrame

I want to know how to place JButtons at a particular coordinate in the JFrame. All day I have seen layouts. This does not suit my purpose. I would prefer something like setBounds. Rumour has it that it does not work but setLocation does. I tried it but, the program disregards the setLocation line and sets it to a Layout.
CODE
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.BorderLayout;
public class SwingUI extends JFrame {
public SwingUI() {
JFrame frm = new JFrame("OmegaZ");
JButton btn = new JButton("ClickMe");
frm.getContentPane().add(btn, BorderLayout.NORTH);
frm.setSize(400, 400);
frm.setVisible(true);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
btn.setLocation(100, 200);
}
public static void main(String[] args) {
new SwingUI();
}
}
Any help is appreciated.
Many Thanks
You can do absolute positioning with a null layout. You do all the work in that case.

Dynamically adding toolbars in Java Swing GUI

I am developing a Java Desktop Application. In the GUI, I want that user can add as many toolbars dynamically as he wants. To implement this, the following are the things that I have done already:
Have taken a mainPanel and set its layout as BorderLayout
Then taken a topPanel and added it to the mainPanel's BorderLayout.NORTH
set the topPanel's layout as BoxLayout
Then taken 5 panels named toolbar1Panel, toolbar2Panel, ....
Afterthat, have added one toolbar to each of the toolbarPanel created in the previous steps.
Have added only one toolbarPanel i.e toolbar1Panel on the topPanel
Now there is a button named "Add" on the first toolbar which is added on the "toolbar1Panel" which in turn is added to the topPanel.
Now I have implemented the "actionPerformed()" method of the above "Add" button as follows:
// to add second toolbar Panel to the topPanel dynamically
topPanel.add(toolbar2Panel);
But the problem is that it is not working. Means there is no toolbar added to the topPanel.
Is there anything which I am missing.
The code is Netbeans Generated so I think it would only add mess for others, that's why I haven't pasted any code here.
After adding another toolbar to the BoxLayout, you may need to (re|in)?validate the panel.
I've done this repeatedly but I can't understand the logic behind the 3 or so method calls; so I just try them until I hit on the one that works:
topPanel.validate();
topPanel.invalidate();
topPanel.revalidate();
topPanel.layout();
(at least) one of those should force your GUI to re-calculate its layout, making the north panel larger and thus showing the 2nd (and successive) toolbar(s) you've added.
Without specifying the layout for the top panel, it might be assuming the incorrect one.
Adding two toolbar panels to it might just be replacing the first with the second, or ignoring the second.
Just for testing set the topPanel's layout to FlowLayout and try again.
I think you are trying to do too much before testing. the way I would approach this is to start with something very simple, for example one panel, one static label. When that appears as you expect add a toolbar with a menu item. Does that work. Then incrmentally add the pieces.
Quite likely you'll have problems with a simple case and can then figure it out, or you'll have a simple case to post here.
Alterntively, as starting point pinck some working example from the net. Cut it down and then build up to your case.
Does it help ?
Is it what you want to achieve ?
import java.awt.BorderLayout;
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.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
public class AddingToolbars {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
AddingToolbars me = new AddingToolbars();
me.initGui();
}
});
}
private JPanel topPanel;
private JPanel mainPanel;
private JFrame frame;
private void initGui() {
frame = new JFrame();
mainPanel = new JPanel(new BorderLayout());
frame.setContentPane(mainPanel);
topPanel = new JPanel();
BoxLayout bLayout = new BoxLayout(topPanel,BoxLayout.Y_AXIS);
topPanel.setLayout(bLayout);
mainPanel.add(topPanel,BorderLayout.NORTH);
JButton addButton = new JButton("Add toolbar");
mainPanel.add(addButton,BorderLayout.CENTER);
addButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
addNewToolBar();
}
});
frame.setSize(500,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
protected void addNewToolBar() {
JToolBar tb = new JToolBar();
tb.add(new JButton("b1"));
tb.add(new JButton("b2"));
tb.add(new JButton("b3"));
topPanel.add(tb);
mainPanel.validate();
}
}

Categories

Resources