Exception in thread, java.lang.NullPointerException - java

I have been searching for an answer to this for two days now, but that didn't seem to solve much. Mostly because i don't really understand what is causing my error in the first place, nor would i know how to go about fixing the problem.
I've been trying to make an "animation" of sorts, where one of the layers in it spawn circles on the right side of the screen and send them to the left over time. Problem is every time it is meant to spawn a circle, it doesn't appear and i get an error.
Exception in thread "Thread-4" java.lang.NullPointerException
at Ball.draw(Ball.java:39)
at Ball.run(Ball.java:23)
Here is the class that is causing the errors:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class Ball extends Thread{
JPanel drawingPanel;
private int x=400,y=200;
private int dx=-2,dy=0;
private static final int XSIZE=10,YSIZE=10;
Random rdm = new Random();
int y_rdm = rdm.nextInt(440)+30;
public Ball(JPanel jp){
drawingPanel=jp;
dx-=1;
}
public void run(){
draw();
for (int i=0;i<1000;i++){
try{
Thread.sleep(10);
}
catch(InterruptedException e){}
move();
}
}
private void move(){
erase();
changePos();
draw();
}
private void draw(){
Graphics g = drawingPanel.getGraphics();
g.setColor(Color.WHITE);
g.fillOval(x,y_rdm,XSIZE,YSIZE);
g.dispose();
}
private void erase(){
Graphics g=drawingPanel.getGraphics();
g.setColor(drawingPanel.getBackground());
g.fillOval(x,y_rdm,XSIZE,YSIZE);
g.dispose();
}
private void changePos(){
x+=dx;y_rdm+=dy;
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class BallPanel extends JPanel implements ActionListener{
JPanel drawingPanel = new JPanel();
public BallPanel(){
int delay = 300;
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Ball b= new Ball(drawingPanel);
b.start();
}
};
new Timer(delay, taskPerformer).start();
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.io.InputStream;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javazoom.jl.player.Player;
public class Window extends JFrame{
private JLayeredPane layerpane;
private JPanel up, down;
public Window(){
layerpane = new JLayeredPane();
down = new JPanel();
down.setBounds(0, 0, 450, 450);
down.setBackground(new Color(0, 51, 102));
layerpane.add(down, new Integer(1));
BallPanel bp = new BallPanel();
layerpane.add(bp, new Integer(2));
bp.setBounds(0, 0, 450, 450);
bp.setOpaque(!bp.isOpaque());
Animation2 ani2 = new Ani2();
ani2.setBounds(0, 0, 400, 450);
layerpane.add(ani2, new Integer(3));
ani2.setOpaque(!ani2.isOpaque());
getContentPane().add(layerpane, BorderLayout.CENTER);
}
public static void main(String args[]){
JFrame f = new Window();
f.setVisible(true);
f.setSize(450,450);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{
URL url = new URL("file:///C://song.mp3");
InputStream in = url.openStream();
Player pl = new Player(in);
pl.play();
}
catch(Exception e){
e.printStackTrace();
}
}
}
Please tell me if i need to include my other classes, they just seem slightly irrelevant.

The getGraphics method of JComponent returns the Graphics object associated with the Component. But if there is no Graphics object associated it will return null, which is the case in your code.
A Component is associated with a Graphics object only when it is added to a container that is associated with one, or if it is a Top-Level Container (JFrame, JDialog, and JApplet).
Your problem here is that your JPanel is not contained inside any top-level container, so its associated Graphics object is null.
To fix the problem, either make sure you have added the JPanel to a top-level container before you call getGraphics() on it, or instead extend JPanel and override its paintComponent(Graphics g) method to do the drawing (second option is preferred since the paintComponent method is called automatically whenever the parent container needs to be redrawn (e.g. if it was resized, or blocked and unblocked by some other window, ...)).
(By the way, in your BallPanel class which extends JPanel, you define a new JPanel and pass it to Ball's constructor. You should be passing this to the the constructor, since the drawingPanel is never added to any container, but the BallPanel instance itself is. It really doesn't make sense to define a JPanel field inside a class which is itself a JPanel and have the field do the job that the class itself is supposed to do.)

Related

image to show up when I press the button in java swing (error in frame.add( ) )

Hello first of all when I run the program a button appear , when I press the button the image will go from top to down.
I try the code when the image go from top to down , it work very well
BUT when I put all the codes together there is an error in ( frame.add(new AnimationPane() ); )
Question : How to add AnimationPane() to the frame ???
because this is my problem.
The idea that I want to make two scenes , the first one have a button to make go to the second scene which will have an image (it must be pushed from top until reach down ).
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package maincontentpaneswitching;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class MainContentPaneSwitching {
private static class ChangeContentPaneListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// I want to put the image here
JPanel newFrameContents = new JPanel(); //Uses FlowLayout by default.
newFrameContents.add(new JLabel("You have successfully changed the content pane of the frame!", JLabel.CENTER));
/*We assume that the source is a JButton and that the Window is of type JFrame, hence
the following utility method call is possible without letting any errors appear:*/
JFrame frame = (JFrame) SwingUtilities.getWindowAncestor((JButton) e.getSource());
frame.setSize(600, 300);
frame.setContentPane(newFrameContents); //Change the content pane of the frame.
frame.revalidate(); //Notify the frame that the component hierarchy has changed.
frame.add(new AnimationPane() );
frame.pack(); //Resize the frame as necessary in order to fit as many contents as possible in the screen.
frame.setLocationRelativeTo(null); //Place the frame in the center of the screen. As you can tell, this needs its size to calculate the location, so we made sure in the previous line of code that it is set.
frame.repaint(); //Repaint frame with all its contents.
}
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int yPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new URL("https://i.stack.imgur.com/memI0.png"));
Timer timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
yPos += direction;
if (yPos + boat.getHeight() > getHeight()) {
yPos = getHeight() - boat.getHeight();
direction *= +1;
} else if (yPos < 0) {
yPos = 0;
direction *= +1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getHeight()*2 , boat.getWidth() *2);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = getWidth() - boat.getWidth();
g.drawImage(boat, x, yPos, this);
}
}
private static class MainRunnable implements Runnable {
#Override
public void run() {
JButton changeContentPaneButton = new JButton("Click to go to the next image!");
changeContentPaneButton.addActionListener(new ChangeContentPaneListener());
JPanel frameContents = new JPanel(); //Uses FlowLayout by default.
frameContents.add(changeContentPaneButton);
JFrame frame = new JFrame("My application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Tells the frame that when the user closes it, it must terminate the application.
frame.setContentPane(frameContents); //Add contents to the frame.
frame.pack(); //Resize the frame as necessary in order to fit as many contents as possible in the screen.
frame.setLocationRelativeTo(null); //Place the frame in the center of the screen. As you can tell, this needs its size to calculate the location, so we made sure in the previous line of code that it is set.
frame.setVisible(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new MainRunnable()); //Swing code must always be used in the Event Dispatch Thread.
}
}
Introduction
As I said in my comment, I couldn't get the image animation to work properly. At least this code would give you a solid foundation to start with.
Here's the GUI I came up with.
Here's the GUI after you left-click on the button.
If you're going to add comments to your code, put the comments on separate lines from the code. Not everyone has a large monitor and can read 200+ character lines of code.
Explanation
Oracle has a rad tutorial, Creating a GUI With Swing. Skip the Netbeans section.
When I create a Swing GUI, I use the model/view/controller (MVC) pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.
In Swing, the MVC pattern means:
The view reads information from the model
The view may not update the model
The controller updates the model and repaints/revalidates the view.
There's usually not one controller to "rule them all". Each listener controls its portion of the model and the view.
When I put together an application, I code one tiny tiny piece of it, then run tests. I probably ran two to three dozen tests, and this was mostly coded by you.
Model
I created a BoatImage class to read the boat image. It's a separate class, so I can read the image before I start to construct the GUI.
View
I created a JFrame. I created a main JPanel with a CardLayout.
I use a CardLayout to layout the button JPanel and the image JPanel. This way, the JFrame is not constantly changing size.
I create the JFrame and JPanels as separate methods/classes. This makes it much easier for people, including yourself, to read and understand the view code.
Controller
I coded the ChangeContentPaneListener to change from the button JPanel to the image JPanel. This is where you would put your image animation code.
Code
Here's the complete runnable code. I made all the additional classes inner classes so I could post this code as one block.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class MainContentPaneSwitching implements Runnable {
public static void main(String[] args) {
// Swing code must always be used in the Event Dispatch Thread.
SwingUtilities.invokeLater(new MainContentPaneSwitching());
}
private AnimationPane animationPane;
private BoatImage boatImage;
private CardLayout cardLayout;
private JPanel mainPanel;
public MainContentPaneSwitching() {
this.boatImage = new BoatImage();
}
#Override
public void run() {
JFrame frame = new JFrame("My application");
// Tells the frame that when the user closes it, it
// must terminate the application.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.mainPanel = createMainPanel();
frame.add(mainPanel, BorderLayout.CENTER);
// Resize the frame as necessary in order to fit as many contents
// as possible in the screen.
frame.pack();
// Place the frame in the center of the screen. As you can tell, this
// needs its size to calculate the location, so we made sure in the
// previous line of code that it is set.
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createMainPanel() {
cardLayout = new CardLayout();
JPanel panel = new JPanel(cardLayout);
panel.add(createButtonPanel(), "button");
animationPane = new AnimationPane(boatImage);
panel.add(animationPane, "image");
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton changeContentPaneButton = new JButton(
"Click to go to the next image!");
changeContentPaneButton.addActionListener(
new ChangeContentPaneListener(this, boatImage));
panel.add(changeContentPaneButton);
return panel;
}
public JPanel getAnimationPane() {
return animationPane;
}
public void repaint() {
animationPane.repaint();
}
public class AnimationPane extends JPanel {
private static final long serialVersionUID = 1L;
private BoatImage boat;
public AnimationPane(BoatImage boat) {
this.boat = boat;
BufferedImage image = boat.getBoat();
this.setPreferredSize(new Dimension(image.getWidth(),
image.getHeight()));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage image = boat.getBoat();
int x = getWidth() - image.getWidth();
g.drawImage(image, x, boat.getyPos(), this);
}
}
private class ChangeContentPaneListener implements ActionListener {
private int direction, yPos;
private final MainContentPaneSwitching view;
private final BoatImage model;
public ChangeContentPaneListener(MainContentPaneSwitching view,
BoatImage model) {
this.view = view;
this.model = model;
this.direction = 1;
this.yPos = 0;
}
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(mainPanel, "image");
}
}
public class BoatImage {
private int yPos;
private BufferedImage boat;
public BoatImage() {
try {
URL url = new URL("https://i.stack.imgur.com/memI0.png");
boat = ImageIO.read(url); // boat.jpg
} catch (MalformedURLException e) {
e.printStackTrace();
boat = null;
} catch (IOException e) {
e.printStackTrace();
boat = null;
}
this.yPos = 0;
}
public BufferedImage getBoat() {
return boat;
}
public void setyPos(int yPos) {
this.yPos = yPos;
}
public int getyPos() {
return yPos;
}
}
}

unresponsive GUI when class instantiated outside main()

I am starting learning Java, and I wanted to create a simple camera feed viewer using OpenCV.
MyCV class works just fine when instantiated from its own main() method, or when the call is made from within the main() method of a caller class.
I then built a "MyClient" class, with a main() method and a simple GUI (just a JFrame and a JButton, really), because I want MyCV GUI to be shown when pressing a button in MyClient GUI.
The problem is, when the "caller" class has its own JFrame and associated GUI elements, and I click the button, the whole GUI freezes, the frame from MyCV class shows up empty, and both windows become unresponsive.
I've also tried the class with SwingUtilities.invokeLater() , to no avail.
As I said, I'm a novice at Java/Swing, and it looks to me like a paintComponent() issue, but for the life of me, I can't fix it.
Any help is greatly appreciated
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.videoio.VideoCapture;
public class MyCV {
public static void main(String args[]){
MyCV cv=new MyCV();
}
public MyCV(){
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
//-- Video capture structure
VideoCapture feed=new VideoCapture(0);
//-- Mat structures
Mat imgFeed1=new Mat();
Mat imgFeed2=new Mat();
Mat imgFeed3=new Mat();
Mat imgFeed4=new Mat();
imgPanel feedPanel1=new imgPanel(); feedPanel1.setPreferredSize(new Dimension(400,400));
imgPanel feedPanel2=new imgPanel(); feedPanel2.setPreferredSize(new Dimension(400,400));
imgPanel feedPanel3=new imgPanel(); feedPanel3.setPreferredSize(new Dimension(400,400));
imgPanel feedPanel4=new imgPanel(); feedPanel4.setPreferredSize(new Dimension(400,400));
JPanel container=new JPanel(); container.setPreferredSize(new Dimension(800,800));
container.add(feedPanel1);
container.add(feedPanel2);
container.add(feedPanel3);
container.add(feedPanel4);
JFrame f=new JFrame("MyChild");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.add(container);
f.setSize(1300, 800);
f.setVisible(true);
//-- clear resources on exit
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
feed.release();
f.dispose();
}
});
//-- main loop
while(true){
if(!feed.isOpened()) break;
feed.read(imgFeed1);
if(imgFeed1.size().width==0) break;
//-- display images in panels (Colors +Feed +Norm)
feedPanel1.setimagewithMat(imgFeed1);
feedPanel2.setimagewithMat(imgFeed1);
feedPanel3.setimagewithMat(imgFeed1);
feedPanel4.setimagewithMat(imgFeed1);
// repaint frame
container.repaint();
}
}
class imgPanel extends JPanel{
private static final long serialVersionUID=1L;
private BufferedImage image;
//public imgPanel(){ super(); }
private BufferedImage getimage(){ return image; }
public void setimage(BufferedImage newimage){image=newimage; return; }
//-- called method
public void setimagewithMat(Mat newimage){
image=matToBufferedImage(newimage);
return;
}
//--
//--
public BufferedImage matToBufferedImage(Mat matrix) {
int cols = matrix.cols();
int rows = matrix.rows();
int elemSize = (int)matrix.elemSize();
byte[] data = new byte[cols * rows * elemSize];
int type;
matrix.get(0, 0, data);
switch (matrix.channels()) {
case 1:
type = BufferedImage.TYPE_BYTE_GRAY;
break;
case 3:
type = BufferedImage.TYPE_3BYTE_BGR;
// bgr to rgb
byte b;
for(int i=0; i<data.length; i=i+3) {
b = data[i];
data[i] = data[i+2];
data[i+2] = b;
}
break;
default:
return null;
}
BufferedImage image2 = new BufferedImage(cols, rows, type);
image2.getRaster().setDataElements(0, 0, cols, rows, data);
return image2;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
BufferedImage temp=getimage();
if(temp!=null){
g.drawImage(temp, 0, 0, temp.getWidth(), temp.getHeight(), this);
}
}
}
}
MyClient.java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MyClient {
public static void main(String args[]){
//MyCV cv=new MyCV();
//MyClient cli=new MyClient();
JFrame f=new JFrame("My Client");
f.setSize(300, 300);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);
JButton button=new JButton("call Color Detector");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
MyCV cv=new MyCV();
}
});
f.add(button);
}
public MyClient(){
JFrame f=new JFrame("My Client");
f.setSize(300, 300);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);
JButton button=new JButton("call Color Detector");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
MyCV cv=new MyCV();
}
});
f.add(button);
}
}
while(true){
The above is an infinite loop that runs on the Event Dispatch Thread (aka EDT). Swing is single threaded - all events, painting, etc...occur on a single thread (the EDT) - if that Thread is for any reason tied up doing work none of its other responsibilities can occur (in other words, it looks like your user interface locks up). The main method runs on a separate Thread, so you do not see the same behavior (although all calls to Swing components should be placed on the EDT so I would not necessarily call this the correct way to get around the behavior). Three options:
Start one or more new Threads and place any long running tasks within that thread (note that any calls to Swing Components should be placed on the EDT using SwingUtilities)
Use a SwingWorker
If you wish to do something periodically, such as animation, you can use a java.swing.Timer
An example of 1:
//long running task inside a new Thread
new Thread(new Runnable(){
#Override
public void run(){
while(true){
}
}
});

Failing to draw Image to JFrame

first I want to apologize for any mistakes, I'm not speaking english well, I'm new to Java and I'm new to Stackoverflow. Please be kind!
I keep failing to draw a simple image to screen. I tried everything, but I keep failing and I'm getting more and more confused. Here's my Sourcecode:
package com.Animation;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Class1 extends JFrame{
private BufferedImage backgroundImg;
public Class1(){
this.setTitle("Animation");
this.setSize(1080, 720);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
LoadContent();
}
public static void main(String[] args){
new Class1();
}
private void LoadContent()
{
try
{
URL backgroundImgUrl = this.getClass().getResource("Back.jpg");
backgroundImg = ImageIO.read(backgroundImgUrl);
}
catch (IOException ex) {
System.err.println("Fehler!");
}
}
public void Draw(Graphics2D g2d)
{
g2d.drawImage(backgroundImg, 0, 0, null);
}
}
So what happens is, that a JFrame window opens with nothing to see on it. I think that's beacuse the Draw() method doesn't get called. But when I add like "Draw(g2d);" somewhere, I keep getting a NullPointerException. The picture "Back.jpg" is located in the same package as the class. I'm using eClipse and the JRE JavaSE 1.7.
I really hope you can help me, im totally exhausted by all my tries to figure out what's the problem. It would be cool if you could write the correct code into the answers and explain what I've done wrong. Remember, I'm new to all this.
Thanks a lot!
There are a lot of ways to do that. Examples
1) JLabel. //Not recommended
Add the JLabel in your JFrame, then do label.setIcon(backgroundImg);
2) JPanel
Override the paint() method in JPanel(make sure you've added it to your JFrame).
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(backgroundImg, 0, 0, this);
}
Try this. Here I have set the image to a JPanel instead of directly setting it to JFrame.
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
/**
*
* #author Rumesh
*/
public class Test extends JFrame{
public static void main(String[] args) throws IOException {
JFrame frame = buildFrame();
final BufferedImage image = ImageIO.read(new File("1.jpg"));
JPanel pane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
frame.add(pane);
}
private static JFrame buildFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
return frame;
}
}
I don't know if this is what you're searching for:
ImageIcon image = new ImageIcon("src/media/Image.jpg");
JLabel lblImg = new JLabel("", image, JLabel.CENTER);
lblImg.setBounds(..., ..., ..., ...);
add(lblImg);
This way you'll add an image to a JLabel and than place it on the screen. I hope it helps in some way.

How to display different components in a JFrame?

I am very new to Java AWT. My question header must seem ridiculous to you, sorry about that. In my application I have three buttons which display different threads when clicked on. Now I want to add maybe a button or checkboxes or choicelist, etc when clicked on a particular button. For eg, if I click on yes button, it should display a choice list, something like that. How do I achieve something like that? Here is my code so far:
import java.awt.Button;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class AppWindow extends Frame implements ActionListener{
String keymsg = "Test message";
String mousemsg = "Nothing";
int mouseX=30, mouseY=30;
String msg;
public AppWindow(){
//addKeyListener(new MyKeyAdapter(this));
//addMouseListener(new MyMouseAdapter(this));
addWindowListener(new MyWindowAdapter());
}
public void paint(Graphics g){
g.drawString(msg, 150, 100);
}
//Here the window is created:
public static void main(String args[]){
AppWindow appwin = new AppWindow();
appwin.setSize(new Dimension(300,200));
appwin.setTitle("My first AWT Application");
appwin.setLayout(new FlowLayout(FlowLayout.LEFT));
appwin.setVisible(true);
Button yes,no,maybe;
yes = new Button("yes");
no = new Button("no");
maybe = new Button("maybe");
appwin.add(yes);
appwin.add(no);
appwin.add(maybe);
yes.addActionListener(appwin);
no.addActionListener(appwin);
maybe.addActionListener(appwin);
}
#Override
public void actionPerformed(ActionEvent ae) {
// TODO Auto-generated method stub
String str = ae.getActionCommand();
if(str.equals("yes")){
msg = "You pressed Yes";
}
if(str.equals("no")){
msg = "You pressed No";
}
if(str.equals("maybe")){
msg = "You pressed Maybe";
}
repaint();
}
}
class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent we){
System.exit(0);
}
}
Points describing what you should be doing :
As already mentioned by others, better to use Swing over AWT, since Swing is more advanced.
As much as possible, always try to Paint on top of a JPanel or a
JComponent, instead of Painting right on top of your JFrame, by
overriding the paintComponent(Graphics g) method of the said
JComponent/JPanel
Never call setVisible(true) on the JFrame until and unless it's
size has been established. So in general terms, this has to be the
last call, once you are done adding components to the JFrame and
the size of the JFrame has been realized by the LayoutManager.
Inside your actionPerformed(...), instead of writing all if
statement blocks, you should adhere to the if-else if statement
blocks. The benefit of this, over the former is that, at any given
time, only one event will be fired, hence once the said condition is
satisfied, you don't want your code to keep checking other
conditions, which in general is really not a good programming
practice, IMHO.
MOST IMPORTANT THING : Never make calls like pack()/setVisible(...) from within the main method, such calls belong
to the Event Dispatch Thread, and must be done on the same. Please
read Concurrency in Swing for more detail.
Have a look at the example program, for better understanding.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ComponentExample
{
private CustomPanel drawingBoard;
private JPanel contentPane;
private JButton yesButton;
private JButton noButton;
private JButton maybeButton;
private JComboBox cbox;
private ActionListener buttonAction = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
JButton button = (JButton) ae.getSource();
if (cbox.isShowing())
contentPane.remove(cbox);
if (button == yesButton)
{
drawingBoard.setText("You Pressed YES.");
contentPane.add(cbox, BorderLayout.PAGE_END);
}
else if (button == noButton)
drawingBoard.setText("You Pressed NO.");
else if (button == maybeButton)
drawingBoard.setText("You Pressed MAYBE.");
/*
* revalidate()/repaint() is needed
* when the JComponent is added or
* removed from the already
* visible Container.
*/
contentPane.revalidate();
contentPane.repaint();
}
};
public ComponentExample()
{
cbox = new JComboBox(
new String[]{"I GOT IT"
, "I STILL HAD DOUBT"});
}
private void displayGUI()
{
JFrame frame = new JFrame("Component Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setOpaque(true);
contentPane.setBackground(Color.DARK_GRAY);
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(5, 5));
JPanel buttonPanel = new JPanel();
buttonPanel.setOpaque(true);
buttonPanel.setBackground(Color.WHITE);
yesButton = new JButton("YES");
yesButton.addActionListener(buttonAction);
noButton = new JButton("NO");
noButton.addActionListener(buttonAction);
maybeButton = new JButton("MAY BE");
maybeButton.addActionListener(buttonAction);
buttonPanel.add(yesButton);
buttonPanel.add(noButton);
buttonPanel.add(maybeButton);
contentPane.add(buttonPanel, BorderLayout.PAGE_START);
drawingBoard = new CustomPanel();
contentPane.add(drawingBoard, BorderLayout.CENTER);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ComponentExample().displayGUI();
}
});
}
}
class CustomPanel extends JPanel
{
private String msg;
public CustomPanel()
{
msg = "";
setOpaque(true);
setBackground(Color.WHITE);
}
public void setText(String msg)
{
this.msg = msg;
repaint();
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(300, 300));
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString(msg, getWidth() / 3, getHeight() / 3);
}
}
I don't know if I have understood the question well but... couldn't you create those elements and call their setVisible(boolean) methods to make them not visible at first, and them make them visible when user pushes buttons?

Using components in a JApplet that has a continually repainted JPanel

I'm having a major problem with this school assignment; lucky I started it early for once. We've been asked to make a children's math game using a JApplet. So far so good. I have managed to create a JPanel, which is then added to the JApplet and holds all the drawings (the JPanel contents are continually being redrawn). However, whenever I try to add a Swing component such as a JLabel to the JApplet content pane, it does not show or show signs of ever existing. I am completely new to JApplets so please don't be too harsh if it's obvious.
Below is the code:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CountingSheep extends JApplet
{
final int BOARDWIDTH = 800;
final int BOARDHEIGHT = 500;
final int SCREENWIDTH = 800;
final int SCREENHEIGHT = 800;
Dimension boardDim = new Dimension(BOARDWIDTH, BOARDHEIGHT);
Dimension screenDim = new Dimension(SCREENWIDTH, SCREENHEIGHT);
Graphics bufferGraphics;
Image offScreen;
Image backgroundImage;
Image[] sheepImage = new Image[2];
JPanel gameBoard = new JPanel(true);
List<Sheep> sheepArray = new ArrayList<>();
Timer myTimer;
public void init()
{
loadImages();
initScreen();
initBufferGraphics();
initBoard();
initTimer();
sheepArray.add(new Sheep(sheepImage));
myTimer.start();
}
private void loadImages()
{
sheepImage[0] = getImage(getDocumentBase(), "sheep.png");
sheepImage[1] = getImage(getDocumentBase(), "sheep2.png");
backgroundImage = getImage(getDocumentBase(), "bg.jpg");
}
private void initScreen()
{
setSize(800, 600);
setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
}
private void initBoard()
{
gameBoard.setPreferredSize(new Dimension(BOARDWIDTH, BOARDHEIGHT));
getContentPane().add(gameBoard);
}
private void initBufferGraphics()
{
offScreen = createImage(BOARDWIDTH, BOARDHEIGHT);
bufferGraphics = offScreen.getGraphics();
}
private void initTimer()
{
myTimer = new Timer(80, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
timerTick(e);
}
});
}
private void timerTick(ActionEvent e)
{
repaint();
}
public void paint(Graphics g)
{
bufferGraphics.clearRect(0, 0, BOARDWIDTH, BOARDHEIGHT);
bufferGraphics.drawImage(backgroundImage, 0, 0, null);
drawSheepHerd();
moveSheepHerd();
gameBoard.getGraphics().drawImage(offScreen, 0, 0, this);
}
public void drawSheepHerd()
{
for (Sheep s : sheepArray)
{
s.draw(bufferGraphics);
}
}
public void moveSheepHerd()
{
for (Sheep s : sheepArray)
{
s.move();
}
}
}
Thanks in advance, hope you guys can figure it out because I'm stumped.
To summarize some of my recommendations:
Create your own ContentPane class that extends JPanel, that overrides paintComponent(...) and that draws your background image and shows the animation.
Call setContentPane(...) on the JApplet in the init method, passing in an object of this class.
Experiment with different layouts and positionings for the ContentPane.
Make sure that the very first line of the paintComponent(Graphics g) method is: super.paintComponent(g) so that your drawing will be reset each time it paints.
JPanels are opaque by default, and you should leave it as such since contentPanes must be opaque. If you add components on top of the contentPane and want to see the image behind the added components, you may have to make them non-opaque.

Categories