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使ったり。こっちの方が楽かも知れませんね。まあ、実用品としてでは無く、サンプルとして見て
ください。
(c)Copyright HAZAWA KEIICHI 2017 All
rights reserved
|