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

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

ただいまの
回答率

90.53%

  • Java

    13745questions

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

  • JavaFX

    396questions

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

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

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 881

vetom

score 1

前提・実現したいこと

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

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

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

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

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

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

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

 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をピックアップしました。

Set<String> union = new HashSet<String>(diarrhea);    
    union.addAll(vomit);    

    for(String u: union) {System.out.println(u);}

/*ただこれをGUIに組み込もうとしたときに手詰まりになってしまいます。
今まで考えた方法はチェックボックスやラジオボタンのON状態をisSelected()で取得してif文でtrueならラベルを
setTextで変更するというものです。

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

 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"); }

ただこの方法だと最初のラベル表示から変更されません。そもそも和集合のコードを組み込めてませんし、冗長です。
    

                 RadioButton btn1 = new RadioButton("下痢");
         btn1.setOnAction( (ActionEvent)-> {label.setText("ckd")});

のようなコードだとラベルを変更できるのですが、複数選択の和集合を想定しているので一つのボタンにたいして
一つの答えみたいになるのはイメージとは異なります。

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

追記

疑問

public class Main extends Application {
  Label label;
  RadioButton[] symptomButtons;

  @Override
  void start(Stage stage) {
    ...
    RadioButton btn1 = new RadioButton("下痢");
    RadioButton btn2 = new RadioButton("嘔吐");

    symptomButtons = new RadioButton[] { btn1, btn2, ... };

symptomButtons = new RadioButton[] { btn1, btn2, ... };
ラジオボタンのイベントをsymptomButtonsにまとめているのか?

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

左辺
配列BooleanProperty[]  変数名selectedPropertiesという変数に各ラジオボタンのチェック状態を格納している?
ただ型がBooleanで配列になるのかが分かりません。 配列はintとかStringとかが入ると思っていました。

右辺
配列symptomButtonsのstreamを取得して、マップ関数でsymptomButtonsの中でチェックされたボタンの情報のみ取得している。
それを配列BooleanProperty[]に再変換(再配列)している。

// 各症状のいずれかのボタンの選択状態が変化したときに病名を再計算してlabelへ反映させる

 label.textProperty().bind(
      Bindings.createStringBinding(
        () -> diagnose(makeSelectedSymptomSet()),
        selectedProperties));


...

labelとBindings.createStringBinding(() -> diagnose(makeSelectedSymptomSet())とselectedPropertiesをbindしている
Bindings.createStringBinding(() -> diagnose(makeSelectedSymptomSet())は調べたけど全然わかりませんでした。

 flow.getChildren().addAll(symptomButtons);
    ...
    stage.show();
  }

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

  Set<String> makeSelectedSymptomSet() {
    return Arrays.stream(symptomButtons)
      .filter(b -> b.isSelected())
      .collect(Collectors.toSet());
  }

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

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

該当のソースコード

試したこと

追記

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

import java.util.HashSet;
import java.util.Set;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class testd extends Application {
    Label label;
    RadioButton[] symptomButtons;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        label = new Label();

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

        Button bt1 = new Button("cal");
        Button bt2 = new Button("dignosis");


        Set<String> dignosis = new HashSet<String>();

        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");

         btn1.setOnAction(event ->dignosis.addAll(diarrhea));

         btn2.setOnAction(event ->dignosis.addAll(vomit));

         btn3.setOnAction(event ->dignosis.addAll(constipation));

         btn4.setOnAction(event ->dignosis.addAll(dehydration));




         bt1.setOnAction(event -> {for(String s: dignosis) {label.setText(s);}}); 




        /*
          この方法だとSystem.out.println(s)でイメージ通りの出力ができるのですが、label.setText(s)だと
      一疾患しかピックアップしてくれませんでした。おそらくラベルの宣言が配列として行われていないから
      適当な一疾患だけピックアップされているのかなと思いましたが、配列として宣言した場合、配列数を先に
      決めとかなければならないと書いてあったため、追加されていくこのdignosisには当てはまらないなと思いました。
      こういうときにラベルをSet<String>のように宣言出来たらいいなと思ったんですが、調べたけど分かりませんでした。
      */







  BorderPane pane = new BorderPane();
  pane.setTop(label);
    FlowPane flow = new FlowPane();
    flow.getChildren().add(btn1);
    flow.getChildren().add(btn2);
    flow.getChildren().add(btn3);
    flow.getChildren().add(btn4);
    flow.getChildren().add(bt1);
    pane.setCenter(flow);
    Scene scene = new Scene(pane, 320, 120);
    stage.setScene(scene);
    stage.show();
}

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

より詳細な情報

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KSwordOfHaste

    2017/09/27 08:22

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

    キャンセル

  • mts10806

    2017/09/27 14:54

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

    キャンセル

  • 退会済みユーザー

    2017/09/27 21:25

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 3

+2

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

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

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

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

if(btn1.isSelected()&&btn2.isSelected()) {label.setText("ibd");}
if(btn2.isSelected()&&btn3.isSelected()) {label.setText("ckd");}

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

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

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

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

public class Main extends Application {
  Label label;
  RadioButton[] symptomButtons;

  @Override
  void start(Stage stage) {
    ...
    RadioButton btn1 = new RadioButton("下痢");
    RadioButton btn2 = new RadioButton("嘔吐");
    ...
    symptomButtons = new RadioButton[] { btn1, btn2, ... };
    BooleanProperty[] selectedProperties = Arrays.stream(symptomButtons)
      .map(b -> b.selectedProperty())
      .toArray(size -> new BooleanProperty[size]);
    // 各症状のいずれかのボタンの選択状態が変化したときに病名を再計算してlabelへ反映させる
    label.textProperty().bind(
      Bindings.createStringBinding(
        () -> diagnose(makeSelectedSymptomSet()),
        selectedProperties));
    ...
    flow.getChildren().addAll(symptomButtons);
    ...
    stage.show();
  }

  // 選択状態の症状のみの集合を生成する
  Set<String> makeSelectedSymptomSet() {
    return Arrays.stream(symptomButtons)
      .filter(b -> b.isSelected())
      .collect(Collectors.toSet());
  }

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

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


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/27 20:53

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

    キャンセル

  • 2017/09/27 21:04 編集

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

    キャンセル

  • 2017/09/28 19:28

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

    キャンセル

  • 2017/09/29 00:00

    Java言語の文法や基本ライブラリー(java.lang.*やjava.util.*)の使い方を学びバッチ的なプログラムを作ることに比べ、GUIプログラムの方法論やJavaFXなどのライブラリーの使い方を学ぶ難易度は高いので、難しいと感じることに不思議はないです。

    ところで、参考書のようなものを使っておられない印象ですが、もしそうなら効率よく学ぶために参考書での学習が無難ではないでしょうか。ある程度のプログラミング経験があればネット情報やリファレンスのみに頼った自習も可能ではありますが、その効率は学び手の経験度に従って大きく変わる(初学者であればあるほど効率が悪い)気がします。

    キャンセル

  • 2017/09/29 00:22

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

    キャンセル

  • 2017/09/29 00:45

    > ちゃんと体系的に勉強したほうが

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

    キャンセル

+1

単純な方法としては、

  1. 選択されているものそれぞれについて、結果に含まれているものをList化する
  2. それらListすべてに共通して入っているものをピックアップして返す

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/27 14:41

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

    追記しましたので時間のある時に回答お願いします。

    キャンセル

0

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

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

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    13745questions

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

  • JavaFX

    396questions

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