Функция рисования определена в отдельном потоке, а не в рисовании (Java)
У меня есть три файла, вот основной, под названием 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);
}
}
}
Мой второй файл называется: StartScreen.java. Он содержит мою функцию рисования:
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();
}
}
Мой третий файл короткий:
public class screenTracker {
int screen = 1;
}
Сейчас я просто хочу, чтобы функция рисования в StartScreen.java отображалась на моем JFrame. Я хочу привет, чтобы двигаться по экрану. Я сделал нить т, чтобы экран мог закрыться. Если я избавлюсь от потока t или создам его в Display.java (внутри оператора if, где я устанавливаю закрывающую операцию по умолчанию и добавляю начальный экран в контейнер c), программа рисует то, что я хочу, но Jframe выиграл не близко Я смотрел на многих других веб-сайтах и вопросов, но я не смог понять это. Я новичок в многопоточности и графике в Java,
2 ответа
Много проблем:
Не расширяйте апплет. Апплеты мертвы. Для пользовательской живописи вы бы просто продлили
JPanel
и добавьте панель в рамку.Вы бы переопределить
paintComponent()
в JPanel, а не рисовать ().Метод рисования предназначен только для рисования. НЕ следует:
Прочитайте изображение в методе. Метод рисования вызывается много раз. Вы хотите, чтобы рисование было быстрым, и не следует делать ввод / вывод. Прочитайте изображения в конструкторе вашего класса
создавать темы. Опять же, поскольку метод рисования вызывается несколько раз, и вы не можете его контролировать, поэтому вы не хотите продолжать создавать потоки. Если вы хотите какую-то анимацию, вы должны использовать Swing Timer.
Я предлагаю вам прочитать раздел из учебника Swing по пользовательской живописи. Он содержит рабочие примеры, которые покажут вам, как лучше структурировать ваш код.
Есть также раздел на How to Use Swing Timers
,
Если мы говорим о графике в Java, у нас есть только один поток, отвечающий за это EDT ([1][Event Dispatch Thread]). Другими словами, все, что вы хотите сделать с представлением, будет обрабатываться и должно обрабатываться EDT, да, ваше представление также со всеми заданиями, фреймами...
Но имейте в виду, что это всего лишь один поток, когда этот протектор занят выполнением некоторых вычислений, которые не могут реагировать на пользовательские события, поэтому ваше представление замораживается. Что вы можете сделать в другой ветке, это подготовить данные (в вашем случае прочитайте файл с изображениями)
Для работы в EDT вы используете SwingInvoker.invokelater() или проверьте, находитесь ли вы уже в EDT, с помощью swingutilities.isEventDispatchThread()
[1] https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html