JPanel won't display components when layout is null - java

I'm trying to create a GUI, and I want to place elements in certain places. I made the layout of my panel null, so I could do this. However, Nothing will appear when the panel is null. Here's the code:
public class OverView extends JFrame {
//height and width of screen
Toolkit tk = Toolkit.getDefaultToolkit();
int x = ((int) tk.getScreenSize().getWidth());//length of screen
int y = ((int) tk.getScreenSize().getHeight());//height
//components
private JLabel title;
private JLabel description;
private JPanel panel;
private ArrayList<JButton> farms;
//farm variables
public ArrayList<Farm> owned;
public OverView(ArrayList<Farm> owned) {
super("The Lolipop Farm - Overview");
setSize(700, 700);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
//initialize variables
this.owned = owned;
panel = new JPanel();
panel.setLayout(null);
title = new JLabel("<html>Your Farms - The Lolipop Farm"
+ "<br> <font size=1000> <i> An Eph Production </i> </font></html>");
//set background color, color, and font of JComponents
title.setFont(new Font("serif", Font.BOLD, 25));
title.setBackground(Color.GRAY);
title.setOpaque(true);
//set size and location of the components
title.setSize(350, 120);
title.setLocation(x / 2, 600);
//add to panel
panel.add(title);
//add panel to the screen
add(panel);
}
}
Why isn't the panel showing anything when the layout's null?

As Overview is a Frame, I think you must call the method
setVisible(true);
according to https://docs.oracle.com/javase/tutorial/uiswing/layout/using.html in order to make it visible .
Now, if that doesn't work, I wonder if you have created an instance of the Overview class somewhere else in your code, or in the Main method. If you haven't, then there is no object that can show the panel inside of your class so your program won't show anything.

Your problem is with the code
setLayout(null);
This will set the layout of the JFrame to null since you are extending (inheriting it). You must have a layout for a JFrame although you can do without layout for JPanel. Just remove that line and it will be fine.
EDIT:
And of course you need to call setVisible(true) like the other guy said.

Related

How to avoid "put on top of" a component another component - Java Swing

I have two components ready to add to frame:
class Lamina extends JPanel{
public Lamina(){
setLayout(new BorderLayout(50,50));
JPasswordField user_password = new JPasswordField();
add(user_password, BorderLayout.SOUTH);
}
}
class DOMHeader extends JPanel
{
public DOMHeader()
{
setLayout(new BorderLayout());
JLabel title = new JLabel("Sign in");
add(title, BorderLayout.NORTH);
}
}
This is my class UI:
public class UI {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Frame frame = new Frame();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
frame.setTitle("Metin2");
}
}
Frame class:
class Frame extends JFrame {
public Frame() {
Toolkit screen = Toolkit.getDefaultToolkit();
Dimension screenSize = screen.getScreenSize();
int widthScreen = screenSize.width;
int heightScreen = screenSize.height;
setBounds((widthScreen/4/2),(heightScreen/4/2),(widthScreen/2/2), (heightScreen/2/2));
Image icon = screen.getImage("icon.jpeg");
setIconImage(icon);
/* Add to Components to frame*/
add(new DOMHeader());
add(new Lamina());
}
}
In my class Frame I'm adding the components shown earlier, but it "put on top of" a component another component.
According to the API:
public Component add(Component comp,int index)
Adds the specified component to this container at the given position
(index).
I run the main method:
As you can see it only show the Component DOMHeader class: add(new DOMHeader())
And what happened with add(new Lamina())
What number or Constant I should give it ?
This line:
class Frame extends JFrame {
is incorrect for the following reasons:
It's confusing because of AWT Frame class
It extends JFrame but you never change the behavior of the JFrame later, so no need to extend JFrame but create it inside of class
Now, we must head to JFrame class in which says:
The default content pane will have a BorderLayout manager set on it.
Now, if we go to the visual guide for layout managers in the BorderLayout section we can see the following image:
Which shows us that we can only add our components to 5 locations:
PAGE_START (or NORTH)
LINE_START (or WEST)
CENTER
LINE_END (or EAST)
PAGE_END (or SOUTH)
To answer your question:
According to the API:
public Component add(Component comp,int index)
Adds the specified component to this container at the given position (index).
What number or Constant I should give it ?
Well you need to add it as follows:
JFrame frame = new JFrame("Write your title here"); //Follow first advice
frame.add(new DOMHeader(), BorderLayout.NORTH); //These are the constants.
frame.add(new Lamina(), BorderLayout.SOUTH);
You confused yourself by adding the items in their locations in their own JPanels not on the JFrame itself.
Side note: Why are you doing these weird calculations?
setBounds((widthScreen/4/2),(heightScreen/4/2),(widthScreen/2/2), (heightScreen/2/2));
Wouldn't it be clearer if you called: widthScreen / 8?
As per #camickr comment:
There is no need for the DOMHeader and Lamina classes. You don't need to extend JPanel just to add a component to the frame. The "content pane" of a JFrame is a JPanel, so you can just add the label and text field to the frame as shown above.
You can also have your code improved in this way:
JFrame frame = new JFrame("Your title here");
JLabel title = new JLabel("Sign in");
JPasswordField userPassword = new JPasswordField(); //changed variable name to userPassword instead of user_password to follow Java naming conventions
frame.add(title, BorderLayout.NORTH);
frame.add(userPassword, BorderLayout.SOUTH);
frame.setVisible(true); //This line should be the last one or you'll find yourself with strange "bugs" when your application starts until you move it or resize it
No need to create a whole new JPanel for each component.

Setting Location of JButton never works?

I'm trying to create a button and place it in a certain location, but for some reason it never goes in that specific location. I tried putting it a panel, using setBounds, using setLocation... but It doesn't seem to work...
I'm running this file in another file.
public class Inventory extends JPanel
{
private final static int frameWidth = 200;
private final static int frameHeight = 500;
private final static int screenLocationX = 100;
private final static int screenLocationY = 50;
private Panel panel;
private JFrame frame;
private JPanel jpanel;
public Inventory()
{
panel = new Panel();
frame = new JFrame();
JButton button = new JButton("Add Gem");
button.addActionListener(new Listener());
button.setPreferredSize(new Dimension(frameWidth,50));
// button.setLocation(0,400);
// button.setBounds(0,400,frameWidth,50);
panel.setVisible(true);
frame.setContentPane(panel);
frame.add(button);
frame.setVisible(true);
frame.setSize(frameWidth, frameHeight);
frame.setLocation(screenLocationX, screenLocationY);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
}
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
panel.addImage(new Gems());
}
}
}
Before adding panel to the frame use:
panel.setLayout(null); //setting the default settings of panel to null
and then use:
button.setBounds(300, 300, 300, 300); //bounding the button at specific location
this would work..
You need to turn the LayoutManager off
panel.setLayout(null);
JFrame by default uses a BorderLayout and, by default, components are added to the BorderLayout.CENTER position, unless otherwise specified
In this setup, the component will be placed on the centre of the frame and sized to fill it
Remember, each platform/OS renders content differently and these differences will change the amount of space required to display your components and all of this will effective the relationships between all the other components...
You consider changing the layout manager and using a combination of EmptyBorders and insets/padding to influence the location/size of your components. Try something like GridBagLayout or if your adventurous, checking out MigLayout
One of the first lessons you need to learn with GUI program (on just about any platform) is pixel perfect layouts are an illusion, there are too many variables which effect how content is rendered and how these can change the amount of space individual components will need in order to be displayed correctly...

Changing layout of a JPanel sent to JOptionPane with the pane still running

Trying to change the look of a JOptionPane while its open, depending on which radiobutton the user clicks. What am I doing wrong? It works perfect if I for example add a button and move a JLabel from side to side of the window.
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import static javax.swing.JOptionPane.*;
public class ChangePanel extends JFrame{
private JButton click = new JButton("CLICK ME!");
ChangePanel(){
add(click, BorderLayout.SOUTH);
click.addActionListener(new ButtonListen());
setVisible(true);
setSize(300,100);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public class ButtonListen implements ActionListener{
public void actionPerformed(ActionEvent e){
PopUpPanel pop = new PopUpPanel();
showConfirmDialog(ChangePanel.this, pop, "Changeable", OK_CANCEL_OPTION);
}
}
//Send this as Parameter to the ConfirmDialog
public class PopUpPanel extends JPanel implements ActionListener{
JRadioButton jewelry = new JRadioButton("Jewelry");
JRadioButton shares = new JRadioButton("Shares");
JRadioButton machine = new JRadioButton("Machine");
PopUpPanel(){
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
ButtonGroup bg = new ButtonGroup();
JPanel north = new JPanel();
bg.add(jewelry);
jewelry.addActionListener(this);
bg.add(shares);
shares.addActionListener(this);
bg.add(machine);
machine.addActionListener(this);
north.add(jewelry);
north.add(shares);
north.add(machine);
add(north);
}
//Listener for RadioButtons
public void actionPerformed(ActionEvent e){
JTextField info1Txt = new JTextField(12);
JTextField info2Txt = new JTextField(12);
JTextField info3Txt = new JTextField(3);;
JRadioButton b = (JRadioButton)e.getSource();
if(b.getText().equals("Jewelry")){
//Dummy test text
System.out.println("Jewelry");
JPanel info1 = new JPanel();
info1.add(new JLabel("info1:"));
info1.add(info1Txt);
add(info1);
JPanel info2 = new JPanel();
info2.add(new JLabel("info2:"));
info2.add(info2Txt);
add(info2);
JPanel info3 = new JPanel();
info3.add(new JLabel("info3:"));
info3.add(info3Txt);
add(info3);
validate();
repaint();
}else if(b.getText().equals("Shares")){
//Dummy test text
System.out.println("Shares");
}else
//Dummy test text
System.out.println("Machine");
}
}
public static void main(String[] args){
new ChangePanel();
}
}
As you are working with BoxLayout, you should provide size hints to the PopUpPanel panel, which you haven't given.
When a BoxLayout lays out components from top to bottom, it tries to size each component at the component's preferred height. If the vertical space of the layout does not match the sum of the preferred heights, then BoxLayout tries to resize the components to fill the space. The components either grow or shrink to fill the space, with BoxLayout honoring the minimum and maximum sizes of each of the components.
check out the official tutorial page discussion: BoxLayout Feature
Call revalidate() and repaint() on the container after removing or adding components to it. So if you change the following lines:
validate();
repaint();
to:
revalidate();
repaint();
The content should appear. Though, it will not fit the original size of the JOptionPane. You can override PopUpPanel.getPreferredSize() to return desired size so that JOptionPane is packed properly, ie:
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
You can also use JDialog instead of JOptionPane.
Also, consider using CardLayout instead of swapping components manually. Check How to Use CardLayout for examples.
Why not just use setPreferredSize(new Dimension(300, 300)) in PopUpPanel constructor? Works fine for me. Good eye on revalidate and repaint.

JToolbar background and drag problems

I'm new to Swing and I currently work on some sort of graphic editor.
First I started implementing the toolbar (class OptionsBar) as an extended JPanel. Everything looked fine(image below), but it didn't work as a toolbar (it wasn't always focused). Then I found out that there actually exists a JToolBar element, so I replaced "extends JPanel" with "extends JToolBar". I look thorugh toolbar specifications. It seemed like I should change anything.
The problem is that the toolbar is transparent (besides its panel elements) even though isBackgroundSet() returns true. (image 2)
The second bug is drag the toolbar and then bring it back to the initial positions. It shrinks. (image 3)
Also, some movements (i can't describe them exactly) result in java.lang.IllegalArgumentException: illegal component position
The main windows is a JFrame that has border layout and uses a desktop pane.
Any help? Thanks!!
public class OptionsBar extends JToolBar {
..some constants and attributes..
public OptionsBar(BrushStroke brushStroke, BrushStroke savedBrushStroke) {
super();
this.setBackground(backgroundColor);
// keep the references to strokes from the main gui
this.brushStroke = brushStroke;
this.savedBrushStroke = savedBrushStroke;
// create buttons for selecting pencil/eraser
JToggleButton brushButton = makeInstrumentButton(brushIcon, "Pencil");
JToggleButton eraserButton = makeInstrumentButton(eraserIcon, "Eraser");
// make a button for adjusting colors
JButton adjustColorButton = makeAdjustButton();
// create label for descriptions
JLabel toolsLabel = makeDescriptionLabel("Tools");
JLabel parametersLabel = makeDescriptionLabel("Parameters");
JLabel colorsLabel = makeDescriptionLabel("Colors");
// create panel for brush size and opacity parameters
ParameterPanel sizePanel = new ParameterPanel("Size", "1", 1,
maxBrushSize, 1);
ParameterPanel opacityPanel = new ParameterPanel("Opacity", "100", 0,
100, 100);
// create a check box for selecting rounded caps
JCheckBox roundedCap = new JCheckBox("Use round strokes");
roundedCap.setSelected(true);
JSeparator separator = new JSeparator(JSeparator.VERTICAL);
separator.setMaximumSize(new Dimension(3, 35));
JSeparator separator1 = new JSeparator(JSeparator.VERTICAL);
separator1.setMaximumSize(new Dimension(3, 35));
// create a box layout
this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
this.add(Box.createHorizontalStrut(20));
this.add(toolsLabel);
this.add(Box.createHorizontalStrut(30));
this.add(brushButton);
this.add(Box.createHorizontalStrut(10));
this.add(eraserButton);
this.add(Box.createHorizontalStrut(30));
this.add(separator1);
this.add(Box.createHorizontalStrut(30));
this.add(parametersLabel);
this.add(Box.createHorizontalStrut(20));
this.add(sizePanel);
this.add(Box.createHorizontalStrut(20));
this.add(opacityPanel);
this.add(Box.createHorizontalStrut(25));
this.add(roundedCap);
this.add(Box.createHorizontalStrut(25));
this.add(separator);
this.add(Box.createHorizontalStrut(30));
this.add(colorsLabel);
this.setOpaque(false);
addColorButtons();
this.add(Box.createHorizontalStrut(20));
this.add(adjustColorButton);
this.colorPicker = new ColorPicker();
colorPicker.getSelectionModel().addChangeListener(new ColorChange());
this.colorPopup = new JPopupMenu();
colorPopup.add(colorPicker);
this.setSize(2000, 65);
this.setVisible(true);
}
And here is the snipped from the JFrame constructor
Here is a snippet from the JFrame constructor
desktop = new JDesktopPane();
setContentPane(desktop);
whiteBoards = new HashMap<String, Canvas>();
createFrame("first try", 400, 300);
desktop.add(new OptionsBar(brushStroke,savedBrushStroke),BorderLayout.PAGE_START);
To give an answer to all your questions:
JMenuBar is transparent by default. You can change that setting as follows:
menuBar.setOpaque(true);
You added your JMenuBar to a JDesktopPane container. A JDesktopPane has no layout set by default, to allow positioning of the added JInternalFrame. Thats why your JMenuBar is not visible, if you do not set the size manually.
Usually it is a better idea to let the LayoutManager align your components. To do so, replace your last code snippet with these lines:
desktop = new JDesktopPane();
JPanel basePanel = new JPanel(new BorderLayout());
basePanel.add(desktop, BorderLayout.CENTER);
basePanel.add(new OptionsBar(...), BorderLayout.PAGE_START);
getContentPane().add(basePanel);
This code uses another parent JPanel which allows us to add our JMenuBar to the top area. Aligning and sizing of our JMenuBar is not delegated to the LayoutManager of the JPanel so we can get rid of the getSize(...) in the constructor of the OptionsBar.
I am pretty sure that this change also fixes the thrown IllegalArgumentException.

Placing a JLabel at a specific x,y coordinate on a JPanel

I'm trying to place a series of JLabels at specific X and Y coordinates on a JPanel (and set its height and width, too). No matter what I do, each label winds up immediately to the right of the previous label and has the exact same size as all of the others.
Right now, my Jpanel is in a Grid Layout. I've tried Absolute Layout (illegal argument exception results), Free Design (no labels appear), Flow Layout (everything just gets squeezed to the center), and a few others.
Not sure what I need to do to make this work. Can anyone help? Thanks!
JLabel lbl1 = new JLabel("label 1");
JLabel lbl2 = new JLabel("label 2");
JLabel lbl3 = new JLabel("label 3");
JLabel lbl4 = new JLabel("label 4");
JLabel lbl5 = new JLabel("label 5");
myPanel.add(lbl1);
myPanel.add(lbl2);
myPanel.add(lbl3);
myPanel.add(lbl4);
myPanel.add(lbl5);
lbl1.setLocation(27, 20);
lbl2.setLocation(123, 20);
lbl3.setLocation(273, 20);
lbl4.setLocation(363, 20);
lbl5.setLocation(453, 20);
lbl1.setSize(86, 14);
lbl2.setSize(140, 14);
lbl3.setSize(80, 14);
lbl4.setSize(80, 14);
lbl5.setSize(130, 14);
You have to set your container's Layout to null:
myPanel.setLayout(null);
However is a good advise also to take a look at the Matisse Layout Manager, I guess it is called GroupLayout now. The main problem with absolute positioning is what happens when the window changes its size.
Set the container's layout manager to null by calling setLayout(null).
Call the Component class's setbounds method for each of the container's children.
Call the Component class's repaint method.
Note:
Creating containers with absolutely positioned containers can cause problems if the window containing the container is resized.
Refer this link:
http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html
Layout managers are used to automatically determine the layout of components in a container. If you want to put components at specific coordinate locations, then you should not use a layout manager at all.
myPanel = new JPanel(null);
or
myPanel.setLayout(null);
My advise is to use an IDE like NetBeans with its GUI editor. To inspect the code and because there are many ways:
Setting the layout manager, or for absolute positioning doing a myPanel.setLayout(null), has several influences.
In general, assuming you do your calls in the constructor of a JFrame, you can call pack() to start the layouting.
Then, every layout manager uses its own implementation of add(Component) or add(Component, Constraint). BorderLayout's usage is with add(label, BorderLayout.CENTER) and so on.
// Best solution!!
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = (JPanel) frame.getContentPane();
panel.setLayout(null);
JLabel label = new JLabel("aaa");
panel.add(label);
Dimension size = label.getPreferredSize();
label.setBounds(100, 100, size.width, size.height);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
You can use your own method that calling by setSize, setLocation values for directly....! `
As well i show you how to use JProgress Bar
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class installComp{
void install(Component comp, int w, int h, int x, int y){
comp.setSize(w,h);
comp.setLocation(x,y);
}
}
class MyFrame extends JFrame{
int cur_val = 0;
JButton btn = new JButton("Mouse Over");
JProgressBar progress = new JProgressBar(0,100);
MyFrame (){
installComp comp=new installComp();
comp.install(btn,150,30,175,20);
comp.install(progress,400,20,50,70);
btn.addMouseListener(new MouseAdapter(){
public void mouseEntered(MouseEvent evt){
cur_val+=2;
progress.setValue(cur_val);
progress.setStringPainted(true);
progress.setString(null);
}
});
add(btn);
add(progress);
setLayout(null);
setSize(500,150);
setResizable(false);
setDefaultCloseOperation(3);
setLocationRelativeTo(null);
setVisible(true);
}
}
class Demo{
public static void main(String args[]){
MyFrame f1=new MyFrame();
}
}

Categories

Resources