首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >医疗诊断选择器

医疗诊断选择器
EN

Code Review用户
提问于 2016-02-12 06:38:35
回答 2查看 439关注 0票数 2

好吧,所以我的代码“全完了”,缺少了一些关于MVC设计模式的基本知识,我应该把我的关注点分开,我没有模型层,我不知道如何在当前的情况下实现它。我的两个班是:

代码语言:javascript
复制
public class GuiPanel extends JPanel {

public ImageIcon resource01;

public ImageIcon getResource01() {
    if (resource01 == null) {
        resource01 = new ImageIcon(getClass().getResource("/images/reptiles99_11.jpg"));
    }
    return resource01;
}

public ImageIcon resource02;

public ImageIcon getResource02() {
    if (resource02 == null) {
        resource02 = new ImageIcon(getClass().getResource("/images/rsz_s13.jpg"));
    }
    return resource02;
}

private Font font;

@Override
public Font getFont() {
    if (font == null) {
        font = new Font("Times new Roman", Font.BOLD, 14);
    }
    return font;
}

private final String[] listS1 = {"-Odaberi-", "Akutni", "Hronicni"};
private int counterS1 = 0;
private JComboBox comboS1;

private JComboBox getComboS1() {
    if (comboS1 == null) {
        comboS1 = new JComboBox();
        comboS1.setBounds(245, 135, 90, 30);
        for (int i = 0; i < 3; i++) {
            comboS1.addItem(listS1[counterS1++]);
        }
        add(comboS1);

    }
    return comboS1;
}

private final String[] listS2 = {"-Odaberi-", "Abdomen", "Udovi", "Glava"};
private int counterS2 = 0;
private JComboBox comboS2;

private JComboBox getComboS2() {
    if (comboS2 == null) {
        comboS2 = new JComboBox();
        comboS2.setBounds(245, 235, 90, 30);
        for (int i = 0; i < 4; i++) {
            comboS2.addItem(listS2[counterS2++]);
        }
        add(comboS2);

    }
    return comboS2;
}

private ComboBoxModel[] models;

private ComboBoxModel[] getComboModels() {
    if (models == null) {
        models = new ComboBoxModel[5];
        models[0] = new DefaultComboBoxModel(new String[]{"-Odaberi-"});
        models[1] = new DefaultComboBoxModel(new String[]{"-Odaberi-", "1 - GL",
            "2 - GS", "3 - GD", "4 - SL", "5 - SD", "6 - SL", "7 - DL", "8 - DS", "9 - DD"});

    }
    return models;
}

private JComboBox comboS3;

private JComboBox getComboS3() {
    if (comboS3 == null) {
        comboS3 = new JComboBox();
        comboS3.setBounds(245, 335, 90, 30);
        comboS3.setModel(models[0]);
        comboS3.disable();
        add(comboS3);

    }
    return comboS3;
}

private JLabel title;

private JLabel getTitleLabel() {
    if (title == null) {
        title = new JLabel("Aplikacija za dijagnozu bolesti");
        title.setBounds(90, 40, 200, 100);
        title.setFont(getFont());
        add(title);
    }

    return title;
}

private JLabel diagnose;

private JLabel getDiagnoseLabel() {
    if (diagnose == null) {
        diagnose = new JLabel("Preliminarna dijagnoza :");
        diagnose.setBounds(10, 420, 200, 100);
        add(diagnose);

    }
    return diagnose;
}

private JLabel symptome01;

private JLabel getSymptome01Label() {
    if (symptome01 == null) {
        symptome01 = new JLabel("Vrsta bola koju osecate : ");
        symptome01.setBounds(10, 100, 200, 100);
        add(symptome01);
    }

    return symptome01;
}

private JLabel symptome02;

private JLabel getSymptome02Label() {
    if (symptome02 == null) {
        symptome02 = new JLabel("U kom delu tela osecate taj bol :");
        symptome02.setBounds(10, 200, 200, 100);
        add(symptome02);
    }
    return symptome02;
}

private JLabel symptome03;

private JLabel getSymptome03Label() {
    if (symptome03 == null) {
        symptome03 = new JLabel("Vas bol osecate u (vidi sliku) : ");
        symptome03.setBounds(10, 300, 200, 100);
        add(symptome03);
    }
    return symptome03;
}

private JLabel picture01;

private JLabel getPicture01Label() {
    if (picture01 == null) {
        picture01 = new JLabel(getResource01());
        picture01.setBounds(400, 40, 350, 400);
        add(picture01);

    }
    return picture01;
}

private JLabel picture02;

private JLabel getPicture02Label() {
    if (picture02 == null) {
        picture02 = new JLabel(getResource02());
        picture02.setBounds(400, 40, 350, 400);
        picture02.setVisible(false);
        add(picture02);
    }
    return picture02;

}

private JButton reset;

private JButton getResetButton() {
    if (reset == null) {
        reset = new JButton("Ponovo");
        reset.setBounds(640, 470, 110, 50);
        reset.addActionListener(new AgainButton(getResetButton(), getComboS1(),
                getComboS2(), getComboS3(), getDiagnoseField(), getPicture01Label()));
        add(reset);
    }

    return reset;
}

private JButton calculate;

private JButton getCalculateButton() {
    if (calculate == null) {
        calculate = new JButton("Dijagnoza");
        calculate.setBounds(400, 470, 110, 50);
        calculate.addActionListener(new CalculateButton(getCalculateButton(),
                getComboS1(), getComboS2(), getComboS3(), getDiagnoseField()));
        add(calculate);
    }
    return calculate;
}

private JTextField diagnoseField;

private JTextField getDiagnoseField() {
    if (diagnoseField == null) {
        diagnoseField = new JTextField("");
        diagnoseField.setBounds(10, 490, 350, 30);
        diagnoseField.setEditable(false);
        add(diagnoseField);
    }
    return diagnoseField;
}

public GuiPanel() {

    setLayout(null);

    getComboS1();
    getComboS2();
    getComboModels();
    getComboS3();
    getTitleLabel();
    getDiagnoseLabel();
    getSymptome01Label();
    getSymptome02Label();
    getSymptome03Label();
    getPicture01Label();
    getPicture02Label();
    getResetButton();
    getCalculateButton();
    getDiagnoseField();
}

这是主GUI类,我有一个按钮函数类,它实现了一个动作侦听器:

代码语言:javascript
复制
public class CalculateButton implements ActionListener {

private final JComboBox comboS1;
private final JComboBox comboS2;
private final JComboBox comboS3;
private final JTextField diagnoseField;

public CalculateButton(JButton calculate, JComboBox comboS1, JComboBox comboS2, JComboBox comboS3, JTextField diagnoseField) {
    this.comboS1 = comboS1;
    this.comboS2 = comboS2;
    this.comboS3 = comboS3;
    this.diagnoseField = diagnoseField;
    calculate.addActionListener(this);
}

@Override
public void actionPerformed(ActionEvent e) {

    if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 1) {
        diagnoseField.setText("Upala zucovoda");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 2) {
        diagnoseField.setText("Cir na zeludcu");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 3) {
        diagnoseField.setText("Gastritis");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 4) {
        diagnoseField.setText("Renalne kolike");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 5) {
        diagnoseField.setText("Divertikulitis");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 6) {
        diagnoseField.setText("Rani apendicitis / pankreatitis");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 7) {
        diagnoseField.setText("Apendicitis");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 8) {
        diagnoseField.setText("Cistitis / bolovi u rektumu / problemi sa stolicom");
    } else if (comboS1.getSelectedIndex() == 1 && comboS2.getSelectedIndex() == 1 && comboS3.getSelectedIndex() == 9) {
        diagnoseField.setText("Spasma stigme");
    }

}

}

所有的字符串,尽管用我的母语,都应该被看作是普通的字符串。

EN

回答 2

Code Review用户

回答已采纳

发布于 2016-02-12 09:00:21

布局

不要硬编码尺寸和位置。在Mac电脑上,一切看起来都不对劲。(我没有你的照片,所以我会在接下来的评论中忽略它们。)

此外,GuiPanel的用户不知道它需要有多大,而且还会被硬编码。

一种更好的布局方法是使用LayoutManagers。通过调整按钮的大小和一些边距,可以或多或少地自动获得以下结果。

图形用户界面构建

你经常使用懒惰的getter模式。为什么?懒惰不会给您带来任何好处,因为您肯定需要实例化这个UI的每个组件。而且,构造函数调用这些getter纯粹是因为它们的副作用,这是非常奇怪的。相反,您应该负责构造函数中的所有实例化。

没有必要为每个JLabel创建一个实例变量。构造函数中的局部变量可以:一旦每个标签都被添加到布局中,您就不再需要引用它了。

我会以这样的方式构造UI:

代码语言:javascript
复制
import java.awt.*;
import javax.swing.*;

public class GuiPanel extends JPanel {
    private JComboBox<String> typeCombo = makeComboBox("Akutni", "Hronicni"),
                              partCombo = makeComboBox("Abdomen", "Udovi", "Glava"),
                              painCombo = makeComboBox("1 - GL", "2 - GS", "3 - GD", "4 - SL", "5 - SD", "6 - SL", "7 - DL", "8 - DS", "9 - DD");

    private JTextField diagnosisField = new JTextField(20);

    public GuiPanel() {
        this.setLayout(new BorderLayout());
        this.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        // Title
        JLabel title = new JLabel("Aplikacija za dijagnozu bolesti", SwingConstants.CENTER);
        title.setFont(new Font("Times new Roman", Font.BOLD, 14));
        this.add(title, BorderLayout.NORTH);

        // Questions
        JPanel questions = new JPanel();
        questions.setLayout(new GridLayout(0, 2, 30, 30));
        questions.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        questions.add(new JLabel("Vrsta bola koju osecate :"));
        questions.add(this.typeCombo);
        questions.add(new JLabel("U kom delu tela osecate taj bol :"));
        questions.add(this.partCombo);
        questions.add(new JLabel("Vas bol osecate u (viki sliku) :"));
        //this.painCombo.setEnabled(false);
        questions.add(this.painCombo);
        this.add(questions, BorderLayout.CENTER);

        // Diagnosis and buttons
        JPanel bottom = new JPanel();
        bottom.setLayout(new FlowLayout());
        bottom.setAlignmentY(Container.BOTTOM_ALIGNMENT);

        JPanel diagnosis = new JPanel();
        diagnosis.setLayout(new BoxLayout(diagnosis, BoxLayout.Y_AXIS));
        diagnosis.setAlignmentX(Container.LEFT_ALIGNMENT);
        diagnosis.add(new JLabel("Preliminarna dijagnoza :"));
        diagnosisField.setEditable(false);
        diagnosis.add(diagnosisField);
        bottom.add(diagnosis);

        JButton diagnosisButton = new JButton("Dijagnoza");
        diagnosisButton.setMargin(new Insets(10, 10, 10, 10));
        diagnosisButton.addActionListener(ActionEvent -> { diagnose(); });
        bottom.add(diagnosisButton);

        JButton resetButton = new JButton("Ponovo");
        resetButton.setMargin(new Insets(10, 10, 10, 10));
        resetButton.addActionListener(ActionEvent -> { reset(); });
        bottom.add(resetButton);

        this.add(bottom, BorderLayout.SOUTH);
    }

    private static JComboBox<String> makeComboBox(String... options) {
        JComboBox<String> combo = new JComboBox<String>();
        combo.addItem("-Odaberi-");
        for (String opt : options) {
            combo.addItem(opt);
        }
        return combo;
    }

    private void diagnose() {
        String disease = DiagnosisEngine.diagnose(
            this.typeCombo.getSelectedIndex() == 0 ? null : (String)this.typeCombo.getSelectedItem(),
            this.partCombo.getSelectedIndex() == 0 ? null : (String)this.partCombo.getSelectedItem(),
            this.painCombo.getSelectedIndex()
        );
        this.diagnosisField.setText(disease == null ? "" : disease);
    }

    private void reset() {
        this.typeCombo.setSelectedIndex(0);
        this.partCombo.setSelectedIndex(0);
        this.painCombo.setSelectedIndex(0);
        this.diagnose();
    }

}

诊断

诊断逻辑不应与UI相耦合。由于这个诊断任务很简单,让GuiPanel从UI中提取必要的信息,请求诊断,并显示结果。

代码语言:javascript
复制
public class DiagnosisEngine {
    public static String diagnose(String type, String part, int pain) {
        if ("Akutni".equals(type)) {
            if ("Abdomen".equals(part)) {
                switch (pain) {
                    case 1: return "Upala zucovoda";
                    case 2: return "Cir na zeludcu";
                    case 3: return "Gastritis";
                    case 4: return "Renalne kolike";
                    case 5: return "Divertikulitis";
                    case 6: return "Rani apendicitis / pankreatitis";
                    case 7: return "Apendicitis";
                    case 8: return "Cistitis / bolovi u rektumu / problemi sa stolicom";
                    case 9: return "Spasma stigme";
                }
            }
        }
        return null;
    }

}
票数 10
EN

Code Review用户

发布于 2016-02-12 08:56:06

General

这看起来要好得多,因为初始化的每一个组成部分是粘在一起,在一个地方。

添加组件

组件不应将自身添加到父组件中。不应该显式地知道父级。将它们添加到构造函数中,如下所示:

代码语言:javascript
复制
public GuiPanel() {

    ...

    add(getComboS1());
    add(getComboS2());
    add(getComboModels());
    add(getComboS3());

    ...

}

模型

在一个类似的问题中,我举了一个例子。作为一个复兴的问题,我将在这里提供它,所以你有一个想法,如何分开关注。

Main.java

代码语言:javascript
复制
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MyModel myModel = new MyModel();
                MyFrame myFrame = new MyFrame(myModel);
                myFrame.setVisible(true);
            }

        });
    }

MyFrame.java

代码语言:javascript
复制
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

public class MyFrame extends JFrame {

    private final MyModel myModel;

    private JButton nextWordButton;
    private WordTextField wordTextField;


    public MyFrame(MyModel myModel) {
        this.myModel = myModel;
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(getNextWordButton(), BorderLayout.WEST);
        getContentPane().add(getWordTextField(), BorderLayout.CENTER);
        setSize(400, 200);
    }


    private JButton getNextWordButton() {
        if (nextWordButton == null) {
            nextWordButton = new JButton("Next");
            nextWordButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    myModel.execute();
                }
            });
        }
        return nextWordButton;
    }


    private WordTextField getWordTextField() {
        if (wordTextField == null) {
            wordTextField = new WordTextField();
            myModel.add(wordTextField);
        }
        return wordTextField;
    }

}

MyModel.java

代码语言:javascript
复制
import java.util.HashSet;
import java.util.Set;

public class MyModel {


    private static final String[] INFINITE_SENTENCE = new String[] {"This", "sentence", "will", "never", "end", "because ..."};


    private int index;
    private Set<MyModelListener> listeners;

    public MyModel() {
        this.index = 0;
        this.listeners = new HashSet<>();
    }

    public void execute() {
        this.index++;
        notifyOnExecute(getWord());
    }

    private String getWord() {
        return INFINITE_SENTENCE[this.index % INFINITE_SENTENCE.length];
    }

    private void notifyOnExecute(String word) {

        for (MyModelListener listener: this.listeners) {
            listener.onExecute(word);
        }

    }

    public boolean add(MyModelListener l) {
        l.onListenerRegistration(getWord());
        return listeners.add(l);
    }

    public boolean remove(MyModelListener l) {
        return listeners.remove(l);
    } 


}

MyModelListener.java

代码语言:javascript
复制
public interface MyModelListener {

    void onExecute(String word);

    void onListenerRegistration(String word);

}

WordTextField

代码语言:javascript
复制
public class WordTextField extends JTextField implements MyModelListener {

    @Override
    public void onExecute(String word) {
        setTextLater(word);
    }


    private void setTextLater(String word) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                setText(word);
            }
        });
    }


    @Override
    public void onListenerRegistration(String word) {
        setTextLater(word);
    }

}

程序是:

  1. 按钮被点击
  2. ActionListener被称为
  3. 它是委托给模型的
  4. 模型改变了它的内部
  5. 该模型将内部更改(监听器模式、推送机制)通知感兴趣的侦听器。
  6. 由于WordTextField注册为对模型更改感兴趣,它将收到通知,可以自行更新其状态

主要的优点是:

  1. 接收端与发送方的解耦。WordTextField不需要知道操作是否由按钮启动。任何触发模型改变的因素都有可能。
  2. 将UI与模型分离,因此不再将自己绑定到特定的UI技术中。扔掉Swing并使用JavaFX。这也是可行的。如果您认为没有必要改变UI技术,那么它仍然是解耦的代码。模型将是可测试的,没有任何视觉效果。
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/119733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档