- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经为这个问题苦苦挣扎了一个多星期了,非常感谢您的帮助。我正在使用 GUI 开发我的第一个 Java 游戏,目前涉及大约 20 个类。该游戏是《星际迷航》的简单基于网格的表示,JLabel 图标在星系网格中移动。问题是,通常在大约 7 到 10 次移动之后,会发生以下两种情况之一:其一,我当前象限中的扇区网格将消失,仅在左上角留下一个扇区;一两次,企业图标将消失。
我没有处理线程的经验,但经过一些阅读后,我认为这可能是事件调度线程未与程序逻辑正确同步的结果。我阅读了更新 GUI 的正确方法,并用 invokeLater 和 invokeAndWait block 包围了对 GUI 有任何影响的所有语句(我认为)。
但是,这并没有解决问题。所以,今天我将所有内容重写为我能做到的最小可编译单元(它不是那么小,但我不知道如何使其更小),同时仍然保留我的基本游戏结构,看看这是否会改变任何东西。事实并非如此。 7 到 10 次移动后,GUI 仍然会损坏。
我已经无计可施了。如果您能提供一些帮助,我将不胜感激。
这是我的代码。它按原样编译并运行。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
public class GUI extends JFrame
{
int screenwidth;
int screenheight;
public static void main(String[] args)
{
GUI gui = new GUI();
run(gui);
}
public static void run(final GUI gui)
{
Quadrant[][] galaxy = new Quadrant[8][8];
//populate galaxy with quadrants
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < 8; j++)
{
galaxy[i][j] = new Quadrant(i, j);
}
}
//Quadrant to put in the view when game starts
Quadrant startingQuadrant = galaxy[0][0];
final QuadrantView quadrantView = startingQuadrant.getQuadrantView();
Enterprise enterprise;
Sector startingSector;
//add SectorViews to the QuadrantView
for (int i = 0; i < 8; i++)
{
for(int j = 0; j < 8; j++)
{
startingQuadrant.getQuadrantView().addSectorView(startingQuadrant.getSectorArray()[i][j].getSectorView(), i, j);
}
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//initialize gui with the starting quadrant quadrantView
gui.intiGUI(quadrantView);
}
});
//start on sector (0, 0)
startingSector = startingQuadrant.getSectorArray()[0][0];
enterprise = new Enterprise(startingQuadrant, startingSector);
startingSector.setContainsEnterprise(true);
Scanner input = new Scanner(System.in);
Sector destinationSector;
int qRow; //destination quadrant row
int qCol; //destination quadrant column
int sRow; //destination sector row
int sCol; //destination sector column
while(true)
{
System.out.println("Enter quadrant row: ");
qRow = input.nextInt();
System.out.println("Enter quadrant column: ");
qCol = input.nextInt();
System.out.println("Enter sector row: ");
sRow = input.nextInt();
System.out.println("Enter sector column: ");
sCol = input.nextInt();
destinationSector = galaxy[qRow][qCol].getSectorArray()[sRow][sCol];
enterprise.move(destinationSector, galaxy[qRow][qCol], gui);
}
}
public GUI()
{
super("Star Trek");
//create an anonymous listener to close window and end game
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
dispose();
System.exit(0);
}
});
// get user's screen width and height
screenwidth = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
screenheight = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
//set layout
getContentPane().setLayout(new BorderLayout());
resizeGUI();
setVisible(true);
validate();
}
private void resizeGUI()
{
// set window size
if (screenwidth >= 1280)
setSize(1024, 768);
else if (screenwidth >= 1024)
setSize(800, 600);
else if (screenwidth >= 800)
setSize(640, 480);
// maximize window
setExtendedState(this.getExtendedState() | this.MAXIMIZED_BOTH);
}
//initialize this gui with the starting QuadrantView
public void intiGUI(QuadrantView quadrantView)
{
getContentPane().add(quadrantView, BorderLayout.CENTER);
validate();
}
//reset the gui to hold the new QuadrantView
public void resetGUI(QuadrantView newQuadrantView)
{
getContentPane().add(newQuadrantView, BorderLayout.CENTER);
validate();
}
static class Quadrant
{
private int row;
private int col;
private QuadrantView quadrantView;
private Sector[][] sectorArray;
public Quadrant(int r, int c)
{
// quadrant row
row = r;
// quadrant columns
col = c;
// the view object associated with this quadrant
setQuadrantView(new QuadrantView(8, 8));
// an array to hold the sectors in this quadrant (req. 3.1.0)
sectorArray = new Sector[8][8];
// create the 64 sectors in this quadrant and add them to the array (req. 3.1.0)
for (int i = 0; i < sectorArray.length; i ++)
{
for (int j = 0; j < sectorArray[i].length; j++)
{
sectorArray[i][j] = new Sector(i, j, this);
}
}
}
public int getRow()
{
return row;
}
public int getCol()
{
return col;
}
public void setRow(int r)
{
row = r;
}
public void setCol(int c)
{
col = c;
}
public Sector[][] getSectorArray()
{
return sectorArray;
}
public QuadrantView getQuadrantView()
{
return quadrantView;
}
public void setQuadrantView(QuadrantView quadrantView)
{
this.quadrantView = quadrantView;
}
}
static class Sector
{
//sector row
private int row;
//sector column
private int col;
//the quadrant this sector is in
private Quadrant quadrant;
//the view associated with this sector
private SectorView sectorView;
//boolean values to determine what this sector holds (Req. 4.1.0)
private boolean containsEnterprise;
//if the sector holds the Enterprise, store a reference to it
private Enterprise enterprise;
public Sector(int r, int c, Quadrant q)
{
row = r;
col = c;
quadrant = q;
setSectorView(new SectorView());
containsEnterprise = false;
//print the sector's coordinates on the gui
sectorView.setID(row + ", " + col);
}
public int getRow()
{
return row;
}
public int getCol()
{
return col;
}
public void setRow(int r)
{
row = r;
}
public void setCol(int c)
{
col = c;
}
public Quadrant getQuadrant()
{
return quadrant;
}
public boolean containsEnterprise()
{
return containsEnterprise;
}
public void setContainsEnterprise(boolean containsEnterprise)
{
this.containsEnterprise = containsEnterprise;
if (containsEnterprise)
{
sectorView.showEnterpriseIcon();
}
else
{
sectorView.hideEnterpriseIcon();
}
}
public Enterprise getEnterprise()
{
return enterprise;
}
public void addEnterprise(Enterprise enterprise)
{
this.enterprise = enterprise;
}
public void removeEnterprise()
{
enterprise = null;
}
public SectorView getSectorView()
{
return sectorView;
}
public void setSectorView(SectorView sectorView)
{
this.sectorView = sectorView;
}
public String toString()
{
return Integer.toString(row)+ "." + Integer.toString(col);
}
}
//end Sector class
static class SectorView extends JPanel
{
// default font for text
private final Font TREK_FONT = new Font("Verdana", Font.BOLD, 10);
// color for text
private final Color LABEL_COLOR = Color.BLACK;
// component layout
private SpringLayout layout;
// displays sector ID
private JLabel IDLabel;
//enterprise display
private JLabel enterpriseIcon;
/*
* create a new SectorView
*/
public SectorView()
{
super();
//create and set layout for child components
layout = new SpringLayout();
this.setLayout(layout);
//initialize child components
initComponents();
//position and display child components
layoutComponents();
//set background color
setBackground(Color.DARK_GRAY);
//set border
setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
//set size of sectors
setPreferredSize(new Dimension(QuadrantView.SECTOR_SIZE, QuadrantView.SECTOR_SIZE));
}
/*
* initialize components
*/
private void initComponents()
{
// displays ID of this view
IDLabel = new JLabel("");
IDLabel.setFont(TREK_FONT);
IDLabel.setForeground(Color.WHITE);
// create an enterprise icon and make it invisible
enterpriseIcon = new JLabel("E");
enterpriseIcon.setForeground(Color.WHITE);
enterpriseIcon.setVisible(false);
}
/*
* lay out components and add them to this view
*/
private void layoutComponents()
{
// position components:
// ID label
layout.putConstraint(SpringLayout.WEST, IDLabel, 1, SpringLayout.WEST, this);
layout.putConstraint(SpringLayout.NORTH, IDLabel, 1, SpringLayout.NORTH, this);
// enterprise icon
layout.putConstraint(SpringLayout.WEST, enterpriseIcon, 5, SpringLayout.WEST, this);
layout.putConstraint(SpringLayout.NORTH, enterpriseIcon, 30, SpringLayout.NORTH, this);
// add to view
this.add(IDLabel);
this.add(enterpriseIcon);
}
public void showEnterpriseIcon()
{
enterpriseIcon.setVisible(true);
}
public void hideEnterpriseIcon()
{
enterpriseIcon.setVisible(false);
}
//the sector's (row, col) coordinates within the quadrant
public void setID(String id)
{
IDLabel.setText(id);
}
}
//end SectorView class
static class QuadrantView extends JPanel
{
//size of sectors
public final static int SECTOR_SIZE = 100;
private final Color BACKGROUND_COLOR = Color.DARK_GRAY;
private SpringLayout layout;
/*
* create a new QuadrantView with the specified width
* and height
*
* @param quadrantHeight height of quad. in sectors
* @param quadrantWidth width of quad. in secors
*/
public QuadrantView(int quadrantHeight, int quadrantWidth)
{
//call JPanel constructor
super();
//create and set the layout
layout = new SpringLayout();
setLayout(layout);
//set the size of the QuadrantView we are creating using the inherited JComponent method
setPreferredSize(new Dimension(quadrantWidth * SECTOR_SIZE, quadrantHeight * SECTOR_SIZE));
//set background color using the inherited JComponent method
setBackground(BACKGROUND_COLOR);
}
/*
* add the specified Sector to this view
*
* each sector is represented by a (row, column) pair
* @param sectorView SectorView to be added to the QuadrantView
* @param row row coordinate
* @param col column coordinate
*/
public void addSectorView(SectorView sectorView, int row, int col)
{
//position the sector
layout.putConstraint(SpringLayout.WEST, sectorView, col * SECTOR_SIZE, SpringLayout.WEST, this);
layout.putConstraint(SpringLayout.NORTH, sectorView, row * SECTOR_SIZE, SpringLayout.NORTH, this);
//add sectorView to the layout using inherited method of Container class
this.add(sectorView);
}
}
static class Enterprise
{
protected Sector sectorLocation;
protected Quadrant quadrantLocation;
public Enterprise(Quadrant quadrant, Sector sector)
{
sectorLocation = sector;
quadrantLocation = quadrant;
sector.addEnterprise(this);
sector.setContainsEnterprise(true);
}
// Requirement 9.4.0
public boolean move(Sector destinationSector, final Quadrant destinationQuadrant, final GUI gui)
{
//if the destination quadrant is not our current quadrant, we need to update the gui (is updating this way causing a problem?)
if (!destinationQuadrant.equals(this.quadrantLocation))
{
//Put the new SectorViews in the new quadrant.
for (int i = 0; i < 8; i++)
{
for(int j = 0; j < 8; j++)
{
destinationQuadrant.getQuadrantView().addSectorView(destinationQuadrant.getSectorArray()[i][j].getSectorView(), i, j);
}
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//initialize gui with the starting quadrant quadrantView
//replace the old quadrant view with the new one
gui.resetGUI(destinationQuadrant.getQuadrantView());
}
});
}
//remove the reference to this starship from the current sector
sectorLocation.removeEnterprise();
//sector no longer contains the Enterprise
sectorLocation.setContainsEnterprise(false);
//move to destination quadrant
quadrantLocation = destinationQuadrant;
//move to destination sector
sectorLocation = destinationSector;
//add a reference to this starship to the new sector
sectorLocation.addEnterprise(this);
//new sector now contains Enterprise
sectorLocation.setContainsEnterprise(true);
return true;
}
}//end Enterprise class
}
最佳答案
限制线程之间交换的数据量。唯一需要交换的数据是键盘的输入。特别是避免在线程之间共享字段 - 这会导致竞争条件。您的主循环应如下所示:
while(true)
{
final int qRow = input.nextInt();
final int qCol = input.nextInt();
final int sRow = input.nextInt();
final int sCol = input.nextInt();
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
move(qRow,qCol,sRow,sCol);
}
});
}
删除所有其他 invokeAndWait
和 invokeLater
。根本不要使用invokeLater
。它使您的程序变得不可预测。
尝试在变量初始化之前声明变量并将其标记为final。可变状态会导致错误。
我无法弄清楚为什么表格缩小到 1x1。尝试使用 GridLayout
而不是 SpringLayout
。它似乎更适合这种情况。
关于java - GUI 未正确更新,组件消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23848756/
我找到了 this excellent question and answer它以 x/y(加上 center x/y 和 degrees/radians)开始并计算旋转- 到 x'/y'。这个计算很
全部: 我已经创建了一个 Windows 窗体和一个按钮。在另一个线程中,我试图更改按钮的文本,但它崩溃了;但是如果我尝试更改按钮的颜色,它肯定会成功。我认为如果您更改任何 Windows 窗体控件属
本网站的另一个问题已证实,C 中没有缩写的字面后缀,并且可以执行以下操作: short Number = (short)1; 但是转换它和不这样做有什么区别: short Number = 1; 您使
我有下表: ID (int) EMAIL (varchar(50)) CAMPAIGNID (int) isSubscribe (bit) isActionByUser (bit) 此表存储了用户对事
也就是说,无需触发Javascript事件即可改变的属性,如何保留我手动选中或取消选中的复选框的状态,然后复制到另一个地方? 运行下面的代码片段并选中或取消选中其中的一些,然后点击“复制”: $('#
我在网上找到的所有关于递增指针导致段错误的示例都涉及指针的取消引用 - 如果我只想递增它(例如在 for 循环的末尾)并且我不在乎它是否最终进入无效内存,因为我不会再使用它。例如,在这个程序中,每次迭
我有一个 Spring MVC REST 服务,它使用 XStream 将消息与 XML 相互转换。 有什么方法可以将请求和响应中的 xml(即正文)打印到普通的 log4j 记录器? 在 Contr
做我的任务有一个很大的挑战,那就是做相互依赖的任务我在这张照片中说的。假设我们有两个任务 A 和 B,执行子任务 A1、A2 和 B1、B2,假设任务 B 依赖于 A。 要理想地执行任务 B,您应该执
通过阅读该网站上的几个答案,我了解到 CoInitialize(Ex) should be called by the creator of a thread 。然后,在该线程中运行的任何代码都可以使
这个问题已经困扰我一段时间了。我以前从未真正使用过 ListViews,也没有使用过 FirebaseListAdapters。我想做的就是通过显示 id 和用户位置来启动列表的基础,但由于某种原因,
我很难解释这两个(看似简单)句子的含义: “受检异常由编译器在编译时检查” 这是什么意思?编译器检查是否捕获了所有已检查的异常(在代码中抛出)? “未经检查的异常在运行时检查,而不是编译时” 这句话中
我有一个包含排除子字符串的文本文件,我想迭代该文件以检查并返回不带排除子字符串的输入项。 这里我使用 python 2.4,因此下面的代码可以实现此目的,因为 with open 和 any 不起作用
Spring 的缓存框架能否了解请求上下文的身份验证状态,或者更容易推出自己的缓存解决方案? 最佳答案 尽管我发现这个用例 super 奇怪,但您可以为几乎任何与 SpEL 配合使用的内容设置缓存条件
我有以下函数模板: template HeldAs* duplicate(MostDerived *original, HeldAs *held) { // error checking omi
如果我的应用程序具有设备管理员/设备所有者权限(未获得 root 权限),我如何才能从我的应用程序中终止(或阻止启动)另一个应用程序? 最佳答案 设备所有者可以阻止应用程序: DevicePolicy
非常简单的问题,但我似乎无法让它正常工作。 我有一个组件,其中有一些 XSLT(用于导航)。它通过 XSLT TBB 使用 XSLT Mediator 发布。 发布后
我正在将一个对象拖动到一个可拖放的对象内,该对象也是可拖动的。放置对象后,它会嵌套在可放置对象内。同样,如果我将对象拖到可放置的外部,它就不再嵌套。 但是,如果我经常拖入和拖出可放置对象,则可拖动对象
我正在尝试为按钮和弹出窗口等多个指令实现“取消选择”功能。也就是说,我希望当用户单击不属于指令模板一部分的元素时触发我的函数。目前,我正在使用以下 JQuery 代码: $('body').click
我从 this question 得到了下面的代码,该脚本用于在 Google tasks 上更改 iframe[src="about:blank"] 内的 CSS使用 Chrome 扩展 Tempe
我有一些 @Mock 对象,但没有指定在该对象上调用方法的返回值。该方法返回 int (不是 Integer)。我很惊讶地发现 Mockito 没有抛出 NPE 并返回 0。这是预期的行为吗? 例如:
我是一名优秀的程序员,十分优秀!