gikoha’s blog

個人的メモがわり

JavaFX chart on TornadeFX/kotlin

子供の自由研究結果をグラフにするソフトを書いた

 

f:id:gikoha:20180829163921j:plain

 

はじめの美しくないやりかた 

vbox += barchart("氷の溶ける早さ",CategoryAxis(), NumberAxis())
{
series(header[1]) {
data(serHdr[1],numdata[1][1])
data(serHdr[2],numdata[2][1])
data(serHdr[3],numdata[3][1])
data(serHdr[4],numdata[4][1])
}
series(header[2]) {
data(serHdr[1],numdata[1][2])
data(serHdr[2],numdata[2][2])
data(serHdr[3],numdata[3][2])
data(serHdr[4],numdata[4][2])
}
series(header[3]) {
data(serHdr[1],numdata[1][3])
data(serHdr[2],numdata[2][3])
data(serHdr[3],numdata[3][3])
data(serHdr[4],numdata[4][3])
}
series(header[4]) {
data(serHdr[1],numdata[1][4])
data(serHdr[2],numdata[2][4])
data(serHdr[3],numdata[3][4])
data(serHdr[4],numdata[4][4])
}
}

こうかけばよかった

val bc = barchart("氷の溶ける早さ",CategoryAxis(), NumberAxis())

for(i in 1..4)
{
val ser = XYChart.Series<String,Number>()
ser.name = header[i]
for(j in 1..4)
{
ser.data.add(XYChart.Data(serHdr[j], numdata[j][i]))
}

bc.data.add(ser)
}
vbox += bc

 

TornadoFX Kotlin

swiftはxcodeだけあり iPhone, macOS両対応

kotlinはAndroid Studio事例はたくさんあるが、desktop appの作成はうまくいかないらしい

JavaFXをコールするにしてもいろいろ面倒くさい

WindowBuilderみたいなのはないので、TornadoFXでwrapしてScenebuilderをダウンロードして使うのがいいらしい

 

以下導入

Terminal から "brew install gradle" "brew install maven32" で開発ツールインストールしておく

JDKが入っていなければ1.8以降をインストール

Android Studioとは別に

www.jetbrains.com

をインストール

Pluginsの下の真ん中のボタン Browse respositories...から TornadoFXプラグインをインストール

New Project...から TornadoFX - tornadofx-gradle-projectを選ぶ

初回 gradle homeがないといってくるので 

/usr/local/Cellar/gradle/4.9/libexec/

あたりを指定

make: Buildボタン コマンドラインなら "gradle build"

実行:まずRunメニューのEdit Configurations...から + を押したあと、Gradleを選び、Gradle Projectに現在のプロジェクトを選び、Tasksに"run"と入力する。すると下記のようになって実行ボタンが使える  コマンドラインなら "gradle run"

f:id:gikoha:20180828111717j:plain

 

fxmlのサンプル

下記にfxmlを入れる src/main/resources/PACKAGES/ そうするとAnchorPane by fxml()で読み込めるし gradleでもリソース扱いされてファイルが無視されない

f:id:gikoha:20180828121756j:plain

fxmlの実際:fx:controller attributeがAnchorPaneタグ内に入っているとjavafx exception : Controller value already specifiedエラーが出るので削除すること。IDEならScenebuilderがビルトインされていて編集が容易。

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button layoutX="172.0" layoutY="121.0" mnemonicParsing="false" onAction="#increment" text="Click here to Increment" />
<Label layoutX="135.0" layoutY="70.0" text="Counter: " />
<Label fx:id="counterLabel" layoutX="219.0" layoutY="70.0" prefHeight="17.0" prefWidth="66.0" text="0" />
</children>
</AnchorPane>

読み込む方の実際 MainView.kt

package com.hatenablog.gikoha.view

import tornadofx.*
import javafx.scene.layout.*
import javafx.scene.control.*
import javafx.beans.property.SimpleIntegerProperty

class MainView : View("Hello TornadoFX FXML") {
override val root : AnchorPane by fxml()
val counter = SimpleIntegerProperty()
val counterLabel: Label by fxid()

init {
counterLabel.bind(counter)
}

fun increment() {
counter.value += 1
}
}

jarの作成: "gradle jar" で/build/libs以下にjarができる。でもでかい。

Charts · edvin/tornadofx Wiki · GitHubなどはkotlinならjavaよりかなり簡単にグラフ化できるのでよさげ。

DOAC Calculator iPhone

swift-xcodeならどのくらいで書けるかとおもって移植してみた

    @IBAction func buttonTapped(_ sender : Any) {

        bodyHeightField.endEditing(true)

        bodyWeightField.endEditing(true)

        sCrField.endEditing(true)

        ageField.endEditing(true)

 

        let height: Double = Double(bodyHeightField.text!)!

        let weight: Double = Double(bodyWeightField.text!)!

        let age: Double = Double(ageField.text!)!

        let crea: Double = Double(sCrField.text!)!

        var egfr: Double = 194*pow(age,-0.287)*pow(crea,-1.094)             // new formula from Am J Kidney Disease in press

        let bsa: Double = 0.007184*pow(weight,0.425)*pow(height,0.725)      // The DuBois formula

        if genderSwitch.selectedSegmentIndex != 0

        {   egfr *= 0.739

        }

        let gfr: Double = egfr*bsa

        CcrField.text = String(format: "%4.1f",gfr)

        BSAField.text = String(format: "%4.1f",bsa)

        eGFRField.text = String(format: "%4.1f",egfr)

        

        

        // 腎障害ステージ

        var stage: String = ""

        switch egfr {

        case 90...150: stage = "正常"

        case 60...90: stage = "軽度腎障害"

        case 30...60: stage = "中等度腎障害"

        case 15...30: stage = "高度腎障害"

        default: stage = "末期腎不全"

        }

        renalStageField.text = stage

        

        // プラザキサ

        if gfr>=50 && age<70

        { ...

 

f:id:gikoha:20180821111835j:plain

苦労したこと

swift: Interface Builderはやっぱり簡単。でもいちいち @IBOutlet weak var bodyHeightField: UITextField! とかして接続してやんないといけないのはめんどい。

if がいちいち{}が必要でコードが汚い

whenがなく switchも多段ifの代わりに使えない

++がない

デベロッパー年間料金が高い(もう退会しちゃった)

 

kotlin: インターフェースデザインがすごく大変。今回はTable Layoutつかったけれど初だったのでよくわからない。思ったようにサイズ調整ができない。

ただLandscapeインターフェースが作りやすい iPhoneはめんどくさい

インターフェースと変数をいちいちひっぱる必要がない

when { -> } がスマートでコードが美しい

デベロッパー登録は1回だけで安い

kotlin

iPhoneでswiftが簡単なように Androidでは kotlinがメジャーになっているらしい

そんなわけで久しぶりにandroid studioをインストール

Ccr計算機も

package com.hatenablog.gikoha.doaccalculator

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import kotlin.math.pow

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)


calculateButton.setOnClickListener {
var height: Double = bodyHeightField.text.toString().toDouble()
var weight: Double = bodyWeightField.text.toString().toDouble()
var age: Double = ageField.text.toString().toDouble()
var crea: Double = sCrField.text.toString().toDouble()
var egfr: Double = 194*age.pow(-0.287)*crea.pow(-1.094) // new formula from Am J Kidney Disease in press
var bsa: Double = 0.007184*weight.pow(0.425)*height.pow(0.725) // The DuBois formula
if(femaleButton.isChecked) egfr *= 0.739
var gfr: Double = egfr*bsa
CcrField.text = "%4.1f".format(gfr)
}
}

}

こんな形ですごく簡単にかけました

f:id:gikoha:20180820164804j:plain

Java使う気なくすじゃねーかw