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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

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

Q&A

3回答

3024閲覧

java でこういうプログラムを作りたいです

vetom

総合スコア8

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

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

1グッド

0クリップ

投稿2017/09/26 01:45

編集2017/09/28 10:23

###前提・実現したいこと

java でこういうプログラムを作りたいです

複数選べる選択肢のボックスaがある。

その選択によって結果を返す。

例えば
ボックスaには("下痢","嘔吐","宿便","d","e","f".....""""""""""""""&quo
"""")
って選択肢があって
結果には
心臓病("下痢","嘔吐")
腎臓病("嘔吐","宿便")
が格納してあります。

ボックスaで"下痢"を選択した場合、
その選択肢を含む心臓病が帰ってくる。
ボックスaで"嘔吐"を選択した場合、
その選択肢を含む心臓病、腎臓病が返ってくる。
ボックスaで"宿便"を選択した場合、
その選択肢を含む腎臓病が返ってくる。
ボックスaで"下痢""嘔吐"を選択した場合、
その選択肢を含む心臓病、腎臓病が返ってくる。
ボックスaで"下痢""宿便"を選択した場合、
その選択肢を含む心臓病、腎臓病が返ってくる。
ボックスaで"宿便""嘔吐"を選択した場合、
その選択肢を含む心臓病、腎臓病が返ってくる。
ボックスaで"下痢""宿便""嘔吐"を選択した場合、
その選択肢を含む心臓病、腎臓病が返ってくる。

こういうものを書くときに必要な知識って何ですか?
基本的なものを除いて
コンボボックスとかラジオボタンを使うのかなと思ったのですが手詰まりです。

//追記分
積集合で病名を取り出す方法を考えてみました。
全パターンを網羅したわけではないですが、一応下のコードではdiarrheaとvomitの積集合でibdをピックアップすることができました

```java

Set<String> diarrhea = new HashSet<String>();
diarrhea.add("ibd");

Set<String> vomit = new HashSet<String>(); vomit.add("ckd"); vomit.add("ibd"); Set<String> constipation = new HashSet<String>(); constipation.add("akd"); Set<String> dehydration = new HashSet<String>(); dehydration.add("akd"); dehydration.add("ibd"); Set<String> intersection = new HashSet<String>(diarrhea); intersection.retainAll(vomit); for(String s: intersection) {System.out.println(s);}
//ただ今回のピックアップのイメージは和集合なので、diarrheaとvomitの和集合ibdとckdをピックアップしました。 ```java Set<String> union = new HashSet<String>(diarrhea); union.addAll(vomit); for(String u: union) {System.out.println(u);}
/*ただこれをGUIに組み込もうとしたときに手詰まりになってしまいます。 今まで考えた方法はチェックボックスやラジオボタンのON状態をisSelected()で取得してif文でtrueならラベルを setTextで変更するというものです。

     例えばこういう感じです(上記の和集合コードは組み込めてません、以前に考えてみたものです)

```java

RadioButton btn1 = new RadioButton("下痢");
RadioButton btn2 = new RadioButton("嘔吐");
RadioButton btn3 = new RadioButton("宿便");
RadioButton btn4 = new RadioButton("脱水");

if(btn1.isSelected()) {label.setText("akd,ckd"); } if(btn2.isSelected()) {label.setText("ibd,ckd"); } if(btn3.isSelected()) {label.setText("ibd"); } if(btn4.isSelected()) {label.setText("akd"); } if(btn1.isSelected()&&btn2.isSelected()) {label.setText("ibd,ckd,akd"); } if(btn1.isSelected()&&btn3.isSelected()) {label.setText("ibd,ckd,akd"); } if(btn1.isSelected()&&btn4.isSelected()) {label.setText("ckd,akd"); } if(btn2.isSelected()&&btn3.isSelected()) {label.setText("ibd,ckd"); } if(btn2.isSelected()&&btn4.isSelected()) {label.setText("ibd,ckd,akd"); } if(btn3.isSelected()&&btn4.isSelected()) {label.setText("ibd,akd"); } if(btn1.isSelected()&&btn2.isSelected()&&btn3.isSelected()) {label.setText("ibd,ckd,akd"); } if(btn1.isSelected()&&btn2.isSelected()&&btn4.isSelected()) {label.setText("ibd,ckd,akd"); } if(btn1.isSelected()&&btn3.isSelected()&&btn4.isSelected()) {label.setText("ibd,ckd,akd"); } if(btn2.isSelected()&&btn3.isSelected()&&btn4.isSelected()) {label.setText("ibd,ckd,akd"); } if(btn1.isSelected()&&btn2.isSelected()&&bt34.isSelected()&&btn4.isSelected())                        {label.setText("ibd,ckd,akd"); }
ただこの方法だと最初のラベル表示から変更されません。そもそも和集合のコードを組み込めてませんし、冗長です。      ```java RadioButton btn1 = new RadioButton("下痢"); btn1.setOnAction( (ActionEvent)-> {label.setText("ckd")});
のようなコードだとラベルを変更できるのですが、複数選択の和集合を想定しているので一つのボタンにたいして 一つの答えみたいになるのはイメージとは異なります。

###発生している問題・エラーメッセージ

追記

疑問

Java

1public class Main extends Application { 2 Label label; 3 RadioButton[] symptomButtons; 4 5 @Override 6 void start(Stage stage) { 7 ... 8 RadioButton btn1 = new RadioButton("下痢"); 9 RadioButton btn2 = new RadioButton("嘔吐"); 10 11 symptomButtons = new RadioButton[] { btn1, btn2, ... }; 12
symptomButtons = new RadioButton[] { btn1, btn2, ... }; ラジオボタンのイベントをsymptomButtonsにまとめているのか? ```java

BooleanProperty[] selectedProperties = Arrays.stream(symptomButtons)
.map(b -> b.selectedProperty())
.toArray(size -> new BooleanProperty[size]);

左辺 配列BooleanProperty[]  変数名selectedPropertiesという変数に各ラジオボタンのチェック状態を格納している? ただ型がBooleanで配列になるのかが分かりません。 配列はintとかStringとかが入ると思っていました。 右辺 配列symptomButtonsのstreamを取得して、マップ関数でsymptomButtonsの中でチェックされたボタンの情報のみ取得している。 それを配列BooleanProperty[]に再変換(再配列)している。 // 各症状のいずれかのボタンの選択状態が変化したときに病名を再計算してlabelへ反映させる ```Java label.textProperty().bind( Bindings.createStringBinding( () -> diagnose(makeSelectedSymptomSet()), selectedProperties));
... labelとBindings.createStringBinding(() -> diagnose(makeSelectedSymptomSet())とselectedPropertiesをbindしている Bindings.createStringBinding(() -> diagnose(makeSelectedSymptomSet())は調べたけど全然わかりませんでした。

Java

1flow.getChildren().addAll(symptomButtons); 2 ... 3 stage.show(); 4}

// 選択状態の症状のみの集合を生成する

Java

1 Set<String> makeSelectedSymptomSet() { 2 return Arrays.stream(symptomButtons) 3 .filter(b -> b.isSelected()) 4 .collect(Collectors.toSet()); 5 } 6

コレクションフレームワークの Setで知っていた文法は
Set<型> 変数名 = new Set()のような形で変数名.add()で要素を入れていく
というものなんですが
上記のような
Set<型> 変数名 {配列を集めるための処理}?みたいな文法は見たことありませんでした。この解釈で合っている分かりませんが
Set<型> 変数名 {配列を集めるための処理}だとすると
配列symptomButtonsをstreamを取得して、マップ関数でsymptomButtonsの中でチェックされたボタンの情報のみ取得している。
その結果をSetで取得してString diagnose(Set<String> symptomSet)に返している。

Java

1// 選択された症状の集合を受け取り、該当する複数の病名を連結した文字列を返す 2 String diagnose(Set<String> symptomSet) { 3 // 実装については質問者さんご自身で進めておられるようなので省略 4 String diagnosis = ...; 5 return diagnosis; 6 } 7}

###該当のソースコード

###試したこと

追記

ほかの方法のアプローチもないかと作ってみましたがうまくいきません

Java

1 2import java.util.HashSet; 3import java.util.Set; 4 5import javafx.application.Application; 6import javafx.scene.Scene; 7import javafx.scene.control.Button; 8import javafx.scene.control.Label; 9import javafx.scene.control.RadioButton; 10import javafx.scene.layout.BorderPane; 11import javafx.scene.layout.FlowPane; 12import javafx.stage.Stage; 13 14public class testd extends Application { 15 Label label; 16 RadioButton[] symptomButtons; 17 18 public static void main(String[] args) { 19 launch(args); 20 } 21 22 @Override 23 public void start(Stage stage) throws Exception { 24 label = new Label(); 25 26 RadioButton btn1 = new RadioButton("下痢"); 27 RadioButton btn2 = new RadioButton("嘔吐"); 28 RadioButton btn3 = new RadioButton("宿便"); 29 RadioButton btn4 = new RadioButton("脱水"); 30 31 Button bt1 = new Button("cal"); 32 Button bt2 = new Button("dignosis"); 33 34 35 Set<String> dignosis = new HashSet<String>(); 36 37 Set<String> diarrhea = new HashSet<String>(); 38 diarrhea.add("ibd"); 39 40 Set<String> vomit = new HashSet<String>(); 41 vomit.add("ckd"); 42 vomit.add("ibd"); 43 44 Set<String> constipation = new HashSet<String>(); 45 constipation.add("akd"); 46 47 Set<String> dehydration = new HashSet<String>(); 48 dehydration.add("akd"); 49 dehydration.add("ibd"); 50 51 btn1.setOnAction(event ->dignosis.addAll(diarrhea)); 52 53 btn2.setOnAction(event ->dignosis.addAll(vomit)); 54 55 btn3.setOnAction(event ->dignosis.addAll(constipation)); 56 57 btn4.setOnAction(event ->dignosis.addAll(dehydration)); 58 59 60 61 62 bt1.setOnAction(event -> {for(String s: dignosis) {label.setText(s);}}); 63 64 65 66 67 /* 68 この方法だとSystem.out.println(s)でイメージ通りの出力ができるのですが、label.setText(s)だと 69      一疾患しかピックアップしてくれませんでした。おそらくラベルの宣言が配列として行われていないから 70      適当な一疾患だけピックアップされているのかなと思いましたが、配列として宣言した場合、配列数を先に 71      決めとかなければならないと書いてあったため、追加されていくこのdignosisには当てはまらないなと思いました。 72      こういうときにラベルをSet<String>のように宣言出来たらいいなと思ったんですが、調べたけど分かりませんでした。 73      */ 74 75 76 77 78 79 80 81  BorderPane pane = new BorderPane(); 82  pane.setTop(label); 83 FlowPane flow = new FlowPane(); 84 flow.getChildren().add(btn1); 85 flow.getChildren().add(btn2); 86 flow.getChildren().add(btn3); 87 flow.getChildren().add(btn4); 88 flow.getChildren().add(bt1); 89 pane.setCenter(flow); 90 Scene scene = new Scene(pane, 320, 120); 91 stage.setScene(scene); 92 stage.show(); 93}

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

LouiS0616👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2017/09/26 01:53

なぜ手詰まりなのかわかりませんが、そこで人に聞かなくてはならないほどなら、そもそもプログラミングせずにすむ方法を探した方が早いかもしれません。時間がかかっても良いなら基礎から勉強してください。足し算のできない人に方程式は教えられません。
KSwordOfHaste

2017/09/26 23:22

javaでGUI画面を作る場合、複数のライブラリー(JavaFX, AndroidSDK, swing)が存在します。JavaFXを想定されているのであれば質問のタグにJavaFXを追加すべきと思います。
m.ts10806

2017/09/27 05:54

プログラムコード(およびエラーメッセージ)は```で囲ってください。(わからなければ質問編集画面でコード部分を選択し<code>ボタンを押してください)正しく反映されているかどうかは質問編集画面のプレビューを見ながら編集していってください。
guest

回答3

0

一般的にGUIプログラムはユーザーの操作によって生じた変化に応じて適切に反応することが要求されますが、バッチ方式のもの(単に初期入力に基づく計算を一度だけ行い結果を出力して終わるもの)に比べると、動作が複雑なだけにそれを実現するライブラリーの仕組みもより複雑で必要な知識が広くなります。本件でいえばイベントハンドリングがポイントだと思いますが、質問者さんはイベントハンドリングについて把握しておられないようですので、とりあえずはその点についてコメントしてみます。

###ユーザ操作に適切に反応するには(イベントハンドリング)

提示しておられる以下のコードに着目してください。

java

1RadioButton btn1 = new RadioButton("下痢"); 2RadioButton btn2 = new RadioButton("嘔吐"); 3RadioButton btn3 = new RadioButton("宿便"); 4 5if(btn1.isSelected()&&btn2.isSelected()) {label.setText("ibd");} 6if(btn2.isSelected()&&btn3.isSelected()) {label.setText("ckd");}

これでは画面の初期化時に一度だけそれぞれのif文が実行されるに過ぎず、画面表示後にユーザーがボタンを操作する度に再計算すべきという点が表現できていません。こうした計算はイベントハンドリングつまりイベント契機(ユーザ操作等による何らかの変化を表す)で処理(ハンドラー)を起動すべきであることを登録しておくという考え方をします。ハンドラーを登録しておけばしかるべきタイミングで自動的にJavaFXのランタイムがハンドラーを起動してくれるので、ハンドラーの中に必要な計算処理などを記述することになります。

さらに具体的な実現にはいくつか方法があります。

(1) 「マウスクリック」「キーの押下」等々のユーザー操作契機でハンドラーを起動
(2) 特定のJavaFXプロパティー(本件ではRadioButtonのselected)が変化した契機でハンドラーを起動
(3) バインディング

概ね(1)が低水準、(3)が一番高度な仕組みといえるので可能ならなるべく(3)あるいは(2)を使うのがJavaFXでのコツと言えるかと思います。本件では(2)も(3)も利用できますが、(3)を用いるなら例えば次のように書けます。

java

1public class Main extends Application { 2 Label label; 3 RadioButton[] symptomButtons; 4 5 @Override 6 void start(Stage stage) { 7 ... 8 RadioButton btn1 = new RadioButton("下痢"); 9 RadioButton btn2 = new RadioButton("嘔吐"); 10 ... 11 symptomButtons = new RadioButton[] { btn1, btn2, ... }; 12 BooleanProperty[] selectedProperties = Arrays.stream(symptomButtons) 13 .map(b -> b.selectedProperty()) 14 .toArray(size -> new BooleanProperty[size]); 15 // 各症状のいずれかのボタンの選択状態が変化したときに病名を再計算してlabelへ反映させる 16 label.textProperty().bind( 17 Bindings.createStringBinding( 18 () -> diagnose(makeSelectedSymptomSet()), 19 selectedProperties)); 20 ... 21 flow.getChildren().addAll(symptomButtons); 22 ... 23 stage.show(); 24 } 25 26 // 選択状態の症状のみの集合を生成する 27 Set<String> makeSelectedSymptomSet() { 28 return Arrays.stream(symptomButtons) 29 .filter(b -> b.isSelected()) 30 .collect(Collectors.toSet()); 31 } 32 33 // 選択された症状の集合を受け取り、該当する複数の病名を連結した文字列を返す 34 String diagnose(Set<String> symptomSet) { 35 // 実装については質問者さんご自身で進めておられるようなので省略 36 String diagnosis = ...; 37 return diagnosis; 38 } 39}

上のコード例ではbindの部分がややこしくよくわからないと感じると思います。詳しくは仕様を学んでいただきたいのですが、大雑把に言えば「症状を表す各ボタンのselectedプロパティーのいずれかが変化した際にdiagnoseメソッドを呼び出して病名を計算させ、その結果を自動的にlabelのtextプロパティーの値に反映するようよきに計らえ」といった感じです。ちなみにdiagnoseメソッドが引数として必要とする「選択状態の症状名の集合(Set)」はmakeSelectedSymptomSetで生成していますので「画面の状態からどのようにして症状の集合に変換するか」について参考にしてみてください。


追記:すみません、サンプルに上げたbind呼び出しのコードで引数に間違いがあったのでコードを訂正しました。

投稿2017/09/27 11:27

編集2017/09/28 00:46
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vetom

2017/09/27 11:53

ご指摘ありがとうございます。 まだ全部調べれてないので適切に疑問点をピックアップできません。不勉強で申し訳ありませんが、 ちゃんと理解して、分からないところを再度質問させてください。 とりあえずバインドの知識が全くなかったのでそこから調べてみます。 頑張ります。
KSwordOfHaste

2017/09/27 12:05 編集

学ぶという意味では回答の(1),(2),(3)の順番に学んだ方がよいかも知れません。まずは(1)を最初に。(1)は他のGUIシステムでも大抵同様の機能を備えているから一般性の高い機能ですので本件で使わなかったとしてもどんなものかは押さえておく必要はあるでしょう。次は(2)で、(1)に比べると高水準ですが使い方は割合単純でわかりやすいです。(3)は一番高機能ですが仕様が複雑で他の関連知識(例えば(2)の知識)が前提になります。ということで、基本的な機能からより高度な機能を学ぶというのも(遠回りに見えますが)スムーズに理解を進めるためのコツではないかと。
vetom

2017/09/28 10:28

KSwordOfHaste先生 何度も細かく加筆していただいてありがとうございます。 色々と調べてみたのですが、不勉強で申し訳ありませんが分からないところが多々ありました。 とりあえず自分なりに先生の思考と似たように作ってみたのですがうまくいきません。 言語を勉強するときは何か作りたいものを決めたほうが良いと聞いたので、チャレンジしてみたのですが初心者にはかなり難しいものだったのかもしれません。なんとなく想像だと簡単だと思っていたのですが、実際やってみるとかなり難しいです。 でも頑張ります。
KSwordOfHaste

2017/09/28 15:00

Java言語の文法や基本ライブラリー(java.lang.*やjava.util.*)の使い方を学びバッチ的なプログラムを作ることに比べ、GUIプログラムの方法論やJavaFXなどのライブラリーの使い方を学ぶ難易度は高いので、難しいと感じることに不思議はないです。 ところで、参考書のようなものを使っておられない印象ですが、もしそうなら効率よく学ぶために参考書での学習が無難ではないでしょうか。ある程度のプログラミング経験があればネット情報やリファレンスのみに頼った自習も可能ではありますが、その効率は学び手の経験度に従って大きく変わる(初学者であればあるほど効率が悪い)気がします。
vetom

2017/09/28 15:22

KSwordOfHaste先生 ネット情報に頼って勉強しています。 少しわかったつもりで、何か作ってみようと思ったのですが、ちゃんと体系的に勉強したほうがよさそうですね。色々アドバイスしていただいて本当に助かります。
KSwordOfHaste

2017/09/28 15:45

> ちゃんと体系的に勉強したほうが そう思います。コードの断片はあくまでヒントです。それをみてもピンとこないなら、前提知識が不足している可能性が高いと思います。特定の知識の理解は、前提知識を体系的に積み上げていった上に成り立つものであり、例えばコードの断片をみて簡単にわかるようなものではないと思います。参考書などを活用して体系的に学習することをお勧めしておきます。
guest

0

単純な方法としては、
0. 選択されているものそれぞれについて、結果に含まれているものをList化する
0. それらListすべてに共通して入っているものをピックアップして返す

ただ、このような用途なら結果の対応関係を逆にしておいたほうがいいのでは?
病名→症状の対応ではなく、症状→病名のほうが積集合も取りやすいですよ。

投稿2017/09/27 01:55

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vetom

2017/09/27 05:41

ど素人な質問に回答していただきありがとうございます。 始めたばかりなのでこういう掲示板の使い方がわからず、低評価を受けてしまい少しショックを受けていたところでした。 追記しましたので時間のある時に回答お願いします。
guest

0

的を外していたら無視して下さい。

Javaは初心者ですが、javaでデータの管理とロジックをプログラムしようと思えます。

例えばですが、下記のように分離してみては如何ですか?
1.データ管理をdb
2.ロジックをJavaで管理

dbとして「病名」と「病状」という簡単なフィールドを準備して、

dbに下記のようにデータを登録し、
「病名」心臓病、「病状」下痢
「病名」心臓病、「病状」嘔吐
「病名」腎臓病、「病状」嘔吐
「病名」腎臓病、「病状」宿便

select 嘔吐 from db; とすれば「心臓病」と「腎臓病」が返ります。

投稿2018/04/07 16:44

Freedom1ab

総合スコア60

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問