Java Basic JUnit 〜テストの作り方〜

イントロダクション

今までに触れたことのない技術(OpenCvなど)を使おうと思ったら色々と動かしてみたいのが人情、そんな時に使えるフレームワークの使い方を記載します。
その名はJUnitです。
具体的には、参考資料、参考サイトなどを見ながらプログラムを作成する、作成したプログラムの。。。

  1. メソッドのみを動かす。
  2. 全体を動かす。
  3. 一部切り出して動かす。

上記のことが、本体プログラムに影響せず実行できるところが良いところです。

JUnit

JUnitは、「テスト用のフレームワーク」として有名なものです。「テスティングフレームワーク」という言い方が多いと思います。

英語で「Testing framework」といえばなんとなくわかるけど、日本語だとなんか別な意味があるのでは?と疑ってしまうのは筆者だけでしょうか?
とりあえず、『いろんな言い方をして混乱するのは良くない』といいたいだけです。失礼。。。

この記事のタイトルにある「テストスイート」という言葉も「テストケース」を意味するものです。JUnitでの「@Test」のついたメソッドのことです。
色々な言い方があり混乱してしまいがちですが「何を指しているのか?」に注意すればあまり混乱しないと思います。

JUnitの概要

JUnit(本家サイトへのリンクです)は、ズバリ「アノテーション『\@』」でテストの準備、テスト、テストの後始末をっコントロールできる便利なフレームワークです。いろんな書籍でいろいろ書いていると思いますが、基本は「\@Test」「/@Before」「\@After」のアノテーションをつければ動きます。もっと言うと「\@Test」アノテーションのみでよいです。※今回実装したJUNIT5ではBeforEach, AfterEachのように名前が変わっています。

JUnitの設定方法

IntelliJ IDEAでの設定方法です。

Mavenを使用して、pom.xmlに以下のような記述を追加、再ビルド(Mavenビルド)を行う。"dependencies"タグの中に追加する
タグの階層があるので、ちょっと混乱しがちですが、projectタグの直下に記述します。

<dependencies>
  <!-- この部分がJUNITの記述 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

追伸、ほかのOpenCVとかLWJGLなどもこのdependenciesタグの中に追記します。

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd
                                http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>jp.zenryokuservice</groupId>
    <artifactId>TextRPG</artifactId>
    <version>0.8-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>net.objecthunter</groupId>
            <artifactId>exp4j</artifactId>
            <version>0.4.8</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>

コードの実行

ズバリ、「@Test」をメソッドの頭につけるだけです。

import jp.zenryoku.practice.sample.SampleLv1Hello;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.Assert.assertEquals;

/**
 * サンプルテストクラス
 */
public class SampleTest {
    /** テスト対象クラス */
    private SampleLv1Hello target;

    /** テストの準備 */
    @BeforeEach
    public void init() {
        target = new SampleLv1Hello();
    }

    @Test
    public void test01() {
        System.out.println("Hello JUnit");
        target.testMethod();
    }

    @Test
    public void test02() {
        target.testMethod(1, 2);
        target.testMethod(4, 9);
        target.testMethod(5,8);
        target.testMethod(6, 7);
    }

    @Test
    public void test03() {
        // 返却値が正しいか確認する
        assertEquals(2, target.testMethod(1, 1, true));
        assertEquals(2, target.testMethod(5, 3, false));
        assertEquals(3, target.testMethod(1, 1, true));
    }
}

Javaで開発をしていたらすぐに目にすると思うのですが、改めて使い方をみてみようと思います。
<作業動画>

手順(Eclipse)

  1. EclipseにJUnit4(JARファイル)をビルドパスにつなぐ
  2. テストクラスを作る
  3. 実行する
  4. あとは色々といじって遊ぶ

サンプルコード(JUnit4 ※古い)

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.junit.runners.JUnit4;
import org.opencv.core.Mat;

import zenryokuservice.gui.lwjgl.kakeibo.opnecv.ReceiptCv;

/** JUnit4を使う宣言 */
@RunWith(JUnit4.class) 
public class ReceiptCvTest {
    /** テスト対象のクラスをフィールドで保持する */
    private ReceiptCv test;
    /**
     * Bforeアノテーションで各テストを実行する前に
     * 実行するメソッド
     * テストのためのデータセットを用意したり、クラスの呼び出しを行なったりする
     */
    @Before
    public void setup() {
        test  = new ReceiptCv();
    }
    @After
    public void terminated() {
        // テストの終了処理(メモリ開放)
        test = null;
    }
    /** テストケース1 */
    @Test
    public void test1() {
        test.helloCv();
    }
    /** テストケース2 */
    @Test
    public void test2() {
        // イメージファイルを読んでみる
        Mat matrix = test.loadImg("download-1.jpg");
        System.out.println(matrix.dump());
    }
}

テストケースの考え方

じゃんけんゲームを作成しているときに、入力チェックのメソッドを作成したとき。

このメソッドをテストするための「テストケース」を作成するときのことを解説しています。

関連ページ一覧

Java Basic

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Java Introduction〜初めてのJava〜

イントロダクション

Java言語を始めようとしている人向けに記載しています。「早くプログラムが書きたい!」という人は次のページに行ってもおっけ〜です。「次のページ」では初めのプログラム「ハローワールド」をやっています。

Javaを学習して何をするのか?
それは、自身が決めることですが、少なくてもどんな方向へ進みやすいのかを紹介します。

Introduction

It is written for people trying to get started with the Java language. People who say "I want to write a program as soon as possible" can also go on to the next page. On the next page I will do the first program "Hello World".

What do you do learning Java? That is what you decide, but I will show you what direction it is easy to move in at least.

Javaとは?

1990年頃にSun MicroSystemsによって作られたプログラム言語です。C言語が母体になっています。細かいことはWikiを参照してください。

What's Java?

It is a programming language made by Sun MicroSystems around 1990. C language is the mother body. Please see the wiki for details.

どんなことに使っているの?

ゲーム〜銀行のATMまでいろんなところで使用しています。スマートフォンのAndroidなどは、Javaでアプリが作られています。

Java using for

Games, ATM, Networking... many scene. And google android app is using Java.

 

なんでJavaをやるのか?

理由はなんでもいいと思います。こういう時の「理由」ってのはあまり大事ではないと思います。というかやってから考えても遅くありません。(持論です)

<Javaをやるメリット>

  1. 理論的な考え方が身につく
  2. ゲームが作れる
  3. 手に職がつく
  4. 世界の最先端技術に触れることができる

と思います。スクリーンショット 2018-10-20 19.48.16.png

Why Java?

Reason is not important for learn java. I think, if you need a reason, it is better that think about that reason after learn java. I think so.

<Good point of learing java>

  1. Get a theoretical way of thinking
  2. be able to create a game
  3. get a job in your hand

Javaを学ぶ時のロードマップ

  1. JavaSE(スタンダードエディション)を理解する
    1. 文法
    2. クラスの扱い方
    3. クラスの継承関係
  2. JavaSE + Web(JavaEE)など
    1.  Java + DBアクセス(Webサーバー)
    2. Java + Network(CORBA, Socket通信など)
  3. 自分で1〜10まで設計、実装、テストまでできるようになる

だいたいこんな感じです。

RoadMap of Java Road

  1. Learn JavaSE(Standard Edition)
    1. Grammer
    2. Usage of class
    3. Class inheritance
  2. JavaSE + Web(JavaEE)
    1. Java + DB Access( WebServer)
    2. Java + Networking(CORBA, Socket communication) etc
  3. Create system design to coding and testing ...

It is roughly like this.

どこから着手しようか?(Where do i start?)

  1. 開発環境を整える(Setting up develop environment)
  2. Hello World(ハローワールド)
  3. 四則演算(calcurate)
  4. 文字列の扱い




まとめ(As result)

Javaを習得したいなら「Javaで遊ぶ」のが近道です。理論、理屈は後でついてくるので。。。

学習法サンプル(たくのじ流学習方法)

<たくのじ流PG学習法>

  1. とりあえず作る(写経する) [Copy(写経(shakyo) ) java code]
  2. 動かす[Execute]
  3. エラー(Exception)を読む [Read a Exception message]
  4. エラーを潰す[ Fix Exception]
  5. 値や一部のコードをカスタム[ try and test code by change value or a part of code]
  6. 3→5を繰り返す[ repeat 3-5]
  7. 一行ずつ何をしているか自分(人)に説明する[Explain to yourself (person) what you are doing line by line]

スクリーンショット 2018-10-20 20.08.19.png

 

 

 

 

 

Java 3DGame Creation LWJGL Lv3〜 Javaでゲームを作るLv3〜

イントロダクション

前回、Hello LWJGLをやりました。とりあえずは動いたのでここから遊んでみます。→これがプログラムの内容理解になります。

Introduction

Last time, we tried "Hello LWJGL". so let's play LWJGL in own code! → playing will learn.

実装したコードは、こちらになります。

First, implemented code is here.

どうやって遊ぶのか?( How do i play with sample code?)

実行結果が以下のようになります。(The execution result is as fllow)

画面が真っ赤じゃ面白くないのでこの表示を変更する方法を見つけていじることにします。

It's no interesting as only red view. so I think try to change view and draw something.

どこをいじるのか探す(Find out where you are fidding)

スマートな方法としては、対象コード、使用しているフレームワークのドキュメント見るのが良いと思います。

Best way is watch the document

Git Book

https://legacy.gitbook.com/book/lwjglgamedev/3d-game-development-with-lwjgl/details

まず、メソッドの名前をみてみます。今回の実装しているコードにあるメソッドは以下の通りです。

  1. メインメソッド(main())
  2. 初期処理(init())
  3. ゲームループ(gameLoop())

そして、実装したソースの中身が見れないと何もわからないのでソースのリンクを貼ります。

And we do not understand anything if not read LWJGL source, so attach the LWJGL sources.

ソースのアタッチ

中をみてみたいソースコードにカーソルを当てた状態でF3(windows)か[fn]+F3(mac)を押下してください。以下のよう眺めんが見れます。

そして、「Attach Source」と書いてあるボタンをクリックします。

ラジオボタンで下の方を選択します。(External location)

「External File」ボタンをクリックします。

見辛いですが、下の画像にあるように「lwjgl-glfw.jar」と記述されている部分があります。

なので、そいつを探してアタッチします。前回ダウンロードしたZIPファイルの中にあるのでご安心を

こんな感じです。

ポイント(watch it out)

今回使用している(インポートしている)、LWJGLの部品で「static」のついているものがあります。

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

これは宣言、やインスタンスを作らなくてもアクセスするための記述になります。

JUnitというテスト用のフレームワークでも「assertTrue(), assertNull(), fail()」などのメソッドも「static import」しています。下にサンプルコードを示します。

JUnitでのテストコードサンプル( Sample code in JUnit)

@Test
public void test01() {
   System.out.println("テスト開始");
   try {
       File file = new File("/text.txt");
       if (file.exist()) {
          throw new FileNotFoundException("パスが間違っています");
       }
   catch(FileNotFoundException e) {
       fail("テスト失敗");
   }
}

ちょっと長くなったので、今回はここまでにします。

Because I wrote too much. I will describe it in the next step.

2018-10-18

今まで見てきた処理からして、構成は以下のようになります。

From the back ground. Code configuration is as bellow,

  1. run(): このクラスの処理を起動する(メイン処理)
  2. init(); 初期化
  3. gameloop(); 未実装
  4. glfwTerminate(): GLFWの終了処理

  5. glfwSetErrorCallback(null).free(); メモリなどの解放

結論から言うと、「ここに書く」と言うのが見つかりません。。。なので追記します。

From the conclusion, there is no place to implements display method. however we can do it!

コードを追記するのに適当な場所は、画面を描画(初期化)している部分に記載するのが良いと判断し、そこを探します。

I decided that it is a good idea place it in the part where the screen is being drawing(initialized), and search there for places suitable for appending code.

そして、こんな時はメイン処理を眺めます。And look for the place main function.

public void run() {
		System.out.println("Hello LWJGL " + Version.getVersion());
		// 初期処理
		init();
		// ゲームループ
		gameLoop();
		
		glfwFreeCallbacks(window);
		glfwDestroyWindow(window);
System.out.println("終了処理");
		glfwTerminate();
		glfwSetErrorCallback(null).free();		
	}

大まかな処理を一望できるのでメイン処理部分はメインでまとめるとあとあと楽です。

Since you can see the rough processing, the main processing part is easy if you  put in the main.

ソースをいじって遊ぶ場所(The place to play code)

赤字の部分です。 Red line.

/**
 *  初期処理
 */
private void init() {
	// エラー時のコールバックに標準エラー出力を設定する
	GLFWErrorCallback.createPrint(System.err).set();
	// GLFWの初期化
	if (!glfwInit()) {
		throw new IllegalStateException("Unalbe to Initialize GLFW");
	}
	
	// GLFWの設定処理
	glfwDefaultWindowHints();
	glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
	glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
	
	window = glfwCreateWindow(300, 300, "Hello LWJGL", NULL, NULL);
	// ここに描画用のメソッドを追加します。
	addMethod(window);
	if(window == NULL) {
		throw new RuntimeException("Failed to create GLFW Window");
	}
	
	glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
		if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
			glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
		});
		// 2018/10/12 実装漏れ
	try (MemoryStack stack = stackPush()) {
		IntBuffer pWidth = stack.mallocInt(1);
		IntBuffer pHeight = stack.mallocInt(1);
		// ウィンドウサイズ指定
		glfwGetWindowSize(window, pWidth, pHeight);
		// 
		GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
		// 画面の中央座標を設定する
		glfwSetWindowPos(
				window
				, (vidMode.width() - pWidth.get(0) / 2)
				, (vidMode.height() - pHeight.get(0)) / 2
		);
		// OpenGLコンテキストを作成する
		glfwMakeContextCurrent(window);
		// enable v-sync
		glfwSwapInterval(1);
		// 表示処理
		glfwShowWindow(window);
	}
}

追加する場所がわかったので、次は中身の実装をしてみようと思います。

We knew the place to add, we will try to implement content next.

Have a good day!

 


Java Basic Swing Level 2〜画面作成の基本的なところ〜

イントロダクション

前回は、ちょこっとだけSwingの概要に触れました。

Java Swing はOracleのチュートリアルもあるのでそちらも参考にしながら学習できます。

JFCとスイング

参考サイトによると、以下のような説明がありました。


JFC は Java Foundation Classes の略で、グラフィカル ユーザー インターフェイス (GUI) を構築し、豊富なグラフィック機能と対話性を Java アプリケーションに追加するための一連の機能を網羅しています。

他にも、JavaFXでも画面作成ができます。こちらはSceneBuilderというツールを使用して画面の作成ができます。

SceneBuilder1

SceneBuilder2

Swingは

画面を作成できるAPIでも、JavaFXと違い、JDKに同梱されているもので、JavaFXよりも細かい部分を操作できる。
※筆者の感想です。

Swingの基本構成

前回記載した様に土台がありその上にコンポーネントを配置します。

  • JFrame, JDialog, JAppletの3クラスが土台になる
  • Jlabel, JPanel, JTextField...etcはラベルやボタンなどの部品
// 土台クラス
JFrame frame = new JFrame("FirstSwing");
// 土台のコンポーネントを載せる部分(位置などは後で指定する)
// コンテナーと呼びます
Container con = frame.getContentPane();
//コンテナの大記載をしています
con.setSize(300, 300);
// コンテナの上にラベルを配置します
con.add(new JLabel("Hello Swing"));
// 土台の上に乗せたものをおきます
frame.setContentPane(con);
// お約束ごとで閉じる時にこのクラスの起動を終了する設定など。。。
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
// 画面を表示する設定→これをFALSEにすると画面が非表示になる
frame.setVisible(true);

ソースはここからダウンロードできます。

Swingのイメージ




上記の図は、参考サイトから失敬しています。この図のように、JFrameの上にJMenubar, Contentpaneの上に黄色のラベルがのっかっていて
左側のように表示されています。

これから作成するアプリも、同様な形で作成されます。

JFrameの使い方

JFrameクラスでは、上の図のようにコンポーネント(画面の部品)を載せる(追加する)のにはContentPaneを使用して追加します。
下のコードでは、フレームにラベルを追加する処理を行っています。

JFrameをインスタンス化

JFrame frame = new JFrame();
Container cont = frame.getContentPane();
cont.add(new JLabel("ラベル1"));

そして、起動時に終了するときの処理「画面を閉じたらプログラムを終了する設定」と
フレームを表示する処理を行っています。
frame.pack()はコンポーネントのサイズにフレームを合わせる処理です。

// お約束ごとで閉じる時にこのクラスの起動を終了する設定など。。。
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
// 画面を表示する設定→これをFALSEにすると画面が非表示になる
frame.setVisible(true);

JFrameにコンポーネントを追加

下のコードは、チュートリアルにあるコードです。

frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);

このコードをわかりやすく書くと下のようになります。全体のコードはこちらにありました。

JFrame frame = new JFrame();

Container con = frame.getContentPane();

JLabel yellowLabel = new JLabel();
yellowLabel.setOpaque(true);
yellowLabel.setBackground(new Color(248, 213, 131));
yellowLabel.setPreferredSize(new Dimension(200, 180));

con.add(yelloLabel);

もっとたくさんの部品を追加したい場合は、JPanelを使用して、JFrame -> JPanel -> そのほかの部品のような関係で部品(コンポーネント)を追加します。

//Create a panel and add components to it.
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(someBorder);
contentPane.add(someComponent, BorderLayout.CENTER);
contentPane.add(anotherComponent, BorderLayout.PAGE_END);

やはり、プログラムを組んだ時の完成図はイメージするしかないので、下のようなイメージを持つとわかりやすいと思います。

サンプルコード

参考サイトはこちらです。

/** An application that requires no other files. */
public class GlassPaneDemo {
    static private MyGlassPane myGlassPane;

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("GlassPaneDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Start creating and adding components.
        JCheckBox changeButton =
                new JCheckBox("Glass pane \"visible\"");
        changeButton.setSelected(false);

        //Set up the content pane, where the "main GUI" lives.
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new FlowLayout());
        contentPane.add(changeButton);
        contentPane.add(new JButton("Button 1"));
        contentPane.add(new JButton("Button 2"));

        //Set up the menu bar, which appears above the content pane.
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Menu");
        menu.add(new JMenuItem("Do nothing"));
        menuBar.add(menu);
        frame.setJMenuBar(menuBar);

        //Set up the glass pane, which appears over both menu bar
        //and content pane and is an item listener on the change
        //button.
        myGlassPane = new MyGlassPane(changeButton, menuBar,
                                      frame.getContentPane());
        changeButton.addItemListener(myGlassPane);
        frame.setGlassPane(myGlassPane);

        //Show the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

/**
 * We have to provide our own glass pane so that it can paint.
 */
class MyGlassPane extends JComponent
                  implements ItemListener {
    Point point;

    //React to change button clicks.
    public void itemStateChanged(ItemEvent e) {
        setVisible(e.getStateChange() == ItemEvent.SELECTED);
    }

    protected void paintComponent(Graphics g) {
        if (point != null) {
            g.setColor(Color.red);
            g.fillOval(point.x - 10, point.y - 10, 20, 20);
        }
    }

    public void setPoint(Point p) {
        point = p;
    }

    public MyGlassPane(AbstractButton aButton,
                       JMenuBar menuBar,
                       Container contentPane) {
        CBListener listener = new CBListener(aButton, menuBar,
                                             this, contentPane);
        addMouseListener(listener);
        addMouseMotionListener(listener);
    }
}

/**
 * Listen for all events that our check box is likely to be
 * interested in.  Redispatch them to the check box.
 */
class CBListener extends MouseInputAdapter {
    Toolkit toolkit;
    Component liveButton;
    JMenuBar menuBar;
    MyGlassPane glassPane;
    Container contentPane;

    public CBListener(Component liveButton, JMenuBar menuBar,
                      MyGlassPane glassPane, Container contentPane) {
        toolkit = Toolkit.getDefaultToolkit();
        this.liveButton = liveButton;
        this.menuBar = menuBar;
        this.glassPane = glassPane;
        this.contentPane = contentPane;
    }

    public void mouseMoved(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseDragged(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseClicked(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseEntered(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseExited(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mousePressed(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseReleased(MouseEvent e) {
        redispatchMouseEvent(e, true);
    }

    //A basic implementation of redispatching events.
    private void redispatchMouseEvent(MouseEvent e,
                                      boolean repaint) {
        Point glassPanePoint = e.getPoint();
        Container container = contentPane;
        Point containerPoint = SwingUtilities.convertPoint(
                                        glassPane,
                                        glassPanePoint,
                                        contentPane);
        if (containerPoint.y < 0) { //we are not in the content pane
            if (containerPoint.y + menuBar.getHeight() >= 0) { 
                //The mouse event is over the menu bar.
                //Could handle specially.
            } else { 
                //The mouse event is over non-system window 
                //decorations, such as the ones provided by
                //the Java look and feel.
                //Could handle specially.
            }
        } else {
            //The mouse event is probably over the content pane.
            //Find out exactly which component it is over.
            Component component = SwingUtilities.getDeepestComponentAt(
                                        container,
                                        containerPoint.x,
                                        containerPoint.y);

            if ((component != null) 
                && (component.equals(liveButton))) {
                //Forward events over the check box.
                Point componentPoint = SwingUtilities.convertPoint(
                                            glassPane,
                                            glassPanePoint,
                                            component);
                component.dispatchEvent(new MouseEvent(component,
                                                     e.getID(),
                                                     e.getWhen(),
                                                     e.getModifiers(),
                                                     componentPoint.x,
                                                     componentPoint.y,
                                                     e.getClickCount(),
                                                     e.isPopupTrigger()));
            }
        }

        //Update the glass pane if requested.
        if (repaint) {
            glassPane.setPoint(glassPanePoint);
            glassPane.repaint();
        }
    }
}

サンプルコード解説

上記のプログラムを解説します。まずはこのようなプログラムを見るときにメインメソッドを探します。
理由は必ずメインメソッドが動くからです。

メインメソッド

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

単純にcreateAndShowGUI()を起動しているだけですね。細かいところを言うと、こちらのサイトにあるように「イベントディスパッチスレッドで非同期的に実行させます。」ということなので、重い処理は後から非同期で実行する設定だと思ってもらえれば、OKです。
言葉を変えるならば、非同期で処理を実行するので画面の描画中にほかの処理も残ったリソースで実行してくれる設定をしているということです。

createAndShowGUI()

JFrameを生成して、CheckBoxとMenubarを生成。JButtonも同様に生成。

JFrame frame = new JFrame("GlassPaneDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Start creating and adding components.
JCheckBox changeButton =
new JCheckBox("Glass pane \"visible\"");
changeButton.setSelected(false);

//Set up the content pane, where the "main GUI" lives.
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(changeButton);
contentPane.add(new JButton("Button 1"));
contentPane.add(new JButton("Button 2"));

//Set up the menu bar, which appears above the content pane.
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menu.add(new JMenuItem("Do nothing"));
menuBar.add(menu);
frame.setJMenuBar(menuBar);

インナークラスである「MyGlassPane」はフィールド変数に定義、最終的には、JFrameにセットしている(setGlassPane())

//Set up the glass pane, which appears over both menu bar
//and content pane and is an item listener on the change
//button.
myGlassPane = new MyGlassPane(changeButton, menuBar,
frame.getContentPane());
changeButton.addItemListener(myGlassPane);
frame.setGlassPane(myGlassPane);

途中「changeButton.addItemListener(myGlassPane);」では、「項目選択イベントが発生すると、リスナー・オブジェクトのitemStateChangedメソッドが呼び出されます。」ので、「項目の選択」を行ったときの処理を行うのは「itemStateChanged()」でありますよ。と設定しています。
ちなみに、ItemListenerのメソッドをitemStateChangedはオーバーライドしています。

class MyGlassPane extends JComponent implements ItemListener { 
    //React to change button clicks.
    public void itemStateChanged(ItemEvent e) {
        setVisible(e.getStateChange() == ItemEvent.SELECTED);
    }
}

他の部分は、マウスリスナー(マウス操作時の処理)を定義しています。

でわでわ。。。

関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

Java Basic Swing〜Javaで画面アプリを作る。〜

イントロダクション

java.swingパッケージを使用した。画面作成をやります。Java SwingはJava開発をするためにインストールしたJDKの中に入っているので外部のライブラリをインストールして。。。Mavenで依存関係を記述して。。Gradleでインポートして。。。などの手間がありません。

このパッケージ(Swingフレームワーク)はクラス→画面コンポーネント(ラベルや、テキストフィールドなど)になるのでクラス・オブジェクトの扱いを理解するのにとても役立ちます。

Swingについて

画面作成用のフレームワークで、どこに何のクラスを使用するか?が決まっています。

Swing is java frame work to make view. And defind components to use part of view.

詳細はドキュメント(英語)を見てください。

https://docs.oracle.com/javase/tutorial/uiswing/components/index.html

JFrameクラスを継承すると。。。

 Swingの部品構成

画面を作る時は以下の順で画面コンポーネント(部品(ボタンなど))を置いていくイメージです。

Swing components based on “JFrame” or “JDialog” I think ... And put on components one.

<イメージ>

画面の1番下に土台を置きます。(JFrame, JDialo, JAppl

そして、土台の上にはボタンやラベルなどを置きます。これらの部品は土台になる部品とは親クラスが違います。※土台になる部品とボタンなどの部品は別物だと思ってくれればOK

実際の実装は今後やります。

I will write a ample code next blog...

サンプル(sample)

// フレーム(土台)
JFrame frame = new JFrame(“土台”);

// 部品を乗せるスペース=コンテナー
Container con = frame.getContentPain();

// パネル(これもコンテナーフレームより上に乗っかるもの)
JPanel panel = new JPanel();
// パネルにコンポーネントを追加
panel.add(new JLabel("ラベル1"));

// コンテナーにパネル(これもコンテナー)を追加する
con.add(panel);

文字表現ですが、下のようにコンポーネント(画面の部品)を追加して画面を作成します。

  1. フレーム
  2. パネル
  3. ラベルやテキストフィールドなど※チェックボックスなどもある

JLabelを表示する

JLabelを表示する、ハローワールド的なプログラムです。
コメントに処理内容を記述していますが、大まかに土台の上にラベルを載せて表示しているというところです。

ラベル以外のコンポーネント(パネルやフレームを含むすべての画面部品のこと)もAPIで用意されています。※ドキュメント自体は英語ですが、Google翻訳で十分に読めるものでした。

public static void main(String[] args) {
    // 土台クラス
    JFrame frame = new JFrame("FirstSwing");
    // 土台のコンポーネントを載せる部分(位置などは後で指定する)
    // コンテナーと呼びます
    Container con = frame.getContentPane();
    //コンテナの大記載をしています
    con.setSize(300, 300);
    // コンテナの上にラベルを配置します
    con.add(new JLabel("Hello Swing"));
    // 土台の上に乗せたものをおきます
    frame.setContentPane(con);
    // お約束ごとで閉じる時にこのクラスの起動を終了する設定など。。。
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    // 画面を表示する設定→これをFALSEにすると画面が非表示になる
    frame.setVisible(true);
}

Swingを使用して作成したアプリケーションです。「テキストRPG」といいます。

まとめ

つまるところは、Java Swingを使用すると、TextRPGのようなGUIアプリケーションが作成できます。そして、JavaはほとんどのPCで起動できるのでラズパイなどでも起動できマス。
今回は、画面を作成して文字を表示するためのラベルを使用してみました。HTMLで使用するフォーム部品もSwingで使用することができるのでブラウザではなく単体のアプリケーションとして作成することができます。起動するときは「実行可能JAR」というファイルに変換してやれば、ダブルクリックで起動することができます。

関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜