我稍后在我的主方法中使用这样的调用:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Ghi đè
công khai void run() {
Game bird = new Game();
bird.initialize();
}
});
}
然后当我尝试重新绘制时,它不会调用我的 JPanel 中的paintComponent(Graphics g)。但如果我稍后删除调用,然后执行新游戏,它会正常工作吗?
Đây là những gì tôi làm:
private void gameLoop() {
while(this.game) {
this.update();
this.render();
}
}
private void update() {
// TODO UPDATRES
}
private void render() {
super.repaint();
}
Trước khi chương trình đặt gui hiển thị, tôi thêm thành phần bằng cách sử dụng super.add(Màn hình màn hình) và sau đó đặt nó hiển thị, đây là lớp màn hình của tôi:
@SuppressWarnings("nối tiếp")
lớp công khai Màn hình mở rộng JPanel {
trò chơi trò chơi riêng tư;
Màn hình công khai(Trò chơi chim) {
this.game = chim;
}
public void PaintComponent(Graphics g) {
System.out.println("hey");
}
}
Tại sao PaintComponent không vẽ lại khi Invokelater đang chạy?
SRC:
trò chơi.java:
lớp công khai Trò chơi mở rộng Cửa sổ {
riêng tư cuối cùng dài serialVersionUID = 1L;
Màn hình trò chơi riêngMàn hình;
trò chơi boolean riêng tư = sai;
Trò chơi công khai() {
this.gameScreen = Màn hình mới(cái này);
}
khoảng trống công khai khởi tạo() {
super.setGameScreen(this.gameScreen);
this.game = true;
this.gameLoop();
}
private void gameLoop() {
while(this.game) {
this.update();
this.render();
}
}
private void update() {
// TODO UPDATRES
}
private void render() {
super.repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Ghi đè
công khai void run() {
Game bird = new Game();
bird.initialize();
}
});
}
}
cửa sổ.java:
Lớp công khai Cửa sổ mở rộng JFrame {
protectedWindow() {
super.setTitle("test");
super.setSize(this.getPerfectSize());
}
protected void setGameScreen(Màn hình JPanel) {
super.add(màn hình);
super.setVisible(true);
System.out.println("đã thêm");
}
Kích thước riêng tư getPerfectSize() {
trả về Kích thước mới (350, 500);
}
}
màn hình.java:
@SuppressWarnings("nối tiếp")
lớp công khai Màn hình mở rộng JPanel {
trò chơi trò chơi riêng tư;
Màn hình công khai(Trò chơi chim) {
this.game = chim;
}
public void PaintComponent(Graphics g) {
System.out.println("hey");
}
}
Lý do điều này xảy ra là do vòng lặp vô hạn trong gameLoop().
Khi bạn thực thi hàm khởi tạo trò chơi và phương thức khởi tạo() trực tiếp từ phương thức main(), bạn đang ở trên luồng chính. Vòng lặp vô hạn được thực thi trên luồng chính. Khi bạn gọi repaint(), EDT có quyền gọi phương thức PaintComponent().
Khi bạn thực thi hàm tạo Trò chơi và phương thức khởi tạo() từ SwingUtilities.invokeLater(), bạn đặt mã này vào EDT. Sau đó thực hiện một vòng lặp vô hạn trên EDT.
Vì bạn đang chặn EDT bên trong một vòng lặp vô hạn bằng phương thức của mình, điều này có nghĩa là EDT không được phép gọi phương thức PaintComponent(). Nó bị mắc kẹt trong một vòng lặp vô hạn.
Giải pháp cho vấn đề này là đặt gameLoop của bạn trên một chuỗi khác. Một cái gì đó như thế này:
khoảng trống công khai khởi tạo() {
super.setGameScreen(this.gameScreen);
this.game = true;
this.startGameLoop();
}
khoảng trống riêng tư startGameLoop() {
Chủ đề mới(){
công khai void run(){
trong khi(trò chơi) {
cập nhật();
kết xuất();
}
}
}.bắt đầu();
}
Chỉ cần đảm bảo mọi thay đổi đối với gui đều được thực hiện trên EDT. hãy nhìn xemsự đồng thờiVàXoay đồng thờiHướng dẫn để biết thêm chi tiết.
Tôi là một lập trình viên xuất sắc, rất giỏi!