

ゲームの始まりとともに、カウントが始まり、１０秒後に停止、ゲームオーバー画面を、出すことができません。

[code]

    package luna.sexydesign;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    
    class Subthread extends Thread {
    
        private MyPanel2 p2;
    
        public Subthread(MyPanel2 p2) {
            this.p2 = p2;
        }
    
        @Override
        public void run() {// TODO Auto-generated constructor stub
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    //      SwingUtilities.invokeLater(() ->
            p2.setPanel3();
        }
    }
    
    public class ScreenToucher extends JFrame {
    
        int i = 0;
        static int width = 500;
        static int height = 500;
        private MyPanel1 p1;
    
        public static void main(String args[]) {
            ScreenToucher frame = new ScreenToucher("Screen Toucher");
            frame.setVisible(true);
        }
    
        ScreenToucher(String title) {
            setTitle(title);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(100, 100, width, height);
    
            p1 = new MyPanel1();
            MyPanel2 p2 = new MyPanel2(this);
    
            Subthread thread = new Subthread(p2);
            thread.start();
    
            add(p1, BorderLayout.NORTH);
            add(p2, BorderLayout.CENTER);
        }
    
        public void setCount(int count) {
            p1.setCount(count);
        }
    }
    
    class MyPanel1 extends JPanel {
    
        int i;
    
        private JLabel jl1;
    
        MyPanel1() {
            JPanel jp1 = new JPanel();
            jl1 = new JLabel();
            jp1.setBackground(Color.green);
            Integer j = new Integer(i);
            String text = j.toString();
            jl1.setText(text);
            jp1.add(jl1);
            add(jp1);
        }
    
        public void setCount(int count) {
            jl1.setText(Integer.toString(count));
        }
    }
    
    class MyPanel2 extends JPanel {
    
        static int width = 500;
        static int height = 500;
        static int i = 0;
        static int r = 60;
        static int x;
        static int y;
    
        final static Color bc = Color.black;
        final static Color dc = Color.green;
    
        private ScreenToucher owner;
    
        public MyPanel2(ScreenToucher owner) {
            setBackground(Color.black);
            this.owner = owner;
            MouseListener();
            repaint();
        }
    
        void MouseListener() {
            addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent e) {
                    double mouseX = e.getX();
                    double mouseY = e.getY();
                    if (mouseX > x && mouseX < x + 2 * r) {
                        if (mouseY > y && mouseY < y + 2 * r) {
                            repaint();
                            owner.setCount(Count());
                        }
                    }
                }
            });
        }
    
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            x = (int) (Math.random() * width);
            y = (int) (Math.random() * height) + 30;
            if ((x < width - 2 * r) && (y < height - 2 * r)) {
                g.setColor(dc);
                g.fillOval(x, y, r, r);
            } else {
                repaint();
            }
        }
    
        int Count() {
            i += 100;
            return i;
        }
    
        public void setPanel3(){
            MyPanel3 p3 = new MyPanel3();
            add(p3);
        }
    
    }
    
    class MyPanel3 extends JPanel {
    
        public MyPanel3() {
            setBackground(new Color(0,0,0,100));
        }
    
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.white);
            g.drawString("GAME OVER", 100, 200);
        }
    }
    
[/code]


CC BY-SA 4.0
2018-06-23T13:51:01.940
45019
2018-06-25T16:46:45.100
2018-06-25T04:14:09.760
29014
question
java swing
Javaの、タイムラインについて


以下で述べる事項で全て解決するわけではありませんが、取り敢えずJava的に指摘できる事項を2点記載します。(要件的な話は分からないのでここでは記載していません。)

1.  
「ゲームオーバー画面」を表示させようとしている直接のコード、`MyPanel2#setPanel3()`

[code]

    public void setPanel3(){
        MyPanel3 p3 = new MyPanel3();
        add(p3);
    }
    
[/code]

ですが、ここで呼んでいる`add`メソッドのJavaDocは[こちら](https://docs.oracle.com/javase/jp/8/docs/api/java/awt/Container.html#add-
java.awt.Component-)になります。

>
> (前略)このメソッドではレイアウトに関連する情報が変更されるため、コンポーネント階層が無効になります。コンテナがすでに表示されている場合は、追加されたコンポーネントを表示するために、あとで階層を検証する必要があります。

この「検証する必要があります」というのは、日本語訳されていると分かりにくいのですが、要するに
(関連項目にリンクがありますが)[`validate`](https://docs.oracle.com/javase/jp/8/docs/api/java/awt/Container.html#validate--)メソッドを呼べ、ということです。

2.  
上で登場した`MyPanel2#setPanel3()`が行っている処理ですが、(途中まで実装しようとされている形跡があるのでお気づきかも知れませんが)今のコードのままでは描画スレッドとは異なるスレッドでSwingの操作を行っています。  
ので、`SwingUtilities.invokeLater` 内で実行する必要があります。

* * *

以上2点を対応し、次のように同メソッドを書き換えれば、取り敢えずはゲームオーバー画面`MyPanel3`が表示されるのを確認できるかと思います。

[code]

    public void setPanel3() {
        SwingUtilities.invokeLater(() -> {
            MyPanel3 p3 = new MyPanel3();
            // ↓背景色が同じだと表示されたのが分からないので暫定設定
            // p3.setBackground(Color.WHITE);
            add(p3);
            validate();
        });
    }
    
[/code]

冒頭に記載した通り、どのように表示させたいのかという要件は文中からは分からなかったのでそのまま置いています。  
(実際には、ゲーム画面(`MyPanel2`)をゲームオーバー画面(`MyPanel3`)で置き換えたりしたいのかな、と思いましたが、これはコードから伺える意図とは異なるようでした)


CC BY-SA 4.0
2018-06-25T16:46:45.100
45065
2018-06-25T16:46:45.100
2808
45019
answer