I am trying to add buttons over the images in the panels. I am also trying to switch between the panels. The program is running but when I am clicking the "instructions" button it gives a huge list of errors in the cmd. What is the issue?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.JButton;
import javax.swing.JPanel;
public class htw10 extends JFrame
{
final JFrame f=new JFrame("Hunt The Wumpus");
private static final String FIRST_PANEL="first panel";
private static final String SECOND_PANEL="second panel";
private CardLayout cardLayout=new CardLayout();
private JPanel content;
public void start()
{
// Create a new panel, make 'content' refer to it
content = new JPanel();
// Set the content pane of the window to the panel we just created
f.setContentPane(content);
// Create a button group and some buttons
// Set the layout of the content panel and add buttons
content.setLayout(new FlowLayout());
// Create and add the intro panel and instruction panel to the content panel
content.add(introPanel(),FIRST_PANEL);
content.add(instructionPanel(),SECOND_PANEL);
f.setSize(750,500);
f.setDefaultCloseOperation(EXIT_ON_CLOSE);
f.setVisible(true);
}
private JPanel instructionPanel()
{
JPanel secondPanel=new JPanel();
ImageIcon icon=new ImageIcon("img2.jpg");
JLabel pic2 = new JLabel(icon);
secondPanel.add(pic2);
JButton b1=new JButton("Back");
content.add(b1);
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardLayout.show(content,FIRST_PANEL);
}
});
secondPanel.repaint();
return secondPanel;
}
public JPanel introPanel()
{
JPanel iPanel=new JPanel();
ImageIcon icon=new ImageIcon("img1.jpg");
JLabel picLabel = new JLabel(icon);
iPanel.add(picLabel);
ButtonGroup group=new ButtonGroup();
JButton b1=new JButton("Instructions");
JButton b2=new JButton("Play");
JButton b3=new JButton("Exit");
picLabel.add(b1);
//f.getContentPane().add(picLabel,BorderLayout.SOUTH);
content.add(b1);
content.add(b2);
content.add(b3);
// Add a listener to the 'Instructions' button
// so that the cardLayout is shown when the button is clicked
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardLayout.show(content,SECOND_PANEL);
}
});
iPanel.repaint();
return iPanel;
}
public static void main(String args[])throws Exception
{
htw10 obj=new htw10();
obj.start();
}
}
In line 14, you are declaring a member variable content, but you are not initializing it. Member variables will be automatically initialized to null if you do not initialize them yourself:
private JPanel content; // is automatically set to null
In line 25 you are calling the method setLayout on content:
content.setLayout(new FlowLayout());
This will cause a NullPointerException because content is null.
To learn more about what a NullPointerException is and why it happens, see: What is a NullPointerException, and how do I fix it?
You need to set content to something. It appears that this is supposed to refer to the content pane. Furthermore, you are calling the introPanel() method multiple times, causing multiple instances of this panel to be created. That is not what you want. That panel should be created only once, and then you should use that one. Don't call introPanel() multiple times. Your start() method should look something like this:
public void start()
{
// Create a new panel, make 'content' refer to it
content = new JPanel();
// Set the content pane of the window to the panel we just created
f.setContentPane(content);
// Create a button group and some buttons
ButtonGroup group=new ButtonGroup();
JButton b1=new JButton("Instructions");
JButton b2=new JButton("Play");
JButton b3=new JButton("Exit");
// Set the layout of the content panel and add buttons
content.setLayout(new FlowLayout());
content.add(b1);
content.add(b2);
content.add(b3);
// Create and add the intro panel and instruction panel to the content panel
content.add(introPanel(),FIRST_PANEL);
content.add(instructionPanel(),SECOND_PANEL);
f.setSize(750,360);
f.setDefaultCloseOperation(EXIT_ON_CLOSE);
f.setVisible(true);
// Add a listener to the 'Instructions' button
// so that the cardLayout is shown when the button is clicked
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardLayout.show(content,SECOND_PANEL);
}
});
}
I don't think Jpanel has drawImage method which you are trying to call in below code.
public JPanel introPanel()
{
JPanel iPanel=new JPanel();
ImageIcon icon=new ImageIcon("img1.jpg");
iPanel.drawImage(icon, 0, 0,getWidth(),getHeight(),this);
return iPanel;
}
You need a graphics(java.awt.Graphics) object to call drawImage method.
More-over you can try other methods like
public JPanel introPanel()
{
JPanel iPanel=new JPanel();
ImageIcon icon=new ImageIcon("img1.jpg");
JLabel picLabel = new JLabel(icon);
iPanel.add(picLabel);
iPanel.repaint();
return iPanel;
}
Related
I have a JPanel and JButton on the JFrame.
on runtime add JLabel to JPanel When click JButton.
I use of the following code:
panel.setLayout(null);
jLabel _lbl=new jLabel();
_lbl.setText("Label");
panel.add(_lbl);
panel.validate();
but no display any JLabel in JPanel.
I see you create a JLabel called _lbl:
JLabel _lbl=new JLabel();
but you never add it to your panel. Instead you add a new JLabel with no text to your panel:
panel.add(new JLabel());
This would ofcourse construct an empty label which wont be visible.
Also try calling revalidate() and repaint() on your JPanel instance after adding the JLabel like so:
JLabel _lbl=new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
With this you may also need to call pack() on your frames instance so as to resize the JFrame to fit the new components.
Also please never use a null/Absolute layout this is very bad practice (unless doing animation) and may prove to be problematic and very hard to use.
Rather use a LayoutManager:
A Visual Guide to Layout Managers
or if you only have a single component on the JPanel simply call add(label); as it will stretch to the JPanel size.
UPDATE:
Here is a small sample. Simply adds JLabels to the JPanel each time JButton is pressed:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JavaApplication116 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JavaApplication116().createAndShowUI();
}
});
}
private void createAndShowUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(final JFrame frame) {
final JPanel panel = new JPanel(new FlowLayout());
JButton button = new JButton("Add label");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JLabel _lbl = new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
frame.pack();//so our frame resizes to compensate for new components
}
});
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.SOUTH);
}
}
This code displays nothing, I have exhausted many avenues but it does not display anything on the GUI (I have a main class that calls this as well already). Please help. I am trying to put the two JButtons horizontally at the bottom of the page and the JTextField and JLabel at the center of the screen.
package test;
import javax.swing.*;
import java.awt.*;
public class Gui extends JFrame {
private JLabel label;
private JButton clear;
private JButton copy;
private JTextField textfield;
public Gui(){
super("test");
clear = new JButton("Clear");
copy = new JButton("Copy");
label = new JLabel("");
textfield = new JTextField("enter text here");
JPanel bottom = new JPanel(new BorderLayout());
JPanel subBottom = new JPanel();
subBottom.add(copy);
subBottom.add(clear);
JPanel centre = new JPanel (new BorderLayout());
JPanel subCentre = new JPanel();
subCentre.add(label);
subCentre.add(textfield);
bottom.add(subBottom, BorderLayout.PAGE_END);
centre.add(subCentre, BorderLayout.CENTER);
}
}
Your code is a bit over-complicated. You only need two panels, centre, and buttons. There are two reasons your UI is not showing up:
You never added the panels to the frame
You never set visible to true(Achieve this by using setVisible(true)), unless you did this in the class you ran it in.
One simple way to achieve your desired UI is like so(I added a main method to show the window):
import javax.swing.*;
import java.awt.*;
public class test extends JFrame {
public Test() {
super("test");
JPanel buttons = new JPanel();
JPanel centre = new JPanel();
add(buttons, BorderLayout.SOUTH); //these lines add the
add(centre, BorderLayout.CENTER); //panels to the frame
JButton clear = new JButton("Clear"); // No need
JButton copy = new JButton("Copy"); // to declare
JLabel label = new JLabel("Label"); // these
JTextField textfield = new JTextField("enter text here"); // privately
buttons.add(copy);
buttons.add(clear);
centre.add(label);
centre.add(textfield);
pack();
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
} //end constructor
//added main method to run the UI
public static void main(String[] args) {
new Experiments();
} //end main
} //end class
And it shows the window:
I got closer but its not pretty code, the JFrame is 500x500 so this works based on that... any better suggestions than what I have?
package lab6;
import javax.swing.*;
import java.awt.*;
public class Gui extends JFrame {
private JLabel label;
private JButton clear;
private JButton copy;
private JTextField textfield;
public Gui(){
super("test");
clear = new JButton("Clear");
copy = new JButton("Copy");
label = new JLabel("label");
textfield = new JTextField("enter text here");
JPanel masterPanel = new JPanel(new BorderLayout());
JPanel top = new JPanel();
top.setPreferredSize(new Dimension(100, 200));
JPanel bottom = new JPanel();
JPanel subBottom = new JPanel();
subBottom.add(copy);
subBottom.add(clear);
JPanel centre = new JPanel ();
JPanel subCentre = new JPanel();
subCentre.add(label);
subCentre.add(textfield);
bottom.add(subBottom);
centre.add(subCentre);
masterPanel.add(bottom, BorderLayout.PAGE_END);
masterPanel.add(top, BorderLayout.PAGE_START);
masterPanel.add(centre, BorderLayout.CENTER);
add(masterPanel);
}
}
I want to place the button below the "898 Food Restaurant" Jlabel. The setLocation() for button not working.
public class MainMenu extends JPanel{
JLabel picLabel,title;
JButton button;
public MainMenu() throws IOException
{
JPanel panel = new JPanel(new BorderLayout());
BufferedImage myPicture = ImageIO.read(new File("C:\\Users\\seng\\workspace\\FoodOrderingSystem\\ramen-noodles.png"));
Image scaled = myPicture.getScaledInstance(170,170,Image.SCALE_SMOOTH);
picLabel = new JLabel(new ImageIcon(scaled));
title = new JLabel("898 Food Restaurant");
title.setFont(new Font("Serif",Font.ITALIC+Font.BOLD,18));
title.setForeground(Color.BLUE);
button = new JButton("Order Food Now >>");
button.setLocation(40,380);
button.setSize(40,80);
panel.add(picLabel,BorderLayout.CENTER);
panel.add(title,BorderLayout.SOUTH);
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
add(buttonPanel);
add(panel);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
OrderMainPage order = new OrderMainPage();
}
});
}
public static void main(String args[]) throws IOException
{
MainMenu main = new MainMenu();
JFrame frame = new JFrame();
frame.setTitle("898 Food Ordering System");
frame.add(main);
// frame.setSize(120,130);
frame.pack(); // size
frame.setLocationRelativeTo(null); // place frame in center
frame.setVisible(true);
}
}
Each JComponent such as JPanel can only have one layout manager at a time. But since JComponents can be nested you can have different layout managers in your JFrame. Usually that is how you create complex layouts.
Now for your question about button placement. The setLocation won't do anything since your button is in JPanel and it by default uses FlowLayout that ignores location attribute. First step is to set buttonPanel layout to null. But that still might not be enough since the buttonPanel is positioned by another flow layout that will set it's bounds not within the location coordinates of the nested button.
You can always see your JPanel bounds by setting it's background to a different color.
My advice to always try to position your components using layout managers and avoid absolute positioning.
you can use BoxedLayout in place of FrameLayout :
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.awt.image.*;
import javax.imageio.*;
class MainMenu extends Frame {
JLabel picLabel,title;
JButton button;
public MainMenu () {
JPanel panel = new JPanel(new BorderLayout());
try{
BufferedImage myPicture = ImageIO.read(new File("C:\\Users\\seng\\workspace\\FoodOrderingSystem\\ramen-noodles.png"));
Image scaled = myPicture.getScaledInstance(170,170,Image.SCALE_SMOOTH);
picLabel = new JLabel(new ImageIcon(scaled));}catch(Exception e){}
title = new JLabel("898 Food Restaurant");
title.setFont(new Font("Serif",Font.ITALIC+Font.BOLD,18));
title.setForeground(Color.BLUE);
button = new JButton("Order Food Now >>");
panel.add(picLabel,BorderLayout.CENTER);
panel.add(title,BorderLayout.SOUTH);
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
add(panel);
add(buttonPanel);
setLayout (new BoxLayout (this, BoxLayout.Y_AXIS));
setSize(400,400);
setVisible(true);
}
public static void main(String args[]){
MainMenu main = new MainMenu();
}
}
I'm trying to do the following layout, where all JPanels are visible with the exception of panel2 when the program starts. When the user clicks btn1 then JCalendar and panel3 are set to invisible and panel2 becomes visible. The problem I'm having is that panel2 is not showing up with btn1 is clicked. However if i change the borderlayout of panel2 to one that is not being used (in this case WEST) it will show when the button is clicked, but its aligned on the left side and i want it to be centered across the form.
Code:
public class GUI extends JFrame implements ActionListener, PropertyChangeListener
{
private JPanel panel1, panel2, panel3;
private com.toedter.calendar.JCalendar calendar;
private Button btn1, btn2;
private JLabel label1, label2;
public GUI()
{
init();
}
private void init()
{
//panel1 components
panel1 = new JPanel();
btn1 = new JButton("Click me");
panel1.add(btn1);
//panel2 components
panel2 = new JPanel();
label1 = new JLabel("Time:");
label2 = new JLabel("Date:");
panel2.add(label1); panel2.add(label2);
//JCalendar
calendar = new com.toedter.calendar.JCalendar();
//panel3
panel3 = new JPanel();
//Add panels to JFrame
add(panel1, BorderLayout.NORTH);
add(calendar, BorderLayout.CENTER);
add(panel2, BorderLayout.CENTER); //if i set this to WEST it show!!
add(panel3, BorderLayout.EAST);
//event handling
btn1.addActionListener(this);
//hide panel2
panel2.setVisible(false);
pack();
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource().equals(btn1)
{
calendar.setVisible(false);
panel3.setVisible(false);
panel2.setVisible(true); //make panel2 visible
panel2.updateUI();
revalidate();
repaint();
}
}
public static void main(String args[])
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GUI().setVisible(true);
}
});
}
When i click btn1, JCalendar and panel3 is invisible but panel2 does not show
There are a number of issues that I can find...
BorderLayout will only ever allow a single component to occupy any given position. That is, two components can not share the CENTER position at the same time, regardless if one is invisible or not.
You should never call updateUI, this is used to tell UI components that the look and feel has changed that they should update in response to it.
Use revalidate to tell the container that some change has occurred to the layout that it should perform a new layout process...
Before click...
After Click...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class GUI extends JFrame implements ActionListener, PropertyChangeListener {
private JPanel panel1, panel2, panel3;
// private com.toedter.calendar.JCalendar calendar;
private JPanel calendar;
private JButton btn1, btn2;
private JLabel label1, label2;
public GUI() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
init();
}
private void init() {
//panel1 components
panel1 = new JPanel();
btn1 = new JButton("Click me");
panel1.add(btn1);
//panel2 components
panel2 = new JPanel();
label1 = new JLabel("Time:");
label2 = new JLabel("Date:");
panel2.add(label1);
panel2.add(label2);
//JCalendar
calendar = new JPanel();//new com.toedter.calendar.JCalendar();
calendar.setBorder(new LineBorder(Color.RED));
calendar.add(new JLabel("Calendar"));
//panel3
panel3 = new JPanel();
panel3.setBorder(new LineBorder(Color.BLUE));
panel3.add(new JLabel("Panel3"));
panel2.setBorder(new LineBorder(Color.GREEN));
//Add panels to JFrame
add(panel1, BorderLayout.NORTH);
add(calendar, BorderLayout.WEST);
add(panel2, BorderLayout.CENTER);
add(panel3, BorderLayout.EAST);
//event handling
btn1.addActionListener(this);
//hide panel2
panel2.setVisible(false);
pack();
}
public void actionPerformed(ActionEvent ae) {
if (ae.getSource().equals(btn1)) {
calendar.setVisible(false);
panel3.setVisible(false);
panel2.setVisible(true); //make panel2 visible
// panel2.updateUI();
revalidate();
repaint();
}
}
public static void main(String args[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GUI().setVisible(true);
}
});
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
}
}
Now, I'm pretty sure this won't meet you over all requirements (as I see them)...You have at least two options...
Remove the Calendar component and add panel2 to the CENTER position when the button is clicked
Preferably, use a CardLayout
BorderLayout doesn't do overlapping, IIRC none of the layout managers are about "overlapping layout".
You'll need to do it a different way -- try using JLayeredPane with your existing JPanel & BorderLayout as the bottom layer, and then your (optional) panel as the top layer.
See: http://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html
I have a JPanel and JButton on the JFrame.
on runtime add JLabel to JPanel When click JButton.
I use of the following code:
panel.setLayout(null);
jLabel _lbl=new jLabel();
_lbl.setText("Label");
panel.add(_lbl);
panel.validate();
but no display any JLabel in JPanel.
I see you create a JLabel called _lbl:
JLabel _lbl=new JLabel();
but you never add it to your panel. Instead you add a new JLabel with no text to your panel:
panel.add(new JLabel());
This would ofcourse construct an empty label which wont be visible.
Also try calling revalidate() and repaint() on your JPanel instance after adding the JLabel like so:
JLabel _lbl=new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
With this you may also need to call pack() on your frames instance so as to resize the JFrame to fit the new components.
Also please never use a null/Absolute layout this is very bad practice (unless doing animation) and may prove to be problematic and very hard to use.
Rather use a LayoutManager:
A Visual Guide to Layout Managers
or if you only have a single component on the JPanel simply call add(label); as it will stretch to the JPanel size.
UPDATE:
Here is a small sample. Simply adds JLabels to the JPanel each time JButton is pressed:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JavaApplication116 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JavaApplication116().createAndShowUI();
}
});
}
private void createAndShowUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(final JFrame frame) {
final JPanel panel = new JPanel(new FlowLayout());
JButton button = new JButton("Add label");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JLabel _lbl = new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
frame.pack();//so our frame resizes to compensate for new components
}
});
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.SOUTH);
}
}