データ(モデル)をGUI(ビュー)から分離します。
一例を挙げると、スコアボードはおそらくJTableです。JTableはビュークラスにあり、TableModelはモデルクラスにあります。
すべてのGUIコンポーネントに対して同じことを行います。コンポーネントごとに、モデルクラスにコンポーネントデータのモデルがあります。
これが私がまとめたストップウォッチGUIのモデルクラスです。GUIを見なくても、ストップウォッチを構成するすべてのデータコンポーネントを識別できるはずです。
package com.ggl.stopwatch.model;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.DefaultTableModel;
public class StopwatchModel {
protected boolean isSplitTime;
protected long startTime;
protected long endTime;
protected DefaultTableModel tableModel;
protected List<Long> splitTimes;
protected String[] columnNames = {"", "Increment", "Cumulative"};
public StopwatchModel() {
this.splitTimes = new ArrayList<Long>();
this.isSplitTime = false;
this.startTime = 0;
this.endTime = 0;
setTableModel();
}
public void resetTimes() {
this.splitTimes.clear();
this.isSplitTime = false;
this.startTime = 0;
this.endTime = 0;
}
public boolean isSplitTime() {
return isSplitTime;
}
public long getStartTime() {
return startTime;
}
public long getEndTime() {
return endTime;
}
public long getLastSplitTime() {
int size = splitTimes.size();
if (size < 1) {
return getStartTime();
} else {
return splitTimes.get(size - 1);
}
}
public long getPenultimateSplitTime() {
int size = splitTimes.size();
if (size < 2) {
return getStartTime();
} else {
return splitTimes.get(size - 2);
}
}
public DefaultTableModel getTableModel() {
return tableModel;
}
public int getTableModelRowCount() {
return tableModel.getRowCount();
}
public void clearTableModel() {
tableModel.setRowCount(0);
}
public int addTableModelRow(long startTime, long previousSplitTime,
long currentSplitTime, int splitCount) {
String[] row = new String[3];
row[0] = "Split " + ++splitCount;
row[1] = formatTime(previousSplitTime, currentSplitTime, false);
row[2] = formatTime(startTime, currentSplitTime, false);
tableModel.addRow(row);
return splitCount;
}
public void setStartTime() {
if (getStartTime() == 0L) {
this.startTime = System.currentTimeMillis();
} else {
long currentTime = System.currentTimeMillis();
int size = splitTimes.size();
if (size > 0) {
long splitTime = splitTimes.get(size - 1);
splitTime = splitTime - getEndTime() + currentTime;
splitTimes.set(size - 1, splitTime);
}
this.startTime = currentTime - getEndTime() + getStartTime();
}
}
protected void setTableModel() {
this.tableModel = new DefaultTableModel();
this.tableModel.addColumn(columnNames[0]);
this.tableModel.addColumn(columnNames[1]);
this.tableModel.addColumn(columnNames[2]);
}
public void setSplitTime() {
this.splitTimes.add(System.currentTimeMillis());
isSplitTime = true;
}
public void setEndTime() {
Long split = System.currentTimeMillis();
if (isSplitTime) {
this.splitTimes.add(split);
}
this.endTime = split;
}
public String formatTime(long startTime, long time, boolean isTenths) {
long elapsedTime = time - startTime;
int seconds = (int) (elapsedTime / 1000L);
int fraction = (int) (elapsedTime - ((long) seconds * 1000L));
fraction = (fraction + 5) / 10;
if (fraction > 99) {
fraction = 0;
}
if (isTenths) {
fraction = (fraction + 5) / 10;
if (fraction > 9) {
fraction = 0;
}
}
int hours = seconds / 3600;
seconds -= hours * 3600;
int minutes = seconds / 60;
seconds -= minutes * 60;
StringBuilder builder = new StringBuilder();
builder.append(hours);
builder.append(":");
if (minutes < 10) builder.append("0");
builder.append(minutes);
builder.append(":");
if (seconds < 10) builder.append("0");
builder.append(seconds);
builder.append(".");
if ((!isTenths) && (fraction < 10)) builder.append("0");
builder.append(fraction);
return builder.toString();
}
}
分離したら、モデルクラスに初期化メソッドを配置します。
編集して追加:モデルクラスのインスタンスをビュークラスに渡して、ビューを生成します。これがストップウォッチGUIのメインパネルです。
package com.ggl.stopwatch.view;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import com.ggl.stopwatch.model.StopwatchModel;
import com.ggl.stopwatch.thread.StopwatchThread;
public class StopwatchPanel {
protected static final Insets entryInsets = new Insets(0, 10, 4, 10);
protected static final Insets spaceInsets = new Insets(10, 10, 4, 10);
protected JButton resetButton;
protected JButton startButton;
protected JButton splitButton;
protected JButton stopButton;
protected JLabel timeDisplayLabel;
protected JPanel mainPanel;
protected JPanel buttonPanel;
protected JPanel startPanel;
protected JPanel stopPanel;
protected SplitScrollPane splitScrollPane;
protected StopwatchModel model;
protected StopwatchThread thread;
public StopwatchPanel(StopwatchModel model) {
this.model = model;
createPartControl();
}
protected void createPartControl() {
splitScrollPane = new SplitScrollPane(model);
createStartPanel();
createStopPanel();
setButtonSizes(resetButton, startButton, splitButton, stopButton);
mainPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
int gridy = 0;
JPanel displayPanel = new JPanel();
displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE, 6));
timeDisplayLabel = new JLabel(model.formatTime(0L, 0L, true));
timeDisplayLabel.setHorizontalAlignment(SwingConstants.CENTER);
Font font = timeDisplayLabel.getFont();
Font labelFont = font.deriveFont(60.0F);
timeDisplayLabel.setFont(labelFont);
timeDisplayLabel.setForeground(Color.BLUE);
displayPanel.add(timeDisplayLabel);
addComponent(mainPanel, displayPanel, 0, gridy++, 1, 1, spaceInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
buttonPanel = new JPanel();
buttonPanel.add(startPanel);
addComponent(mainPanel, buttonPanel, 0, gridy++, 1, 1, spaceInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
addComponent(mainPanel, splitScrollPane.getSplitScrollPane(), 0, gridy++, 1, 1, spaceInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
}
protected void createStartPanel() {
startPanel = new JPanel();
startPanel.setLayout(new FlowLayout());
resetButton = new JButton("Reset");
resetButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
model.resetTimes();
timeDisplayLabel.setText(model.formatTime(0L, 0L, true));
splitScrollPane.clearPanel();
mainPanel.repaint();
}
});
startPanel.add(resetButton);
startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
model.setStartTime();
thread = new StopwatchThread(StopwatchPanel.this);
thread.start();
displayStopPanel();
}
});
startPanel.add(startButton);
}
protected void createStopPanel() {
stopPanel = new JPanel();
stopPanel.setLayout(new FlowLayout());
splitButton = new JButton("Split");
splitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
model.setSplitTime();
splitScrollPane.addSplit(model.getStartTime(),
model.getPenultimateSplitTime(),
model.getLastSplitTime());
splitScrollPane.setMaximum();
splitScrollPane.repaint();
}
});
stopPanel.add(splitButton);
stopButton = new JButton("Stop");
stopButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
model.setEndTime();
thread.setRunning(false);
if (model.isSplitTime()) {
splitScrollPane.addSplit(model.getStartTime(),
model.getPenultimateSplitTime(),
model.getLastSplitTime());
splitScrollPane.setMaximum();
splitScrollPane.repaint();
}
displayStartPanel();
}
});
stopPanel.add(stopButton);
}
protected void addComponent(Container container, Component component,
int gridx, int gridy, int gridwidth, int gridheight,
Insets insets, int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0);
container.add(component, gbc);
}
protected void displayStopPanel() {
buttonPanel.remove(startPanel);
buttonPanel.add(stopPanel);
buttonPanel.repaint();
}
protected void displayStartPanel() {
buttonPanel.remove(stopPanel);
buttonPanel.add(startPanel);
buttonPanel.repaint();
}
protected void setButtonSizes(JButton ... buttons) {
Dimension preferredSize = new Dimension();
for (JButton button : buttons) {
Dimension d = button.getPreferredSize();
preferredSize = setLarger(preferredSize, d);
}
for (JButton button : buttons) {
button.setPreferredSize(preferredSize);
}
}
protected Dimension setLarger(Dimension a, Dimension b) {
Dimension d = new Dimension();
d.height = Math.max(a.height, b.height);
d.width = Math.max(a.width, b.width);
return d;
}
public void setTimeDisplayLabel() {
this.timeDisplayLabel.setText(model.formatTime(model.getStartTime(),
System.currentTimeMillis(), true));
}
public JPanel getMainPanel() {
return mainPanel;
}
}