Why isn't the paintComponent method being called? - java

The messages that ought to be printed in the printComponent method are not printed. I am having the impression that the paint method is not called. If not, why not?
import java.util.*;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.swing.*;
import javax.imageio.*;
public class Main extends JFrame{
CustomComponent cc;
public static void main(String[] args) {
Main m = new Main();
}
public Main(){
setTitle( "Diverse Testari 7");
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600, 400);
cc = new CustomComponent();
cc.setImage("rgbcmy.jpg");
add(cc);
pack();
setVisible( true );
}
}
class CustomComponent extends JPanel{
BufferedImage img = null;
public void setImage( String str ){
try {
img = ImageIO.read( new File( str ) );
System.out.println("SUCCESS!");
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
System.out.println("altceva");
super.paintComponent(g);
System.out.println("ceva");
}
}

Add this code in your Main constructor:
new Thread(new Runnable() {
public void run() {
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException e) {}
}
}).start();
paintComponent will only be called when you repaint();.
Also, NEVER NEVER NEVER use setLayout(null);. See here.
This code will continually repaint the panel, so it will continually call paintComponent. This is good because it will always keep the panel updated. You could also just call repaint(); when you change what's in the panel.

Related

drawing image in jframe game

I'm having some trouble getting an image drawn in java. There are no console errors and it prints 'drawing'. I believe I am loading the image wrong but I can't figure out the right way. If someone could tell me the correct way that would be great.
package platformer;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.util.List;
import java.util.ArrayList;
import javax.swing.Timer;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.awt.Image;
public class test2 extends JPanel implements KeyListener, ActionListener {
int Width = 1000;
int Height = 600;
private static Image offScreenBuffer;// needed for double buffering graphics
private Graphics offScreenGraphics;// needed for double buffering graphics
private BufferedImage[] img = new BufferedImage[1];
public test2() {
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(img[0],0,0,null);
}
public void timer1() {
int delay = 30; // milliseconds
new Timer(delay, this).start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent evt) {
}
public static void main(String args[]) throws InterruptedException, Exception {
test2 test2 = new test2();
JFrame frame = new JFrame("platformer");
frame.setSize(test2.Width, test2.Height);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.green);
frame.add(test2);
frame.setResizable(false);
frame.addKeyListener(test2);
test2.init();
test2.timer1();
// What to do after the program starts
while (true) {
test2.repaint();
}
}
public void init() {
try {
URL url = new URL("platform.png");
img[0] = ImageIO.read(url);
} catch (IOException e) {
}
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
Swing has an infinite loop that does event handling for you. You don't need the while(true) loop. You should call frame.setVisible(true) after all of your UI is configured. I mean that it should be the last thing in main(). Also, you should do this on the UI thread with
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
So main() should look like
public static void main(String args[]) throws InterruptedException, Exception {
test2 test2 = new test2();
JFrame frame = new JFrame("platformer");
frame.setSize(test2.Width, test2.Height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.green);
frame.add(test2);
frame.setResizable(false);
frame.addKeyListener(test2);
test2.init();
test2.timer1();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
}
However, the main problem is the try... catch in init() which ignores exceptions. You should never leave a catch empty. At the very least you should print a stacktrace. Better yet, add the appropriate exceptions to the methods throws clause like this:
public void init() throws IOException {
URL url = new URL("platform.png");
img[0] = ImageIO.read(url);
}
Note if a problem occurs, you will know about it immediately.

How to fix when JPanel.repaint() doesn't call paintComponent //nothing I found that work

I'm going to create a JPanel Howto, which is rendering 6 images in order and then add the back button to go back to title.
I'm trying check if it call paintComponent method in class howto or not. And it doesn't so the value i is still 0 and end up stuck in loop
Here's my Howto class
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JPanel;
import Audio.HitSound;
import Graphic.DrawingUtility;
public class Howto extends JPanel implements Runnable{
private JButton back;
private static int i;
public Howto(){
this.setPreferredSize(new Dimension(800, 600));
this.setLayout(null);
repaint();
HitSound h = new HitSound();
i=0;
this.setVisible(true);
}
public void run() {
// TODO Auto-generated method stub
try {
while(i<6)
{
GameManager.frame.repaint();
Thread.sleep(10);
System.out.println("i: " + i);
}
} catch (Exception e) {
// TODO: handle exception
Thread.interrupted();
}
}
public void paintComponent(Graphics g){
if(GameManager.thread.isAlive()){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(DrawingUtility.getHowto(i), 0, 0, 800, 600,null);
i++;
}
}
}
and this what in my GameManager class
public static void startThread() {
thread = new Thread(howto);
thread.start();
}
public static void runHowto() {
howto = new Howto();
howto.setVisible(true);
frame.switchScene(howto);
howto.repaint();
startThread();
while (thread.isAlive()) {
//frame.repaint();
}
if (!thread.isAlive()) {
JButton back = new JButton();
back.setBorderPainted(false);
back.setContentAreaFilled(false);
back.setFocusPainted(false);
back.setOpaque(false);
back.setBounds(640, 446, 132, 132);
back.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
HitSound h = new HitSound();
h.play(3);
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
GameManager.goToTitle();
}
});
}
but when I call runHowto(); it's still looping and i == 0 and not increase i
So I think it's may have problem with paintComponent and repaint method
So please help me fixing it Thanks in advance :)
The while (thread.isAlive()) loop blocks the AWT Event Dispatch Thread (EDT).
You need to return to the event dispatch loop from runHowto. Have your Howto task to post back to the EDT with java.awt.EventQueue.invokeLater to construct your back button and presumably add it to a panel.

Java - Response from button

I've tried many things to get this button bb or continue to output "Hey Buddy", yet it still does not work. It is displayed yet when i press it nothing happens. The code uses both java swing a awt.
package Game;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import java.util.concurrent.TimeUnit;
import javax.swing.JButton;
public class base extends java.applet.Applet implements ActionListener, TextListener {
//Graphics
//Graphics
#SuppressWarnings("deprecation")
public static JButton bb = new JButton("Continue");
public TextArea ta = new TextArea(30, 140);
TextArea tb = new TextArea(3, 130);
public int counter = 0;
//main class
public static void main(String[] args) {
Frame f = new Frame("---Quest---");
base ex = new base();
ex.init();
f.add("Center", ex);
f.pack();
f.show(true);
bb.addActionListener(ex);
}
public void actionPerformed1(ActionEvent Continue) {
bb.addActionListener(this);
counter++;
if (Continue.getSource() == bb && counter == 1) {
tb.append("Hey Buddy");
}
}
//graphics
public void init() {
bb.addActionListener(this);
Panel p;
setLayout(new BorderLayout());
p = new Panel();
ta.append("Hey");
bb.addActionListener(this);
p.add(bb);
p.add(ta);
p.add(tb);
p.setBackground(Color.blue);
ta.setBackground(Color.cyan);
ta.setEditable(false);
add("Center", p);
p.setVisible(true);
}
//time class
public static int nap(int time) {
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
//end of code
#Override
public void textValueChanged(TextEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
The whole code is buggy.Read the Comments inline.
1.Idk why you are adding actionListener to the button 4 times(Keep one)
2.You have to have to change the actionPerformed1 to actionPerfromed as you are implementing the ActionListener and assigning this to button's ActionListener
public TextArea ta = new TextArea(30, 140);
TextArea tb = new TextArea(3, 130);
public int counter = 0;
//main class
public static void main(String[] args) {
f.show(true);//show is deprecated use setVisible(true) instead;
bb.addActionListener(ex);//1
}
public void actionPerformed1(ActionEvent Continue) {//have to change the actionPerformed1 to actionPerfromed
bb.addActionListener(this);//2 What is this assigning inside actionPerformed Need to be removed
counter++;
if (Continue.getSource() == bb && counter == 1) {
tb.append("Hey Buddy");
}
}
//graphics
public void init() {
bb.addActionListener(this);//3
Panel p;
setLayout(new BorderLayout());
p = new Panel();
ta.append("Hey");
bb.addActionListener(this);//4
p.add(bb);
p.setVisible(true);//already called a show for JFrame why you want to set Visible of Panel
}

JPanel problem - repaint on resize on normal look

I have strange problem with JPanel. I am trying to show svg image ( SVG_class extends JSVGCanvas from batik jar). Problem is when I start this program I get this
and when I resize with pointer frame a little I get normal picture like this
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
import javax.swing.*;
import org.apache.batik.swing.JSVGCanvas;
public class Main {
static JScrollPane scrollpane;
// The frame.
protected JFrame frame;
public static void main(String[] args) {
final JFrame f = new JFrame("frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(700, 500);
f.setBackground(Color.blue);
SVG_class svg = new SVG_class();
JPanel p = new JPanel();
p.setSize(new Dimension(700, 500));
p.add(svg);
p.setBackground(Color.red);
scrollpane = new JScrollPane(p);
scrollpane.setPreferredSize(new Dimension(700, 500));
Container cont = f.getContentPane();
cont.add(scrollpane);
f.setVisible(true);
}
}
public class SVG_class extends JSVGCanvas {
private List<Type> list;
private int rad;
public boolean red_dot(int iX, int iY, String sX, String sY){
boolean b;
int x,y;
x=Math.abs(iX-(int)Double.parseDouble(sX));
y=Math.abs(iY-(getSize().height-(int)Double.parseDouble(sY)));
System.out.println("iX="+iX+" iY="+iY+" sX="+sX+" sY="+sY+" x="+x+" y="+y);
b=(x<=rad) &&(y<=rad);
return b;
}
public SVG_class(){
try {
this.list=CSV.getCSV("map2");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String fileName = "map2";
File file = new File("C:\\Users\\Gigabyte\\Desktop\\SVG\\"+fileName+".svg");
try {
this.setURI(file.toURL().toString());
this.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
//
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent e) {
boolean found=false;
// System.out.println("pritisnuo si x="+e.getX()+" y="+e.getY());
int x,y;
for(int i=0; i<list.size() && !found;i++ ){
found=red_dot(e.getX(), e.getY(), list.get(i).getX(), list.get(i).getY());
}
if (found) {
System.out.println("pritisao!!!!");
}
System.out.println(" ");
}
});
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Can someone tell me what is mistake ? I tried with p.repaint but it didn't help.
Posting the source for SVG_class might make it easier to see what the problem is.
As it is, I suspect the problem is because you're not explicitly telling it what kind of layout to use.
If you want svg to take up the whole window you could do p.setLayout(new GridLayout(1, 1)); after you create p.
You should call the f.setSize(700, 500); just before showing.
SVG_class has probably set its size in the constructor. Don't do that and define the size at after calling the constructor.
EDIT: Try adding
f.pack();

Problems with a SwingWorker

I'm trying to get a SwingWorker to work.
I've the following code at the moment:
public class ImageWorker extends SwingWorker<Void, Void> implements KeyListener
{
private JLabel imageLabel;
private ImageIcon basicImage;
private ImageIcon whiteImage;
public static void main(String[] args)
{
new ImageWorker();
}
public ImageWorker()
{
final JFrame frame = new JFrame();
imageLabel = new JLabel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.getContentPane().add(imageLabel);
frame.setVisible(true);
try
{
basicImage = new ImageIcon(ImageIO.read(new File("src\\img\\basis1.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
whiteImage = new ImageIcon(ImageIO.read(new File("src\\img\\wit.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
}
catch(IOException ex)
{
ex.getMessage();
}
this.execute();
}
#Override
protected Void doInBackground()
{
try
{
while (true)
{
displayImage(basicImage);
Thread.sleep(1000L);
if(isCancelled())
return null;
}
}
catch(InterruptedException e)
{
e.getMessage();
}
return null;
}
private void displayImage(final Icon image)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
imageLabel.setIcon(image);
}
});
}
I was expecting the images to appear in the JLabel, but I only see the JFrame popping up. The files are loaded correctly Ive tested that in another setup.
Any pointers?
Here is an example using a Timer rather than using the SwingWorker which really isn't appropriate to your situation. Note that it's not too different from your existing code.
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class ImageWorker implements KeyListener
{
private JLabel imageLabel;
private ImageIcon basicImage;
private ImageIcon whiteImage;
private boolean isBasic = true;
private int delay = 1000; //milliseconds
private Timer timer;
public static void main(String[] args)
{
new ImageWorker();
}
public ImageWorker()
{
final JFrame frame = new JFrame();
imageLabel = new JLabel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.getContentPane().add(imageLabel);
frame.setVisible(true);
try
{
basicImage = new ImageIcon(ImageIO.read(new File("src\\img\\basis1.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
whiteImage = new ImageIcon(ImageIO.read(new File("src\\img\\wit.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
}
catch (IOException ex)
{
ex.getMessage();
ex.printStackTrace();
}
frame.addKeyListener(this);
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(isBasic) {
//display basic image
imageLabel.setIcon(basicImage);
}
else {
//display white image
imageLabel.setIcon(whiteImage);
}
//toggle the flag
isBasic = !isBasic;
}
};
//use a timer instead of SwingWorker
timer = new Timer(delay, taskPerformer);
timer.start();
}
#Override
public void keyPressed(KeyEvent e)
{
//key pressed, we want to stop toggling so stop the timer
timer.stop();
//do whatever else you were doing to set the value for isCancelled();
}
#Override
public void keyReleased(KeyEvent e)
{
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e)
{
// TODO Auto-generated method stub
}
}
A SwingWorker is not appropriate for your situation look into a Timer in the swing package. Here is a link to the API: http://download.oracle.com/javase/6/docs/api/javax/swing/Timer.html
You have the timer run and change an image every second since that is what you need.
Also, whenever you have exceptions, print out a stacktrace or the message at least. Otherwise you won't know if an exception occurs and is caught.

Categories