質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.98%

  • Java

    12213questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Java初心者:カウントダウン後に画面遷移をしたいです

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 247

unkomaru

score 1

Java初心者の質問です。こちらのサイト https://www.javadrive.jp/tutorial/timer/index1.html を参考にタイマーが5、4、3・・とカウントダウンしていき、-1になった瞬間に"GameOver"と"Score"を表示するようにしたいのですが,
タイマーが止まったままになってしまいうまくいっていない状況です。

以下、ソースコードです。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class TimerTest1 extends JFrame implements ActionListener{

javax.swing.Timer timer;
JLabel label;
int sec;

public void paint(Graphics g){ //この関数をカウントダウン後に呼び出したい

g.setColor(Color.YELLOW);
g.clearRect(0,0,1000,1000);
g.drawRect(0,0,800,8000);
g.setColor(Color.RED);
g.drawString("GameOver",330,40);
g.drawString("Score",330,60);
}

public static void main(String[] args){
TimerTest1 frame = new TimerTest1();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(10, 10, 800, 800);
frame.setTitle("タイトル画面");
frame.setVisible(true);
}

TimerTest1(){
sec = 5;
label = new JLabel();

JPanel labelPanel = new JPanel();
labelPanel.add(label);

timer = new Timer(1000 , this);

getContentPane().add(labelPanel, BorderLayout.WEST);

timer.start();
}

public void actionPerformed(ActionEvent e){
label.setText(sec "");

if (sec ==-1){
timer.stop();

System.exit(1);// これを強制終了ではなくゲームオーバー画面への遷移にしたい

}else{
sec--;
}
}
}


どなたかご教授お願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

質問文のソースコードがJFrame#paintをオーバーライドしている状態で、
ContentPaneにJPanel (labelPanel)を追加しているコードなため、描画処理の依存関係が破綻しています。。
paint処理を治すのが手間なので、アプローチ方法を変更しました。

JFrameのレイアウトマネージャをCardLayoutにして、GameOverパネルに表示を切り替えるサンプルソースコードです。
□注意点
Swingのコンポーネント(JFrame/JPanel)を継承したクラスでpaintメソッドはオーバライドしないでください。
どうしてもオーバーライドしたい時はpaintComponentをオーバーライドしてください。

Q107683.java

import java.awt.CardLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

@SuppressWarnings("serial")
public class Q107683 extends JFrame {

    private Timer timer;
    private int countdown_sec = 5;// 変数名をsecから変更
    private CardLayout card = new CardLayout(0, 0);

    public static void main(String[] args) {
        // 画面の生成はSwingUtilities.invokeLaterを使用してスレッドセーフにしてくださいな。
        SwingUtilities.invokeLater(() -> {
            Q107683 frame = new Q107683();
            frame.setBounds(10, 10, 800, 800);
            frame.setVisible(true);
        });
    }

    Q107683() {
        // setDefaultCloseOperationは一番先頭で
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("タイトル画面");
        setLayout(card);
        JPanel labelPanel = new JPanel();
        JLabel label = new JLabel();
        labelPanel.add(label);
        add(labelPanel, "title_window");
        timer = new Timer(1000, (e) -> {
            label.setText(String.valueOf(countdown_sec));
            if (countdown_sec ==-1){
                timer.stop();
                showPanel("gameover_window");
                return;
            }
            countdown_sec--;
        });
        JPanel game_over = new GameOver();
        add(game_over, "gameover_window");
                // コンストラクタ内からTimer(別スレッド)をスタートするのはスレッドの可視性の関係上あまり良くないです。
                // frame.setVisible(true);後に別のメソッドより、timer.startを呼び出す形に変更したほうがいいです。
        timer.start();
    }

    public void showPanel(String name) {
        card.show(getContentPane(), name);
    }

}


GameOver.java

import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Color;

@SuppressWarnings("serial")
public class GameOver extends JPanel {
    /**
     * Create the panel.
     */
    public GameOver() {
        //背景を黄色にする。
        setBackground(Color.YELLOW);
        setLayout(new BorderLayout(0, 0));
        // drawStringはコンポーネントの領域を計算する必要があるので、文字列を表示するだけならJLabelの方がいいです。
        JLabel lblGameOver = new JLabel("GameOver");
        // 文字色を赤色にする。
        lblGameOver.setForeground(Color.RED);
        lblGameOver.setVerticalAlignment(SwingConstants.TOP);
        lblGameOver.setHorizontalAlignment(SwingConstants.CENTER);
        add(lblGameOver, BorderLayout.NORTH);

        JLabel lblScore = new JLabel("Score");
        lblScore.setForeground(Color.RED);
        lblScore.setHorizontalAlignment(SwingConstants.CENTER);
        add(lblScore);
    }
}

□補足
作った画面のSwingのコンポーネント配置が知りたい時は画面をクリックした状態で、Ctrl+Shift+F1キーを押下すると、Swingのコンポーネントツリーがコンソールに出力されます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/08 14:34

    ありがとうございます!
    自分の思ってたような形に動いてくれました!

    キャンセル

+1

要はsec == -1のときにpaint内の「画面を黄色に染めて、赤文字でGameOverやScoreを表示」が出来ればいいんですよね?

public void paint(Graphics g){ // secが-1でないときは何もしないようにすればよい
  if(sec == -1) {
    g.setColor(Color.YELLOW);
    g.clearRect(0,0,1000,1000);
    g.drawRect(0,0,800,8000);
    g.setColor(Color.RED);
    g.drawString("GameOver",330,40);
    g.drawString("Score",330,60);
  }
}

paintというのは基本的に「プログラマ」が呼び出すのではなく、「OS」や「Java」が勝手に呼び出すので、任意のタイミングでこちらから呼び出す、というものではありません。そのため、「勝手なタイミングで呼ばれてもいいように内部の処理を書く」というのが正しい手法です。
「プログラマ」から確実に「今この瞬間paintを実行してくれ!」という方法は無いですが、「次暇になったときにpaintを実行してくれ」というお願いは可能です。それはrepaint()です。これを呼び出せば、できるだけ早いタイミングでpaintが実行されます。なので、カウントダウンが終わり、secが-1になったときにpaintを予約するためにrepaintを呼び出しておきましょう。

if (sec ==-1){
  timer.stop();
  repaint();
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/08 14:35

    迅速な回答ありがとうございます!
    repaint();なんていう便利なものがあったのですね・・

    キャンセル

0

System.exit(1);の代わりにthis.repaint();を呼べば、一応画面は更新できますよ。
あとは、状態を管理して、いつどういう表示を行うか決めてみてください。
昨日Timerを使う例を別な質問に回答しましたので、そちらも参考にしてみてください。

https://teratail.com/questions/107417

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/08 14:44

    回答ありがとうございます!
    ワニワニパニックの方も参考にしたいと思います・・!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    12213questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。