当前位置: 首页 > 面试题库 >

重新启动/重播Java游戏,而无需重新启动GUI

劳豪
2023-03-14
问题内容

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

init() method
Game() object

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

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

i.e. add(scoreboard)

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

谢谢!


问题答案:

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

}


 类似资料:
  • 问题内容: 如果我的进程正在加载.so库,并且该库有新版本可用,是否可以在不重新启动进程的情况下切换到新库?还是答案取决于诸如库中现有功能之一是否有参数更改之类的事情? 我正在一个相当大的系统中工作,该系统运行100多个进程,每个系统加载10多个库。这些库提供特定的功能,并由独立的团队提供。因此,当其中一个库发生更改(可以说是针对错误修复)时,理想的做法是在后台发布它而不影响运行的过程。可能吗 ?

  • 问题内容: 我想知道是否可以在不重新启动JBoss服务器的情况下部署Java类文件。我正在使用jboss v4.2.2。 另外,当我尝试部署jsp文件时,它工作正常,服务器几乎立即接收到更改。 在此先感谢:) 问题答案: 我使用Tomcat比使用JBoss更好,但是应该可以(如在Tomcat中)重新启动应用程序而无需重新启动应用程序服务器。如果服务器具有“开发模式”并且该模式处于活动状态,则应该可

  • 问题内容: 这个问题已经在这里有了答案 : While循环中的ReactorNotRestartable错误出现刮擦 (7个答案) 去年关闭。 与: 我一直成功地运行了此过程: 但由于我已将此代码移入一个函数中,因此: 并开始使用类实例化调用该方法,例如: 并运行: 我收到以下错误: 怎么了? 问题答案: 您不能重新启动反应堆,但是应该可以通过分叉一个单独的过程来使其运行更多次: 运行两次: 结果

  • 本文向大家介绍nginx 重新启动NGINX,包括了nginx 重新启动NGINX的使用技巧和注意事项,需要的朋友参考一下 示例 以root用户身份: Ubuntu的例子            

  • 我希望容器在计算机重新启动后自动启动,所以我使用'--restart=always'标志,但它并没有像我预期的那样运行。当我重新启动系统时,容器没有启动。 docker日志信息 添加docker ps-a message,$docker ps-a CONTAINER ID IMAGE命令CREATED STATUS PORTS NAMES a1f4d5471b0a mysql:8.0“docker

  • Triathlon程序执行一个长时间运行的任务,如果该任务已完全执行,则有可能重新启动该任务。我想添加停止执行以重置UI的可能性。为了达到这个目的,我增加了一个新的按钮,停止。代码如下: 如果任务已经完成,程序很好地重新启动,但是如果我在停止它之后调用start,程序就会崩溃。我该纠正什么?