LeatherFace
LeatherFace

Reputation: 476

Painting to a panel using threads in Java

do not know why there is not printing going on here in my run method. I call repaint and override it in the horsethread class. here is my code. When I run the program and hit Run Race it doesnt draw anything to the panel, any ideas?

import javax.swing.JFrame;



public class HorseTester {
  public static void main(String[] args) 
    {
        JFrame frame = new HorsePanel();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.JButton;

import java.awt.GridLayout;
import java.util.ArrayList;

public class HorsePanel extends JFrame
{
    private JPanel panel;
    private JButton reset;
    private JButton quit;
    private JButton run;
    private ActionListener listener;
    private static final int NUM_OF_HORSES = 5;
    public static final int FRAME_WIDTH = 400;
    public static final int FRAME_HEIGHT = 400;
    private ArrayList<Thread> allThreads = new ArrayList<Thread>();
    private ArrayList<HorseThread> horses = new ArrayList<HorseThread>();

    public HorsePanel() 
    {
        //Allocating the memory for horses
        for(int i=0;i<NUM_OF_HORSES;i++)
            horses.add(new HorseThread(i+1));

        //Adding them to thread pool
        for(int i=0;i<NUM_OF_HORSES;i++)
            allThreads.add( new Thread(horses.get(i)));

        createPanel();
        createRunRace();
        createQuit();
        setSize(FRAME_WIDTH, FRAME_HEIGHT);
    }






    public void createRunRace()
    {

        class RunRace implements ActionListener
        {
            public void actionPerformed(ActionEvent rightEvent)
            {
                run.setEnabled(false);
                for(int i=0;i<NUM_OF_HORSES;i++)
                    allThreads.get(i).start();

            }
        }

        ActionListener a = new RunRace();
        this.run.addActionListener(a);
    }

    public void createQuit()
    {           
        class QuitRace implements ActionListener
        {
            public void actionPerformed(ActionEvent rightEvent)
            {
                System.exit(0);             
            }
        }

        ActionListener b = new QuitRace();
        this.quit.addActionListener(b);
    }
    public void createPanel()
    {
        panel = new JPanel(new BorderLayout());
        JPanel drawingPanel = new JPanel();
        this.run = new JButton("Run Race");
        this.quit = new JButton("Quit");
        this.reset = new JButton("Reset");
        JPanel topPanel = new JPanel();


        topPanel.setLayout(new GridLayout(1, 3));
        topPanel.add(run);
        topPanel.add(reset);
        topPanel.add(quit);
        panel.add(topPanel, BorderLayout.NORTH);
        panel.add(drawingPanel, BorderLayout.SOUTH);

        add(panel);
    }
}



import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JComponent;

public class HorseThread extends JComponent implements Runnable
{
public static final int X_START = 10;
public static final int Y_START = 20;

private Horse horse;
private int xpos, ypos;

public HorseThread(int offset) 
{
    xpos = X_START;
    ypos = Y_START * offset;
    horse = new Horse(xpos, ypos);
}

public void paintComponent(Graphics g) 
{
    Graphics2D g2 = (Graphics2D) g;
    horse.draw(g2);
}

/**
 * Run method that thread executes and makes horses go across
 * the screen racing.
 */
public void run() 
{
    repaint();
}
}


import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;

public class Horse 
{
private int xTop;
private int yTop;
public static final int RING_WIDTH = 20;

public Horse(int x, int y) 
{
    xTop = x;
    yTop = y;
}

public void setXY(int dx, int dy)
{
    xTop = dx;
    yTop = dy;
}

public void draw(Graphics2D g2) 
{
    Ellipse2D.Double horse = new Ellipse2D.Double(xTop, yTop, RING_WIDTH,   RING_WIDTH);
    g2.setColor(Color.BLUE);
    g2.fill(horse);
    g2.setColor(Color.WHITE);
    g2.fill(horse);     
}

}

Upvotes: 1

Views: 1644

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347214

The main problem is, HorseThread extends from JComponent, but you never actually add it to anything, therefore it never gets painted.

If, instead, you created a TrackPane and painted each of the horses within the paintComponent method (there's no need for HorseThread to extend from JComponent), you might have better luck.

Also note, that once a Thread has completed, it can not be restarted...

For example...

Horsing around

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class HorseTester {

    public static void main(String[] args) {
        new HorseTester();
    }

    public HorseTester() {
        JFrame frame = new HorsePanel();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public class HorsePanel extends JFrame {

        private JPanel panel;
        private JButton reset;
        private JButton quit;
        private JButton run;
        private ActionListener listener;
        public static final int FRAME_WIDTH = 400;
        public static final int FRAME_HEIGHT = 400;

        private TrackPane trackPane;

        public HorsePanel() {

            createPanel();
            createRunRace();
            createQuit();
            setSize(FRAME_WIDTH, FRAME_HEIGHT);
        }

        public void createRunRace() {

            class RunRace implements ActionListener {

                public void actionPerformed(ActionEvent rightEvent) {
                    run.setEnabled(false);
                    trackPane.start();
                }
            }

            ActionListener a = new RunRace();
            this.run.addActionListener(a);
        }

        public void createQuit() {
            class QuitRace implements ActionListener {

                public void actionPerformed(ActionEvent rightEvent) {
                    System.exit(0);
                }
            }

            ActionListener b = new QuitRace();
            this.quit.addActionListener(b);
        }

        public void createPanel() {
            panel = new JPanel(new BorderLayout());
            trackPane = new TrackPane();
            this.run = new JButton("Run Race");
            this.quit = new JButton("Quit");
            this.reset = new JButton("Reset");
            JPanel topPanel = new JPanel();

            topPanel.setLayout(new GridLayout(1, 3));
            topPanel.add(run);
            topPanel.add(reset);
            topPanel.add(quit);
            panel.add(topPanel, BorderLayout.NORTH);
            panel.add(trackPane, BorderLayout.CENTER);

            add(panel);
        }
    }

    public class TrackPane extends JPanel {

        private static final int NUM_OF_HORSES = 5;

        private ArrayList<HorseThread> horses = new ArrayList<HorseThread>();
        private ArrayList<Thread> threads = new ArrayList<Thread>(25);

        public TrackPane() {
            setBackground(Color.GREEN);
            reset();
        }

        public void reset() {
            // Should dispose of any running threads...
            horses.clear();
            //Allocating the memory for horses
            for (int i = 0; i < NUM_OF_HORSES; i++) {
                horses.add(new HorseThread(this, i + 1));
            }
        }

        public void start() {
            // Should dispose of any running threads...
            threads.clear();
            for (int i = 0; i < horses.size(); i++) {
                Thread thread = new Thread(horses.get(i));
                thread.start();
                threads.add(thread);
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (HorseThread horse : horses) {
                horse.paint(g);
            }
        }

    }

    public class HorseThread implements Runnable {

        public static final int X_START = 10;
        public static final int Y_START = 20;

        private Horse horse;
        private int xpos, ypos;
        private TrackPane track;

        public HorseThread(TrackPane track, int offset) {
            xpos = X_START;
            ypos = Y_START * offset;
            horse = new Horse(xpos, ypos);
            this.track = track;
        }

        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            horse.draw(g2);
        }

        /**
         * Run method that thread executes and makes horses go across the screen
         * racing.
         */
        public void run() {
            track.repaint();
        }
    }

    public class Horse {

        private int xTop;
        private int yTop;
        public static final int RING_WIDTH = 20;

        public Horse(int x, int y) {
            xTop = x;
            yTop = y;
        }

        public void setXY(int dx, int dy) {
            xTop = dx;
            yTop = dy;
        }

        public void draw(Graphics2D g2) {
            Ellipse2D.Double horse = new Ellipse2D.Double(xTop, yTop, RING_WIDTH, RING_WIDTH);
            g2.setColor(Color.BLUE);
            g2.fill(horse);
            g2.setColor(Color.WHITE);
            g2.draw(horse);
        }
    }
}

Also note that Swing is not thread safe, be careful using Threads in this environment ;)

Upvotes: 1

Related Questions