如何为 JComboBox 中的每个值创建加法分配?

问题描述

我有一个 JComboBox,其中包含一个带有月份的 Enum 类和一个 JTextfield(txtHours),用于输入每个月完成的工作时间。

我有一个 JLabel 保存以下所有月份的总价值

run

如何保存和更新特定月份的小时数,以便标签在运行时根据从组合框中选择的月份自行更新?

>>> all_output = subprocess.run(["RNAcofold.exe","ATGTTGG&CCGTGT"],capture_output=True,shell=True)
>>> all_output.stdout
b'this is\nthe content\nof test.txt\n'
>>> all_output.stderr
b''

And so on...

解决方法

回答你的问题,即

如何保存和更新特定月份的小时数

我会使用 Map,其中 Map 键是月份,值是该月的总工作时间。在 Java 1.8 中添加的 date-time API 中,有一个 Month 枚举,因此我将其用作 Map 键。

我不会使用 JTextField 来输入工作时间,而是使用 JSpinner

为了更新工作总小时数,我将向 JSpinner 模型添加一个 ChangeListener,以便每次更改其值时,JLabel 的文本都会显示总小时数工作将得到更新,以显示新的总数。

剩下的唯一事情就是在 JComboBox 中添加一个 ActionListener,这样它就会在用户选择特定月份时显示输入的总工作时间值。

这是一个 minimal,reproducible example

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Month;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class EnumCombo implements ActionListener,ChangeListener,Runnable {
    private Map<Month,Double>  hoursWorked;
    private JComboBox<Month>  monthsCombo;
    private JFrame  frame;
    private JLabel  totalHoursLabel;
    private JSpinner  hoursSpinner;

    public EnumCombo() {
        hoursWorked = new HashMap<Month,Double>(12);
        for (Month month : Month.values()) {
            hoursWorked.put(month,Double.valueOf(0));
        }
    }

    @Override // java.awt.event.ActionListener
    public void actionPerformed(ActionEvent event) {
        Object source = event.getSource();
        if (source instanceof JComboBox<?>) {
            JComboBox<?> combo = (JComboBox<?>) source;
            Object obj = combo.getSelectedItem();
            if (obj instanceof Month) {
                Month month = (Month) obj;
                hoursSpinner.setValue(hoursWorked.get(month));
            }
        }
    }

    @Override // javax.swing.event.ChangeListener
    public void stateChanged(ChangeEvent evt) {
        Object source = evt.getSource();
        if (source instanceof SpinnerNumberModel) {
            SpinnerNumberModel snm = (SpinnerNumberModel) source;
            Object obj = snm.getValue();
            if (obj instanceof Double) {
                Double value = (Double) obj;
                hoursWorked.put((Month) monthsCombo.getSelectedItem(),value);
                Double total = hoursWorked.values()
                                          .stream()
                                          .reduce(Double.valueOf(0),(tot,val) -> tot + val);
                totalHoursLabel.setText(total.toString());
            }
        }
    }

    @Override
    public void run() {
        showGui();
    }

    private JPanel createInputPanel() {
        JPanel inputPanel = new JPanel();
        JLabel monthLabel = new JLabel("Month");
        inputPanel.add(monthLabel);
        monthsCombo = new JComboBox<Month>(Month.values());
        monthsCombo.addActionListener(this);
        inputPanel.add(monthsCombo);
        JLabel hoursLabel = new JLabel("Hours Worked");
        inputPanel.add(hoursLabel);
        SpinnerNumberModel snm = new SpinnerNumberModel(Double.valueOf(0),Double.valueOf(0),Double.valueOf(999),Double.valueOf(1));
        snm.addChangeListener(this);
        hoursSpinner = new JSpinner(snm);
        inputPanel.add(hoursSpinner);
        return inputPanel;
    }

    private JPanel createTotalPanel() {
        JPanel totalPanel = new JPanel();
        JLabel label = new JLabel("Total Hours");
        totalPanel.add(label);
        totalHoursLabel = new JLabel("0");
        totalPanel.add(totalHoursLabel);
        return totalPanel;
    }

    private void showGui() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(createInputPanel(),BorderLayout.PAGE_START);
        frame.add(createTotalPanel(),BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new EnumCombo());
    }
}

注意上面代码中的方法 stateChanged 使用了 stream API,它也是在 Java 1.8 中添加的

这是正在运行的应用程序的屏幕截图。

screen capture of running app