Javaで自動保存されるメモ帳を作る



 JavaFXでEnterキーを押すごとに自動保存さ れるメモ帳を作りました。動作環境はwindows10,Linux,Mac(Macは 動作未確認)。
 データを保存するフォルダは、
 Windowsだと、C:\Users\ユーザ名\OneDrive\ドキュメント\tmpData.dat
 Linuxだと、/home/ユーザ名/
tmpData.dat(動 作未確認)
 Macだと /Users/
ユーザ名/tmpData.dat
 ユーザー名が絡んでいるのでデフォルトで設定しているのではなくて、SHGetFolderPath() メソッドや、getProperty("user.home")メソッドで機種ごとパスを取り出している。

 GUIはscreenBuilderでAnchorPane(初期状態で設置されている)の下に、Menuコント ロールとTextAreaコントロールを配置し、イベントを書き込みます。スクロールバーはどうするんだと思って試 行錯誤しましたが前記の通りすれば自動的に出てきます。最初はBoderPaneを使っていたのですが、AnchorPaneで問題なし。
 

 では、Sample.fxmlはこちら

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="202.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
   <children>
      <MenuBar>
        <menus>
          <Menu mnemonicParsing="false" text="ファイル">
            <items>
                  <MenuItem mnemonicParsing="false" onAction="#endClose" text="終了" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="このソフトについて">
            <items>
              <MenuItem mnemonicParsing="false" onAction="#aboutThis" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
      <TextArea fx:id="txtArea" layoutY="24.0" onKeyPressed="#KeyPressed" prefHeight="178.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="25.0" />
   </children>
</AnchorPane>


 Main.javaはこちら
package application;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Main extends Application {
    @FXML
   private TextArea txtA;
   
    @Override
   
    public void start(Stage primaryStage) {
        try {
           
            AnchorPane root = (AnchorPane)FXMLLoader.load(getClass().getResource("Sample.fxml"));
            Scene scene = new Scene(root,400,400);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());

            primaryStage.setScene(scene);
            primaryStage.show();
           
        } catch (Exception e) {
            myTools.showException( e);
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}


 コントローラークラスのSampleController.javaはこちら。各個人の環境のマイドキュメントにパスを通して ます。

package application;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

public class SampleController  implements Initializable{
    @FXML
    private TextArea txtArea;
   
    @Override
    public void initialize(URL location, ResourceBundle resources) {
       
        String fname;
        File file;
        File folda;
        String osname = System.getProperty("os.name");
        if(osname.indexOf("Windows")>=0){
          // Windowsであったときの処理
            myTools win = new myTools();
            fname = win.SHGetFolderPath()+ "\\tmpData.dat";
            file = new File(fname);
            folda = new File(win.SHGetFolderPath());
            myTools.writeAnyM(folda, file, txtArea);
        } else if(osname.indexOf("Linux")>=0){
          // Linuxであったときの処理
            fname =System.getProperty("user.home") +File.separator + "tmpData.dat";
            file = new File(fname);
            folda = new File(System.getProperty("user.home"));
            myTools.writeAnyM(folda, file, txtArea);       
           
        } else if(osname.indexOf("Mac")>=0){
          // MacOSであったときの処理
          // Macは持ってないし使った事ないので対応不可
            myTools.msgBox("警告! このソフトはMacで検証してません");
            fname =System.getProperty("user.home") +File.separator + "tmpData.dat";
            file = new File(fname);
            folda = new File(System.getProperty("user.home"));
            myTools.writeAnyM(folda, file, txtArea);
        } else {
          // その他の環境だったときの処理
            //Javaだからって何でも対応するわけじゃないぞ、ゴラァ!
            myTools.msgBox("済みません、このソフトはお使いのOSに対応してません");
        }
    }
    @FXML
    void KeyPressed(){// 押下処理を追加する
        txtArea.setOnKeyPressed(new EventHandler<KeyEvent>() {

        @Override
        public void handle(KeyEvent event) {
            if (event.getCode() == KeyCode.ENTER) {
                try {//Enterキーを押されたらファイルに書き込む
                    myTools win = new myTools();
                    File file = new File(win.SHGetFolderPath()+ "\\tmpData.dat");
                    FileWriter filewriter;

                    filewriter = new FileWriter(file);
                    BufferedWriter br = new BufferedWriter(filewriter);
                   
                      br.write(txtArea.getText());
                      br.flush();
                    br.close();
                   
                } catch (Exception e) {
                    myTools.showException( e);
                }
            }
        }
    });
    }
    @FXML
    private void endClose(ActionEvent event){
         Platform.exit();
    }
    @FXML
    private void aboutThis(ActionEvent event){
        myTools.msgBox("Enterキーを押すと勝手に保存されるメモ帳\nby Ryou");
    }
}


 使っているメソッドを集めた(サブルーチン集と言ったら古いのか?)myTools.javaはこちら

package application;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.StringWriter;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeMapped;
import com.sun.jna.Platform;
import com.sun.jna.PointerType;

import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TextArea;

public class myTools {
   
    public static class HANDLE extends PointerType implements NativeMapped {}
    public static class HWND extends HANDLE {}
   
    public static void showException(Exception e){
        // エラーのスタックトレースを表示
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        pw.flush();
        String str = sw.toString();
        //例外メッセージボックスを表示
        msgBox("例外発生!" + str);

    }
    // Java からWindows APIにアクセスして、マイドキュメントのパスを取得する
    public interface Shell32 extends Library {
        Shell32 INSTANCE = (Shell32) Native.loadLibrary("shell32", Shell32.class);
       
        public static final int MAX_PATH = 260;
        public static final int CSIDL_PERSONAL = 0x0005;// マイドキュメント
        public static final int SHGFP_TYPE_CURRENT = 0;
        public static final int SHGFP_TYPE_DEFAULT = 1;
        public static final int S_OK = 0;
          
        int SHGetFolderPathW(
                HWND hwndOwner,
                int nFolder,
                HANDLE hToken,
                int dwFlags,
                char[] lpdzShortPath);
    }
   
        public String SHGetFolderPath() {
            if (Platform.isWindows()) {
                HWND hwndOwner = null;
                int nFolder = Shell32.CSIDL_PERSONAL;
                HANDLE hToken = null;
                int dwFlags = Shell32.SHGFP_TYPE_CURRENT;
                char[] pszPath  = new char [2+256*2];
                int res = Shell32.INSTANCE.SHGetFolderPathW(hwndOwner, nFolder, hToken, dwFlags, pszPath);
       
            if (res == Shell32.S_OK) {
                String path = new String(pszPath);
                path = path.substring(0, path.indexOf('\0'));
                  return path;
              }
         }
         return null;
    }
    public static void writeAnyM(File folda, File file, TextArea txtArea){
        try {
            //フォルダの書き込み許可をチェックして不許可だとエラー表示
            if (!folda.canWrite()){
                msgBox("書き込み許可があるフォルダではありません");
               
            } else if (!file.exists()) {//ファイルがなかった場合
           
                file.createNewFile();
                msgBox("ファイルが無かったので作りました");
               
            } else {//ファイルがあった場合
                FileReader filereader = new FileReader(file);
                BufferedReader br = new BufferedReader(filereader);
                  String str = br.readLine();

                  while(str != null){//ファイルを末尾まで読む
                    txtArea.appendText(str);
                    str = br.readLine();
                    txtArea.appendText("\n");
                  }
                  br.close();
            }

        } catch (Exception e) {
            // エラーのスタックトレースを表示
            myTools.showException( e);
        }

    }
    public static void msgBox(String data){
        Alert alert = new Alert(AlertType.INFORMATION);
        alert.setTitle("情報");
        alert.setHeaderText(null);
        alert.setContentText( data);
        //最前面でボタンクリックを待つ
        alert.showAndWait();
    }

}


 以上、こんな感じです。完成品は、ここからダウンロード。Jarファイルなので、Java8をパスを通したり する必要がありま す。Windows10ではコンソールから起動出来ますが、ダブルクリックで実行できません。Linuxでもコンソール、GUI共に実行できません。理由 が分からないのでteratalで質問しました。どうやら、実行させるには色々環境設定をしなければならないようです。 JVMがあれば動くというわけでもなかったようです。(例えばJavaFXをLinuxで動かすにはGTKをインストールす る必要があるとか)。また、Windowsはダブルクリックに固執しなくても、exeにしたり(32bit限定ですがjsmoothを使う)、Java Web Start使ったり。こっちの方が楽かも知れませんね。まあ、実用品としてでは無く、サンプルとして見て ください。


  HOME



(c)Copyright HAZAWA KEIICHI 2017 All rights reserved