So, i created an object of class "CustomPanel" that creates a JPanel with a GridLayout and a label inside of it then I added it to my JFrame. It works fine showing the label "HELLO", but when I change the layout manager of the jpanel to (null) it doesn't show anything. I know, I know using null layout is a very bad practice but I just want to know why it isn't showing the components.
Main class:
import javax.swing.JFrame;
public class MainMenu extends javax.swing.JFrame{
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Size the window.
frame.setSize(500, 500);
CustomPanel panel = new CustomPanel();
frame.getContentPane().add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
CustomPanel class with GridLayout (This works fine):
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CustomPanel extends JPanel{
public CustomPanel() {
initUI();
}
public final void initUI() {
// create the panel and set the layout
JPanel main = new JPanel();
main.setLayout(new GridLayout());
// create the labels
JLabel myLabel = new JLabel("HELLO");
// add componets to panel
main.add(myLabel);
this.add(main);
}
}
CustomPanel class with Null layout (This doesn't work):
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CustomPanel extends JPanel{
public CustomPanel() {
initUI();
}
public final void initUI() {
// create the panel and set the layout
JPanel main = new JPanel();
main.setLayout(null);
// create the labels
JLabel myLabel = new JLabel("HELLO");
myLabel.setBounds(10, 10, myLabel.getPreferredSize().width, myLabel.getPreferredSize().height);
// add componets to panel
main.add(myLabel);
this.add(main);
}
}
The jlabel is correctly set inside the jpanel so it should be showing in the upper-left side of the jframe, but it doesn't.
What is causing this? what am I missing?.
The problem is that when you don't use a proper layout manager the main JPanel has a preferred size of 0,0, and won't display within the container that it is placed within. The CustomPanel that holds the main JPanel uses FlowLayout and will use its contained component's preferred sizes to help size and position these components, but since main has no layout, adding the JLabel to main does not increase the preferred size as it should -- yet another reason to use layouts, and CustomPanel will display main as just a sizeless dot. You could of course get around this by giving main a preferred size via main.setPreferredSize(...), but then you'd be solving a kludge with a kludge -- not good. Another possible solution is to change CustomPanel's layout to something else that might expand the main JPanel that it holds, perhaps giving CustomPanel a BorderLayout. In this situation, adding main to CustomPanel in a default fashion will place the main JPanel into the BorderLayout.CENTER position, expanding it to fill CustomPanel, and the JLabel will likely be seen.
The proper solution, of course, is to avoid use of null layouts whenever possible.
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.
This is the add(main) version
This is the add(scroll) version
Im trying to get a window full of lables and make it scrollable, this is my code for that purpose:
public class JobHistoryListScreen extends JFrame implements View
{
#Override
public void showScreen()
{
setSize(800, 800);
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel main = new JPanel();
main.setSize(500,500);
JScrollPane scroll = new JScrollPane(main,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setSize(500,500);
//Font
//Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++)
{
JLabel empty = new JLabel("No jobs to display!");
empty.setBounds(0,i+250,400,100);
empty.setFont(david50);
main.add(empty);
}
add(main);
setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
v.showScreen();
}
}
For some reason the window gets filled with the labels but is not scrollable at all.
Learn about layout managers. Refer to Laying Out Components Within a Container. Default for JPanel is FlowLayout and because the JPanel is inside a JScrollPanel, the labels will not wrap. And since you set the horizontal scroll bar policy to NEVER, there is no horizontal scroll bar and hence you cannot scroll horizontally. Try using BoxLayout to display all the labels one under the other. Alternatively you could use a GridLayout with 0 (zero) rows and 1 (one) column. Refer to the tutorial for more details.
EDIT
Here is my modified version of your code. Explanatory notes appear after the code.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class JobHistoryListScreen implements Runnable {
private JFrame frame;
#Override // java.lang.Runnable
public void run() {
showScreen();
}
public void showScreen() {
frame = new JFrame("Jobs");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel main = new JPanel(new GridLayout(0, 1));
JScrollPane scroll = new JScrollPane(main,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setPreferredSize(new Dimension(500, 500));
Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++) {
JLabel empty = new JLabel("No jobs to display!");
empty.setFont(david50);
main.add(empty);
}
frame.add(scroll);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
// Launch Event Dispatch Thread (EDT)
EventQueue.invokeLater(v);
}
}
I don't know what interface View is so I removed that part.
No need to extend class JFrame.
No need to explicitly call setSize() on JFrame. Better to call pack().
Default content pane for JFrame is JPanel and default layout manager for that JPanel is BorderLayout so no need to explicitly set.
No need to call setSize() on JPanel.
Call setPreferredSize() rather than setSize() on JScrollPane.
Add the JScrollPane to the JFrame and not the JPanel.
No need to call setBounds() because GridLayout handles this.
Explicitly launch EDT (Event Dispatch Thread) by calling invokeLater().
Here is a screen capture of the running app. Note the vertical scroll bar.
So, i created an object of class "CustomPanel" that creates a JPanel with a GridLayout and a label inside of it then I added it to my JFrame. It works fine showing the label "HELLO", but when I change the layout manager of the jpanel to (null) it doesn't show anything. I know, I know using null layout is a very bad practice but I just want to know why it isn't showing the components.
Main class:
import javax.swing.JFrame;
public class MainMenu extends javax.swing.JFrame{
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Size the window.
frame.setSize(500, 500);
CustomPanel panel = new CustomPanel();
frame.getContentPane().add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
CustomPanel class with GridLayout (This works fine):
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CustomPanel extends JPanel{
public CustomPanel() {
initUI();
}
public final void initUI() {
// create the panel and set the layout
JPanel main = new JPanel();
main.setLayout(new GridLayout());
// create the labels
JLabel myLabel = new JLabel("HELLO");
// add componets to panel
main.add(myLabel);
this.add(main);
}
}
CustomPanel class with Null layout (This doesn't work):
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CustomPanel extends JPanel{
public CustomPanel() {
initUI();
}
public final void initUI() {
// create the panel and set the layout
JPanel main = new JPanel();
main.setLayout(null);
// create the labels
JLabel myLabel = new JLabel("HELLO");
myLabel.setBounds(10, 10, myLabel.getPreferredSize().width, myLabel.getPreferredSize().height);
// add componets to panel
main.add(myLabel);
this.add(main);
}
}
The jlabel is correctly set inside the jpanel so it should be showing in the upper-left side of the jframe, but it doesn't.
What is causing this? what am I missing?.
The problem is that when you don't use a proper layout manager the main JPanel has a preferred size of 0,0, and won't display within the container that it is placed within. The CustomPanel that holds the main JPanel uses FlowLayout and will use its contained component's preferred sizes to help size and position these components, but since main has no layout, adding the JLabel to main does not increase the preferred size as it should -- yet another reason to use layouts, and CustomPanel will display main as just a sizeless dot. You could of course get around this by giving main a preferred size via main.setPreferredSize(...), but then you'd be solving a kludge with a kludge -- not good. Another possible solution is to change CustomPanel's layout to something else that might expand the main JPanel that it holds, perhaps giving CustomPanel a BorderLayout. In this situation, adding main to CustomPanel in a default fashion will place the main JPanel into the BorderLayout.CENTER position, expanding it to fill CustomPanel, and the JLabel will likely be seen.
The proper solution, of course, is to avoid use of null layouts whenever possible.
I'm a complete beginner to Java, and I'm finding some answers a bit too technical for me (even the most basic tutorials seem to give me syntax errors when I run the code). How, in really simple terms do I add a JButton to a JFrame? I've got as far as:
import javax.swing.JButton;
import javax.swing.JFrame;
public class JF {
public static void main(String[] args) {
JFrame myFrame = new JFrame();
/*some pretty basic code to initialize the JFrame i.e.
myFrame.setSize(300, 200);
This is as far as I got
*/
}
}
I would seriously appreciate some help!
Creating a new JFrame
The way to create a new instance of a JFrame is pretty simple.
All you have to do is:
JFrame myFrame = new JFrame("Frame Title");
But now the Window is hidden, to see the Window you must use the setVisible(boolean flag) method. Like this:
myFrame.setVisible(true);
Adding Components
There are many ways to add a Component to a JFrame.
The simplest way is:
myFrame.getContentPane().add(new JButton());//in this case we are adding a Button
This will just add a new Component that will fill the JFrame().
If you do not want the Component to fill the screen then you should either make the ContentPane of the JFrame a new custom Container
myFrame.getContentPane() = new JPanel();
OR add a custom Container to the ContentPane and add everything else there.
JPanel mainPanel = new JPanel();
myFrame.getContentPane().add(mainPanel);
If you do not want to write the myFrame.getContentPane() every time then you could just keep an instance of the ContentPane.
JPanel pane = myFrame.getContentPane();
Basic Properties
The most basic properties of the JFrame are:
Size
Location
CloseOperation
You can either set the Size by using:
myFrame.setSize(new Dimension(300, 200));//in pixels
Or packing the JFrame after adding all the components (Better practice).
myFrame.pack();
You can set the Location by using:
myFrame.setLocation(new Point(100, 100));// starting from top left corner
Finally you can set the CloseOperation (what happens when X is pressed) by
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
There are 4 different actions that you can choose from:
DO_NOTHING_ON_CLOSE //Nothing happens
HIDE_ON_CLOSE //setVisible(false)
DISPOSE_ON_CLOSE //Closes JFrame, Application still runs
EXIT_ON_CLOSE //Closes Application
Using Event Dispatch Thread
You should initialize all GUI in Event Dispatch Thread, you can do this by simply doing:
class GUI implements Runnable {
public static void main(String[] args) {
EventQueue.invokeLater(new GUI());
}
#Override
public void run() {
JFrame myFrame = new JFrame("Frame Title");
myFrame.setLocation(new Point(100, 100));
myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
myFrame.getContentPane().add(mainPanel);
mainPanel.add(new JButton("Button Text"), BorderLayout.CENTER);
myFrame.pack();
myFrame.setLocationByPlatform(true);
myFrame.setVisible(true);
}
}
//I hope this will help
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
public class JF extends JFrame
{
private JButton myButton;//Here you begin by declaring the button
public JF()//Here you create you constructor. Constructors are used for initializing variable
{
myButton = new JButton();//We initialize our variable
myButton.setText("My Button"); //And give it a name
JPanel panel1 = new JPanel();//In java panels are useful for holding content
panel1.add(myButton);//Here you put your button in the panel
add(panel1);//This make the panel visible together with its contents
setSize(300,400);//Set the size of your window
setVisible(true);//Make your window visible
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args)
{
JFrame frame = new JF();
frame.setTitle("My First Button");
frame.setLocation(400,200);
}
}
I'm trying to add the ScrollPane to my TextArea, but it doesn't appear.
Here's the code:
import javax.swing.*;
public class PracownikGui extends JFrame {
private JPanel Panelek;
private JTextArea Tekscik;
private JScrollPane Skrol;
public PracownikGui() {
setMinimumSize(new Dimension(600, 600));
setLocationRelativeTo(null);
setContentPane(Panelek);
setResizable(false);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
Tekscik();
public void Tekscik() {
Tekscik = new JTextArea(2, 10);
Skrol = new JScrollPane( Tekscik );
Tekscik.setSize(300, 300);
Tekscik.setLocation(20, 70);
Tekscik.setEditable(true);
Tekscik.setLineWrap(true);
add(Tekscik);
}}
Any help, please.
You're shooting yourself in the foot by setting a JTextArea's size or preferredSize since this prevents it from expanding into the JScrollPane:
Tekscik.setSize(300, 300);
set its rows and columns only.
Also you need to add the JScrollPane to the GUI, not the JTextArea.
Also, while null layouts and setBounds() or setSize(...) and setLocation(...) might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
e.g.,
import javax.swing.*;
public class PracownikPanel extends JPanel {
private JTextArea tekscik = new JTextArea(5, 25);
public PracownikPanel() {
tekscik.setLineWrap(true);
tekscik.setWrapStyleWord(true);
JScrollPane skrol = new JScrollPane(tekscik);
skrol.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(skrol);
}
private static void createAndShowGui() {
PracownikPanel mainPanel = new PracownikPanel();
JFrame frame = new JFrame("PracownikPanel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I made quite a few changes to your code. Your code wouldn't run.
Here's the GUI I created.
As you can see, there's a vertical scroll bar. The default action for the scroll bar is that it doesn't appear until you've filled the JTextArea with text.
Here are the important changes I made to your code.
Class names start with a capital letter. Method names and variable names start with a lower case letter.
A Swing application must start with a call to the SwingUtilities invokeLater method. This ensures that the Swing components are created and used on the Event Dispatch thread (EDT). Since the invokeLater method requires a Runnable, I had the PracownikGui class implement Runnable.
You use Swing components. You don't extend Swing components, or any other Java class, unless you want to override one of the methods in that class.
I removed all of the sizing and positioning statements, except for the statement that defines the rows and columns of the JTextArea. Hovercraft Full Of Eels explained this, but you use Swing layouts to get the arrangement of Swing components you want. The default layout for a JPanel is the FlowLayout. The default layout for a JFrame is the BorderLayout.
I added the JScrollPane to the JPanel. I added the JPanel to the JFrame.
Here's the code.
package com.ggl.testing;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class PracownikGui implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new PracownikGui());
}
private JFrame frame;
private JPanel panelek;
private JTextArea tekscik;
private JScrollPane skrol;
#Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
panelek = new JPanel();
tekscik(panelek);
frame.setContentPane(panelek);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
public void tekscik(JPanel panelek) {
tekscik = new JTextArea(2, 20);
tekscik.setEditable(true);
tekscik.setLineWrap(true);
skrol = new JScrollPane(tekscik);
panelek.add(skrol);
}
}