1

我正在尝试为我的 Java 游戏添加重启/重播功能。目前在我的 Game 类(GUI 和游戏被初始化的地方),我有:

init() method
Game() object

Game 对象包含整个游戏窗口的 GUI,并包括各种对象(例如实际游戏窗口、计分板、倒数计时器等)。

我想添加一个功能,如果他们单击 GUI 上的重新启动按钮或游戏结束,游戏将重新启动(以及倒计时和计分)。我确实意识到最好重新实例化对象(得分,倒计时),但是一旦实例化它们就是我的 GUI 的一部分

i.e. add(scoreboard)

有没有办法重新实例化对象而不必重新实例化我的 GUI?理想情况下,我只想重新实例化对象,而不必为 GUI 重新打开一个全新的 JFrame。如果有人可以为我提供我应该拥有的类和方法(以及它们做什么)的大纲,将不胜感激。

谢谢!

4

1 回答 1

5

将数据(模型)与 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;
    }

}
于 2012-11-16T20:19:45.857 回答