Heyo, for my college homework I need to draw some images and race them, but I am stuck even at drawing the images (or in this case, icons). I want to draw ANYTHING (that's why I have the drawLine method, just to test it out) as of right now on one of many JPanels, but my repaint() method does not call my paintComponent method, why?
import java.awt.*;
import javax.swing.*;
import java.lang.Math;
public class Races{
private int numberOfRacers;
public Races(int numberOfRacers){
this.numberOfRacers = numberOfRacers;
JFrame frame = new JFrame("Races - Name Surname");
Icon icon = new ImageIcon("races.jpg");
frame.setLayout(new GridLayout(numberOfRacers, 1));
frame.setSize(icon.getIconWidth()*20, (icon.getIconWidth()*2)*numberOfRacers);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{
Thread.sleep(1000); // Sleeping 1 sec
System.out.println("Sleeping one second for the user!");
}catch(InterruptedException ie){
System.out.println(ie);
}
for(int i = 0; i < numberOfRacers; i++){
innerRacer racer = new innerRacer();
frame.add(racer.panel);
//JLabel iconLabel = new JLabel(icon);
//iconLabel.setHorizontalAlignment(JLabel.LEFT);
//panel.add(iconLabel);
Thread t = new Thread(racer);
t.start();
}
}
public static void main(String args[]){
if(args.length > 0 && Integer.parseInt(args[0]) > 0 && Integer.parseInt(args[0]) < 100){
Races races = new Races(Integer.parseInt(args[0])); // From command line number of racers
System.out.println("Number of racers: " + args[0]);
}else{
Races races = new Races(5); // Default number of racers
System.out.println("Number of racers: 5");
}
}
public class innerRacer extends JPanel implements Runnable{
JPanel panel;
Icon icon;
public innerRacer(){
panel = new JPanel();
panel.setBackground(Color.WHITE);
icon = new ImageIcon("races.jpg");
} //end of innerRacer constructor
@Override
public void run(){
repaint();
System.out.println("TEST");
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawLine(10, 20, 30, 40);
System.out.println("Why is this one not called?");
icon.paintIcon(panel, g, 0, 0);
}
} // end of innerRacer class
} //end of Races class
Thanks in advance.
You've added the JPanel
that innerRacer
contains rather than the JPanel
that innerRacer
is.
Change:
frame.add(racer.panel);
to:
frame.add(racer);
Also I see you are adding components to the frame after setting it to visible. When you do this in AWT/Swing they wont get automatically laid out or painted. You will need to follow with the line:
frame.revalidate();
Alternatively, the setVisible
line could be moved down.
As general notes:
JPanel panel;
in innerRacer
can be deleted.java.awt.EventQueue.invokeLater
.JPanel
without adding any components if you want to paint anything. This appears to be because it is opaque by default. Neither the API docs for JPanel
nor even the OpenJDK source code mention opaqueness. Indeed, it isn't guaranteed. It's just a hack. Prefer setOpaque(true)
to make a component opaque.Comparable
, etc)) isn't great. Use a lambda method, method reference, inner class or just another outer class as appropriate.