jacob
jacob

Reputation: 3

Paint function defined in separate thread not drawing (Java)

I have three files, here is the main one, titled Display.java:

import java.awt.*;
import javax.swing.*;

public class Display{
    static JFrame main = new JFrame("hello");
    static Container c = main.getContentPane();
    static StartScreen start = new StartScreen();
    static screenTracker track = new screenTracker();

    public static void main(String[] args) {
        main.setSize(new Dimension(1920,1080));
        main.setVisible(true);
        if(track.screen==1) {
        main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        c.add(start,  BorderLayout.CENTER);
    }
    }
}

My second file is titled: StartScreen.java. It contains my paint function:

import java.applet.Applet;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class StartScreen extends Applet{
    private static final long serialVersionUID = 1L; 
    int x = 0;
    static Container c = Display.c;
    static Color gray = new Color(128,128,128);
    public void paint(Graphics g) {
        Thread t = new Thread() {
            @Override
            public void run() {
        while(true) {
        c.setBackground(gray);
        g.clearRect( 0 , 0 , getWidth() , getHeight() );
        BufferedImage img1 = null;
        BufferedImage img2 = null;
        BufferedImage img3 = null;
        try {
            img1 = ImageIO.read(new File("images/img1.png"));
            img2 = ImageIO.read(new File("images/img2.png"));
            img3 = ImageIO.read(new File("images/img3.png"));
        }
        catch(IOException e) {
            g.drawString("bad", 200, 200);
        }
        String title1 = "hello: ";
        String title2 = "Gamee ";
        String title3 = "people";
        Color pink = new Color(244,66,182);
        Color black = new Color(0,0,0);
        g.setColor(black);
        g.setFont(new Font("TimesRoman", Font.PLAIN, 50));
        g.drawString(title1, x+600, 200);
        g.setColor(pink);
        g.setFont(new Font("TimesRoman", Font.ITALIC, 50));
        g.drawString(title2, 860, 200);
        g.setFont(new Font("TimesRoman", Font.PLAIN, 50));
        g.setColor(black);
        g.drawString(title3, 960, 200);
        g.drawImage(img1, 200, 250, null);
        g.drawImage(img2, 700, 150, 1000, 750, null);
        g.drawImage(img3, 500, 250, null);
        x++;
        try {
            sleep(10);  // milliseconds
         } catch (InterruptedException ex) {}
        }
            }
        };
        t.start();
    }
}

My third file is short:

public class screenTracker {
int screen = 1;
}

Right now I just want the paint function in StartScreen.java to display on my JFrame. I want hello to move across the screen. I made the thread t so the screen can close. If I get rid of the thread t, or create it in Display.java (inside the if statement, around where I set the default close operation and add the startscreen to the container c) the program draws what I want, but the Jframe won't close. I have looked in a lot of other websites, and questions, but I haven't been able to figure this out. I am new to multithreading and graphics in java,

Upvotes: 0

Views: 277

Answers (2)

camickr
camickr

Reputation: 324108

Many problems:

  1. Don't extend Applet. Applets are dead. For custom painting you would simply extend JPanel and add the panel to the frame.

  2. You would override paintComponent() in the JPanel, not paint().

  3. A painting method is for painting only you should NOT:

    1. read the image in the method. The painting method gets called many times. You want painting to be fast and should not be doing I/O. Read the images in the constructor of your class

    2. be creating Threads. Again since the painting method is called multiple times that you can't control you don't want to keep creating Threads. If you want animation of some kind then you should be using a Swing Timer.

I suggest you read the section from the Swing tutorial on Custom Painting. It contains working examples that will show you how to better structure your code.

There is also a section on How to Use Swing Timers.

Upvotes: 1

vmrvictor
vmrvictor

Reputation: 723

If we speak about graphics in java we have only one thread responsible for It the EDT ([1][Event Dispatch Thread]). In other words whatever you want to do with the view will be handled by and has to be handled by EDT, yes your view also with all setbackroungs, frames...

But be aware, it is only one thread, when this tread is busy doing some calculation cannot react to the user events, so your view will freezee. What you can do in another thread is to prepare the data (in your case read the file images)

To work in the EDT you use SwingInvoker.invokelater() or check if you are already in EDT by using swingutilities.isEventDispatchThread()

[1] https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html

Upvotes: 1

Related Questions