I'm fairly new to JFrame and I want to know why my items are not showing up on the window. I know i dont have a ActionHandler but I just want my textfield's to show up on my window. Here's my code:
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class FirstGUI extends JFrame{
public void GUI(){
setTitle("Welcome");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(600,600);
JLabel title = new JLabel();
title.setText("Apple Inc. Member Login Port");
title.setFont(new Font("Arial", Font.PLAIN, 24));
JTextField login = new JTextField("Login",10);
JPasswordField pass = new JPasswordField("Password");
add(title);
add(login);
add(pass);
}
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
}
}
but when i run it i get this:
but when i run it i get this:
You get an empty screen because you add the components to the frame after the frame is visible.
As has already been suggested you need to use an appropriate layout manager. FlowLayout is the easiest to start with.
invoke setVisible(true) AFTER adding the components to the frame.
So the code should be more like:
panel.add(...);
panel.add(...);
add(panel);
pack();
setVisible(true);
I agree to MadProgrammer's suggestions (+1)
Well, lets take a look at your program though
You actually have created a JFrame with components in it. Its working fine as well, but your question of "why are my items not showing up in the JFrame" is not because you did something wrong but because missed out something i.e. revalidate()
Try:
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
a.revalidate();
}
I'm not saying this will give you perfect UI.. what I'm trying to say is this will help you understand the Swing better. Learn about Swing Layout managers and then work on your UI to have better results
revalidate(): This component and all parents above it are marked as needing to be laid out. This means the Layout Manager will try to realign the components. Often used after removing components. It is possible that some really sharp swing people may miss this. I would think that you will only know this if you are actually using Swing.
The default layout manager for JFrame is BorderLayout.
This means that your components are essentially all been added ontop of each other.
Try changing the layout manager to something like FlowLayout (for example)...
Take a look at A Visual Guide to Layout Managers and Using Layout Managers for more details.
Also, avoid setSize where possible, use Window#pack instead
Update
I'd also like to introduce you to Initial Threads which should be used to launch your UI code...
The only one reason :
setVisible(True); method for the frame should be put on the end of the code.
if you give this line on the top of the code that is when you create a frame. This will cause that problem.
Don't add the components directly to your frame. Instead add to the content pane, which is where a JFrame stores all of the components that it draws. Usually this is a JPanel.
Here is an example:
public class GUI
{
private JPanel content;
public void GUI
{
/*Other code*/
content = new JPanel();
add(content); //make content the content pane
content.add(title);
content.add(login);
content.add(pass);
}
If that fails, call setVisible(true) and setEnabled(true) on all of your components.
On a side note you may want to make your GUI function a constructor.
import javax.swing.*;
import java.awt.*;
class Myframec extends JFrame
{
Myframec()
{
Container c = this.getContentPane();
c.setLayout(null);
this.setBounds(10,10,700,500);
this.setTitle("Welcome");
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBounds(0,0,700,500);
panel.setBackground(Color.gray);
panel.setLayout(null);
c.add(panel);
Font f = new Font("Arial",Font.BOLD,25);
Font f1 = new Font("Arial",Font.BOLD,20);
JLabel lable = new JLabel();
lable.setBounds(130,10,400,100);
lable.setText("Apple Inc. Member Login Port");
lable.setFont(f);
panel.add(lable);
JTextField login = new JTextField("Login",10);
login.setBounds(120,150,400,30);
login.setFont(f1);
panel.add(login);
JPasswordField pass =new JPasswordField("Password");
pass.setBounds(120,200,400,30);
pass.setFont(f1);
lable.setFont(f);
panel.add(pass);
c.setVisible(true);
this.setVisible(true);
}
public static void main(String[] argm)
{
Myframec frame = new Myframec();
frame.setVisible(true);
}
}
Related
The question is that I cannot add JPanel and JLabel in the Frame at the same time.
When i using following code, only MyPanel will be visible. myFrame.add(myLabel);myFrame.add(myPanel);myFrame.setVisible(true);
when I execute: myFrame.add(myLabel);myFrame.setVisible(true);myFrame.add(myPanel);
only myLabel will be visible.
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
MyFrame myFrame = new MyFrame();
MyLabel myLabel = new MyLabel();
MyPanel myPanel = new MyPanel();
myFrame.add(myLabel);
myFrame.add(myPanel);
myFrame.setVisible(true);
}
}
public class MyFrame extends JFrame {
MyFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //exit out of application.
//https://docs.oracle.com/javase/7/docs/api/javax/swing/JFrame.html#setDefaultCloseOperation%28int%29
this.setSize(750, 750); //set the size.
this.setResizable(true);//resize the frame.
this.setTitle("Welocme to new world."); //set the Title.
ImageIcon imageIcon = new ImageIcon("logo.png");
this.setIconImage(imageIcon.getImage());
this.getContentPane().setBackground(new Color(217, 217, 217));
this.setBackground(Color.YELLOW);//this.setVisible(true);//Make the frame visible.
}}
import javax.swing.*;
import java.awt.*;
public class MyPanel extends JPanel {
MyPanel() {
this.setBackground(Color.white);
this.setBounds(2,2,25,25);
}}
import javax.swing.*;
import java.awt.*;
public class MyLabel extends JLabel {
MyLabel(){
this.setText("<html>Heaven <br/>Heaven's body\"<br/> Whirl around me <br/>Make me wonder</html>");
//,SwingConstants.CENTER);
//https://stackoverflow.com/questions/1090098/newline-in-jlabel
//How to print multi line in java
ImageIcon image = new ImageIcon("Cosmogony_Björk_Cover.jpg");
this.setIcon(image);
//jLabel.setForeground(new Color(217,217,217));
this.setForeground(Color.BLACK);
this.setFont(new Font("helvetica",Font.PLAIN,18));
this.setBackground(Color.gray);
this.setOpaque(true);
//jLabel.setVerticalTextPosition(JLabel.TOP); Set the relative text position of the label.
//jLabel.setBorder();
this.setVerticalAlignment(JLabel.CENTER);
this.setHorizontalAlignment(JLabel.CENTER);
}}
The default Layout Manager of JFrame is the BorderLayout.
Since you did not change the layout manager of your JFrame this is also the current layout manager used in your snippet.
Usually, when using the BorderLayout, you specify which area of the BorderLayout should be populated when adding a component. This is usually done via
frame.add(component, BorderLayout.CENTER);
Notice the area specification in the add() method, which tells the BorderLayout where to place the component.
Here is the issue however. If you use the add() method in combination with the BorderLayout without specifying the placement of the component, it will always place the component in BorderLayout.CENTER. (Causing the component which is currently there to be replaced)
To work around this, do one of the following things:
Specify the placement explicitly, so both components will show up:
frame.add(component1, BorderLayout.PAGE_START);
frame.add(component2, BorderLayout.CENTER);
Or use a different Layout Manager, which will take care of the placement for you. E.g. FlowLayout
JPanel contentPanel = new JPanel(); // JPanel uses flowlayout by default!
contentPanel.add(component1);
contentPanel.add(component2);
myFrame.setContentPane(contentPanel);
You could also explicitly set the layout:
Container contentPane = myFrame.getContentPane();
// creates new FlowLayout and sets on content pane
contentPane.setLayout(new FlowLayout());
contentPane.add(component1);
contentPane.add(component2);
Sidenotes:
Look through the Laying out components within a container Oracle tutorial, which will give you more information on which layout managers there are and how to work with them.
When building your GUI, setVisible() on the JFrame should be the last thing you are doing after adding all components. Because if you add components after setting the frame visible, the changes will not immediately take effect without you telling swing that something changed.
When correctly working with the Swing Layout Managers, there should be no need to use things like setBounds(...) or setSize(). After adding all components, calling pack() on the JFrame is the preferred way to go. This will size the JFrame according to the preferred size of the components inside.
I know this question has been asked a lot and I have done my research but still can not find anything. Below is proof of this before anyone gets upset:
I found this link:
https://coderanch.com/t/563764/java/Blank-Frame-Panel
and this:
Adding panels to frame, but not showing when app is run
and this:
Why shouldn't I call setVisible(true) before adding components?
and this:
JPanel not showing in JFrame?
But the first question says use repaint which I tried with no fix and the second and third to last questions talk about putting setVisible after components added which I have.
The last one talks about making the users JPanelArt a extension (done so) of JPanel instead of JFrame and not to make a frame in a frame constructor (also have not done)
When ever I run this I just get a blank frame, as if the panel was never added in.
I apologise if I have missed something in those links. Anyway below is my classes:
GUI.java (extends JFrame)
package javaapplication2;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI extends JFrame{
public GUI(String name) {
super(name);
getContentPane().setLayout(null);
JPanel myPanel1 = new GUIPanel();
myPanel1.setLocation(20, 20);
getContentPane().add(myPanel1);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setResizable(true);
}
public static void main(String[] args) {
JFrame frame = new GUI("Game");
frame.setVisible(true);
}
}
GUIPanel.java (extends JPanel)
package javaapplication2;
import java.awt.*;
import javax.swing.*;
public class GUIPanel extends JPanel {
JButton start;
JButton inspect1;
JButton inspect2;
JButton inspect3;
JButton suspect;
public GUIPanel() {
setLayout(new BorderLayout());
start = new JButton("Start Game");
inspect1 = new JButton("Inspect 1");
inspect2 = new JButton("Inspect 2");
inspect3 = new JButton("Inspect 3");
suspect = new JButton("Choose Suspect");
add(start, BorderLayout.WEST);
add(inspect1, BorderLayout.WEST);
add(inspect2, BorderLayout.WEST);
add(inspect3, BorderLayout.WEST);
add(suspect, BorderLayout.WEST);
}
}
I know it is very simple, but that is because I am following a tutorial from my lecturer to get the hang of things as I previously used a GUI builder which someone in this community pointed out to me is not good to start with (very correct!)
The issue lies in your GUI class when you call getContentPane().setLayout(null). Because of this method call, your JFrame is not displaying anything. If you remove it, your elements should show up.
I also noticed that you were setting each JButton to have a constraint of BorderLayout.WEST. This will most likely put your JButtons on top of each other and render only one of them.
this is my first question on stackoverflow so pls don't be so hard with me (and my English), I'll try my best asking a good question.
The problem is about what the title suggests -> setting the background of a JTextpane (specifically setting it transparent). As the setBackground-method takes a color argument, the way i went was with an alpha value = 0. This leads to the following visual artifacts:
example picture of the visual artifacts when running the code below
I will describe it in detail now, say what i've already tried and then post a minimal example for everyone to be able to recreate the bug easily.
I have a JFrame (myFrame) holding a JPanel (Test()) in which i paint. The background of this JPanel is set to green as you can see in the code. I did this to differ between the background of the TextPane and the actual background of the panel.
We also have a JTextPane inputfield -> which takes user input (it displays what you write). This is held by a JScrollPane scrollpane.
So the Target (meaning what i try to achieve): is a User input field, which is transparent, but still displays the text the user puts in. I tried to achieve this by setting the background of the inputfield and the scrollpane to a transparent color.
I would really appreciate it, if you don't just type something like (you need to setOpague(false) for ....) if you don't know exactly what you're talking about, because i nearly tried everything i can think of and read every post i could find in the internet about the problem. I will post some of them at the end. So...
What i already tried:
The usual way i found while searching for something like "How to make TextPane transparent" was to setOpague(false) at itself as well as the scrollpane and the viewport of the scrollpane. 1. Reading about what the method actually does i don't think that is a proper solution. 2. setting Opague(false) on these three leads to everything being invisible so, that's not good. Packing the frame again after setting the background. Either nothing was fixed or the components became completely invisible.
I also tried: setBackground(null), setting the Background of just the inputfield (just every single component and every possible combination amongst the three (scrollpane, viewport, inputfield)), mixing setOpague(true)/setOpague(false)/setBackground(...) in every way i could think of. Overriding the paintComponent method of the textpane and scrollpane seemed like a good approach, but i did not come very far with it.
So here is the code:
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
#Override
public void paint(Graphics g) {
super.paint(g);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
}
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
inputField.setBackground(new Color(0,0,0,0));
scrollpane.setBackground(new Color(0,0,0,0));
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.pack();
myFrame.setSize(640,480);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.setVisible(true);
}
}
And here some links to posts I read which describe similar problems:
Java - Transparent JScrollPane
Transparent JEditorPane in a JScrollPane over a background JPanel
setOpaque(true/false); Java
I would really appreciate if someone can help me with the problem or even only suggest me an alternative solution. I'm writing a little chat-program atm for a project for my university and i think transparent message fields are a neat idea. I will try to answer here as fast as i can. Thx in advance.
Do not use transparent color as background - kind of hard to delete with it (e.g. when component is being repaint (and opaque)).
Do not use setBounds (unless using null LayoutManager). In below example I used setPreferredSize but still better to correctly use LayoutManager (I am a bit lazy, and lot of work to do at the moment).
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setPreferredSize(new Dimension(300, 100));
inputField.setOpaque(false);
scrollpane.setOpaque(false);
scrollpane.getViewport().setOpaque(false);
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
}
The whole code of main should be called on the EDT (e.g. SwingUtilities.invokeLater) since it is manipulating swing components but that is not part of the question (and not that relevant here since setVisible is the last command - components not being displayed while changed).
Your program gave me some errors when launching, occasionally. Make sure to run a swing GUI from the EDT (invokeLater()).
The line that is causing your issue is:
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
Also - is there some reason you are setting bounds manually instead of using a layout manager?
Maybe I didn't understand your question, or you want to have an image in the background - but could you not just set the color of your text area to be the same color as your JPanel?
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setBackground(Color.GREEN);
scrollpane.setPreferredSize(new Dimension(300, 300));
inputField.setBackground(Color.GREEN);
this.add(scrollpane);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
});
}
}
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);
}
I'm fairly new to JFrame and I want to know why my items are not showing up on the window. I know i dont have a ActionHandler but I just want my textfield's to show up on my window. Here's my code:
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class FirstGUI extends JFrame{
public void GUI(){
setTitle("Welcome");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(600,600);
JLabel title = new JLabel();
title.setText("Apple Inc. Member Login Port");
title.setFont(new Font("Arial", Font.PLAIN, 24));
JTextField login = new JTextField("Login",10);
JPasswordField pass = new JPasswordField("Password");
add(title);
add(login);
add(pass);
}
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
}
}
but when i run it i get this:
but when i run it i get this:
You get an empty screen because you add the components to the frame after the frame is visible.
As has already been suggested you need to use an appropriate layout manager. FlowLayout is the easiest to start with.
invoke setVisible(true) AFTER adding the components to the frame.
So the code should be more like:
panel.add(...);
panel.add(...);
add(panel);
pack();
setVisible(true);
I agree to MadProgrammer's suggestions (+1)
Well, lets take a look at your program though
You actually have created a JFrame with components in it. Its working fine as well, but your question of "why are my items not showing up in the JFrame" is not because you did something wrong but because missed out something i.e. revalidate()
Try:
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
a.revalidate();
}
I'm not saying this will give you perfect UI.. what I'm trying to say is this will help you understand the Swing better. Learn about Swing Layout managers and then work on your UI to have better results
revalidate(): This component and all parents above it are marked as needing to be laid out. This means the Layout Manager will try to realign the components. Often used after removing components. It is possible that some really sharp swing people may miss this. I would think that you will only know this if you are actually using Swing.
The default layout manager for JFrame is BorderLayout.
This means that your components are essentially all been added ontop of each other.
Try changing the layout manager to something like FlowLayout (for example)...
Take a look at A Visual Guide to Layout Managers and Using Layout Managers for more details.
Also, avoid setSize where possible, use Window#pack instead
Update
I'd also like to introduce you to Initial Threads which should be used to launch your UI code...
The only one reason :
setVisible(True); method for the frame should be put on the end of the code.
if you give this line on the top of the code that is when you create a frame. This will cause that problem.
Don't add the components directly to your frame. Instead add to the content pane, which is where a JFrame stores all of the components that it draws. Usually this is a JPanel.
Here is an example:
public class GUI
{
private JPanel content;
public void GUI
{
/*Other code*/
content = new JPanel();
add(content); //make content the content pane
content.add(title);
content.add(login);
content.add(pass);
}
If that fails, call setVisible(true) and setEnabled(true) on all of your components.
On a side note you may want to make your GUI function a constructor.
import javax.swing.*;
import java.awt.*;
class Myframec extends JFrame
{
Myframec()
{
Container c = this.getContentPane();
c.setLayout(null);
this.setBounds(10,10,700,500);
this.setTitle("Welcome");
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBounds(0,0,700,500);
panel.setBackground(Color.gray);
panel.setLayout(null);
c.add(panel);
Font f = new Font("Arial",Font.BOLD,25);
Font f1 = new Font("Arial",Font.BOLD,20);
JLabel lable = new JLabel();
lable.setBounds(130,10,400,100);
lable.setText("Apple Inc. Member Login Port");
lable.setFont(f);
panel.add(lable);
JTextField login = new JTextField("Login",10);
login.setBounds(120,150,400,30);
login.setFont(f1);
panel.add(login);
JPasswordField pass =new JPasswordField("Password");
pass.setBounds(120,200,400,30);
pass.setFont(f1);
lable.setFont(f);
panel.add(pass);
c.setVisible(true);
this.setVisible(true);
}
public static void main(String[] argm)
{
Myframec frame = new Myframec();
frame.setVisible(true);
}
}