JButton ArrayList 没有在滴答时正确更新?
JButton ArrayList not updating correctly on tick?
我正在使用默认的 JFrame gui 开发一个简单的闲置游戏(想想 CookieClicker)。货币单位是 'clicks',赚取足够的 'clicks' 后,玩家应该能够点击与他们可以购买的自动点击器相对应的 JButton。但是,只有添加到自动点击器 ArrayList 的最后一个 'autoclicker' 在正确的时间变得可用,并且如果单击它,所有其他 JButton 将采用其属性。如果可能的话,你能帮我找出问题吗?免责声明:可能是一堆故障排除。
这是我的主要内容 class:
(我将额外的 JButtons 和 AutoClickers 注释掉了,所以它按预期工作)
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.*;
public class Main extends JFrame /*implements Runnable*/{
static double clickCount = 0D;
static double cpst = 0D;
static JFrame frameMain = new JFrame("Clicker - Evan");
static JLabel labelCount = new JLabel("Click Count: " + clickCount);
static JLabel labelcps = new JLabel("Click Per Second: " + cpst);
static ArrayList<AutoClicker> clickers = new ArrayList<AutoClicker>(/*Arrays.asList(AutoClicker("Mouse", 1, 10))*/);
static ArrayList<JButton> buttonAuto = new ArrayList<JButton>();
static JButton buttonMain = new JButton("Click");
private static boolean running = false;
//private Thread thread;
public static void main(String[] args){
init();
run();
}
static long lastTime2 = System.nanoTime();
final static double amountOfTicks2 = 2D;
static double ns2 = 1000000000 / amountOfTicks2;
double delta2 = 0;
//Reference: https://www.youtube.com/watch?v=jEXxaPQ_fQo
static class buttonMainAction implements ActionListener{
public void actionPerformed(ActionEvent e){
clickCount++;
System.out.println("refresh?");
}
}
static class buttonBuyAction implements ActionListener{
public void actionPerformed(ActionEvent e){
int fromNumber = Integer.parseInt(e.getActionCommand());
clickCount -= (int)clickers.get( fromNumber ).getCost();
clickers.get( fromNumber ).buy();
buttonAuto.get( fromNumber ).setText(clickers.get( fromNumber ).getNumberOwned()
+ " " + clickers.get( fromNumber ).getName() + "(s) - Cost: " + (int)clickers.get( fromNumber ).getCost() + " Clicks");
System.out.println("+1 " + clickers.get( fromNumber ).getName());
}
}
//Source: https://www.youtube.com/watch?v=qSdKBQMdlLM
//Source 2: https://www.youtube.com/watch?v=vFRuEgEdO9Q&list=PLah6faXAgguMnTBs3JnEJY0shAc18XYQZ&index=4
public static void run(){
long lastTime = System.nanoTime();
final double amountOfTicks = 60D;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
//init();
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if(delta >= 1){
tick();
delta--;
}
render();
}
}
private static void init(){
clickers.add(new AutoClicker("Mouse", .1, 10));
// clickers.add(new AutoClicker("Monkey", .36, 50));
// clickers.add(new AutoClicker("Toddler", .5, 250));
// clickers.add(new AutoClicker("Pre-Teen", 1, 700));
// clickers.add(new AutoClicker("Angsty Teen", 1.5, 1500));
// clickers.add(new AutoClicker("Intern", 2.5, 2000));
// clickers.add(new AutoClicker("Newbie", 5, 4000));
// clickers.add(new AutoClicker("HR Staffer", 10, 10000));
// clickers.add(new AutoClicker("Misc. Staffer", 15, 12000));
// clickers.add(new AutoClicker("Media Analyst", 30, 100000));
// clickers.add(new AutoClicker("CEO", 50, 800000));
// clickers.add(new AutoClicker("Researcher", 80, 2000000));
//
//
// clickers.add(new AutoClicker("Sacrifice Leader", 500, 99999999));
System.out.println("clickers.size()=\t" + clickers.size());
frameMain.setVisible(true);
frameMain.setSize(800, 600);
frameMain.setResizable(false);
frameMain.setDefaultCloseOperation(EXIT_ON_CLOSE);
frameMain.setLayout(new FlowLayout());
frameMain.add(buttonMain);
buttonMain.addActionListener(new buttonMainAction() );
buttonAuto.add(new JButton("0 Mouse(s) - Cost: 10 Clicks"));
// buttonAuto.add(new JButton("0 Monkey(s) - Cost: 50 Clicks"));
// buttonAuto.add(new JButton("0 Toddler(s) - Cost: 250 Clicks"));
// buttonAuto.add(new JButton("0 Pre-Teen(s) - Cost: 700 Clicks"));
// buttonAuto.add(new JButton("0 Angsty Teen(s) - Cost: 1500 Clicks"));
// buttonAuto.add(new JButton("0 Intern(s) - Cost: 2000 Clicks"));
// buttonAuto.add(new JButton("0 Newbie(s) - Cost: 4000 Clicks"));
// buttonAuto.add(new JButton("0 HR Staffer(s) - Cost: 10000 Clicks"));
// buttonAuto.add(new JButton("0 Misc. Staffer(s) - Cost: 12000 Clicks"));
// buttonAuto.add(new JButton("0 Media Analyst(s) - Cost: 100000 Clicks"));
// buttonAuto.add(new JButton("0 CEO(s) - Cost: 800000 Clicks"));
// buttonAuto.add(new JButton("0 Researcher(s) - Cost: 2000000 Clicks"));
// buttonAuto.add(new JButton("0 Sacrafice Leader(s) - Cost: 99999999 Clicks"));
frameMain.add(labelcps);
frameMain.add(labelCount);
for(int i = 0; i<buttonAuto.size(); i++){
buttonAuto.get(i).addActionListener(new buttonBuyAction() );
buttonAuto.get(i).setActionCommand(Integer.toString(i));
frameMain.add(buttonAuto.get(i));
}
running = true;
}
/*
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop(){
if(!running)
return;
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
*/
static void tick(){
//do stuff
for(AutoClicker clicker: clickers){
clickCount += (clicker.getCPS() / 60)* clicker.getNumberOwned();
System.out.println("added " + (clicker.getCPS() / 60)* clicker.getNumberOwned()
+ " from " + clicker.getNumberOwned() + " " + clicker.getName() +"'s");
}
}
static void render(){
double cpst = 0;
for(AutoClicker clicker: clickers){
cpst += (clicker.getCPS())* clicker.getNumberOwned();
}
labelCount.setText("[ Click Count: " + (int)clickCount + " ]");
labelcps.setText("[ Click Per Second: " + ((int)(cpst*10))/10.0 + " ]");
for(int i = 0; i < clickers.size(); i++){
if((int)clickers.get(i).getCost()>clickCount){
if(buttonAuto.get(i).isEnabled())
buttonAuto.get(i).setEnabled(false);
}else{
if(!buttonAuto.get(i).isEnabled())
buttonAuto.get(i).setEnabled(true);
}
}
}
}
这是我的 AutoClicker class:
public class AutoClicker {
private static String name;
private static double cps;
private static double cost;
private static int numberOwned;
public AutoClicker(String nameIn, double cpsIn, int costIn){
name = nameIn;
cps = cpsIn;
cost = costIn;
numberOwned = 0;
}
public String getName(){
return name;
}
public double getCPS(){
return cps;
}
public double getCost(){
return cost;
}
public int getNumberOwned(){
return numberOwned;
}
public void buy(){
numberOwned++;
cost*=1.174;
}
}
非常感谢! ^_^
- 去掉大部分静态修饰符。尤其是 AutoClicker class 中的所有内容。当这些字段是静态的时,它们成为 class 而不是对象的字段,因此每个 AutoClicker 对象与所有其他对象共享相同的字段 -- 这不是您想要的。
事实上,可能唯一应该是静态的应该是 main 方法,仅此而已。然后你可以改变这个:
public static void main(String[] args){
init();
run();
}
对此:
public static void main(String[] args){
Main main = new Main();
main.init();
main.run();
}
还有
- 您已经声明了 cpst 变量两次,一次是 class 的一个字段,一次是
render()
方法的局部变量,最后一个隐藏了 class 字段 --您确定要这样做吗?
- 如评论中所述,您正在主线程中调用
run()
方法中的代码。如果您的代码启动得当,这将在 Swing 事件线程中调用,并会完全冻结您的程序。如果您随后更正此问题并将 Runnable 放置在线程中并对其调用 start()
,那么现在您将在后台线程中改变 Swing 组件——所有这些都是危险的事情。请阅读:课程:Swing 中的并发,了解如何解决此问题。
我正在使用默认的 JFrame gui 开发一个简单的闲置游戏(想想 CookieClicker)。货币单位是 'clicks',赚取足够的 'clicks' 后,玩家应该能够点击与他们可以购买的自动点击器相对应的 JButton。但是,只有添加到自动点击器 ArrayList 的最后一个 'autoclicker' 在正确的时间变得可用,并且如果单击它,所有其他 JButton 将采用其属性。如果可能的话,你能帮我找出问题吗?免责声明:可能是一堆故障排除。
这是我的主要内容 class: (我将额外的 JButtons 和 AutoClickers 注释掉了,所以它按预期工作)
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.*;
public class Main extends JFrame /*implements Runnable*/{
static double clickCount = 0D;
static double cpst = 0D;
static JFrame frameMain = new JFrame("Clicker - Evan");
static JLabel labelCount = new JLabel("Click Count: " + clickCount);
static JLabel labelcps = new JLabel("Click Per Second: " + cpst);
static ArrayList<AutoClicker> clickers = new ArrayList<AutoClicker>(/*Arrays.asList(AutoClicker("Mouse", 1, 10))*/);
static ArrayList<JButton> buttonAuto = new ArrayList<JButton>();
static JButton buttonMain = new JButton("Click");
private static boolean running = false;
//private Thread thread;
public static void main(String[] args){
init();
run();
}
static long lastTime2 = System.nanoTime();
final static double amountOfTicks2 = 2D;
static double ns2 = 1000000000 / amountOfTicks2;
double delta2 = 0;
//Reference: https://www.youtube.com/watch?v=jEXxaPQ_fQo
static class buttonMainAction implements ActionListener{
public void actionPerformed(ActionEvent e){
clickCount++;
System.out.println("refresh?");
}
}
static class buttonBuyAction implements ActionListener{
public void actionPerformed(ActionEvent e){
int fromNumber = Integer.parseInt(e.getActionCommand());
clickCount -= (int)clickers.get( fromNumber ).getCost();
clickers.get( fromNumber ).buy();
buttonAuto.get( fromNumber ).setText(clickers.get( fromNumber ).getNumberOwned()
+ " " + clickers.get( fromNumber ).getName() + "(s) - Cost: " + (int)clickers.get( fromNumber ).getCost() + " Clicks");
System.out.println("+1 " + clickers.get( fromNumber ).getName());
}
}
//Source: https://www.youtube.com/watch?v=qSdKBQMdlLM
//Source 2: https://www.youtube.com/watch?v=vFRuEgEdO9Q&list=PLah6faXAgguMnTBs3JnEJY0shAc18XYQZ&index=4
public static void run(){
long lastTime = System.nanoTime();
final double amountOfTicks = 60D;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
//init();
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if(delta >= 1){
tick();
delta--;
}
render();
}
}
private static void init(){
clickers.add(new AutoClicker("Mouse", .1, 10));
// clickers.add(new AutoClicker("Monkey", .36, 50));
// clickers.add(new AutoClicker("Toddler", .5, 250));
// clickers.add(new AutoClicker("Pre-Teen", 1, 700));
// clickers.add(new AutoClicker("Angsty Teen", 1.5, 1500));
// clickers.add(new AutoClicker("Intern", 2.5, 2000));
// clickers.add(new AutoClicker("Newbie", 5, 4000));
// clickers.add(new AutoClicker("HR Staffer", 10, 10000));
// clickers.add(new AutoClicker("Misc. Staffer", 15, 12000));
// clickers.add(new AutoClicker("Media Analyst", 30, 100000));
// clickers.add(new AutoClicker("CEO", 50, 800000));
// clickers.add(new AutoClicker("Researcher", 80, 2000000));
//
//
// clickers.add(new AutoClicker("Sacrifice Leader", 500, 99999999));
System.out.println("clickers.size()=\t" + clickers.size());
frameMain.setVisible(true);
frameMain.setSize(800, 600);
frameMain.setResizable(false);
frameMain.setDefaultCloseOperation(EXIT_ON_CLOSE);
frameMain.setLayout(new FlowLayout());
frameMain.add(buttonMain);
buttonMain.addActionListener(new buttonMainAction() );
buttonAuto.add(new JButton("0 Mouse(s) - Cost: 10 Clicks"));
// buttonAuto.add(new JButton("0 Monkey(s) - Cost: 50 Clicks"));
// buttonAuto.add(new JButton("0 Toddler(s) - Cost: 250 Clicks"));
// buttonAuto.add(new JButton("0 Pre-Teen(s) - Cost: 700 Clicks"));
// buttonAuto.add(new JButton("0 Angsty Teen(s) - Cost: 1500 Clicks"));
// buttonAuto.add(new JButton("0 Intern(s) - Cost: 2000 Clicks"));
// buttonAuto.add(new JButton("0 Newbie(s) - Cost: 4000 Clicks"));
// buttonAuto.add(new JButton("0 HR Staffer(s) - Cost: 10000 Clicks"));
// buttonAuto.add(new JButton("0 Misc. Staffer(s) - Cost: 12000 Clicks"));
// buttonAuto.add(new JButton("0 Media Analyst(s) - Cost: 100000 Clicks"));
// buttonAuto.add(new JButton("0 CEO(s) - Cost: 800000 Clicks"));
// buttonAuto.add(new JButton("0 Researcher(s) - Cost: 2000000 Clicks"));
// buttonAuto.add(new JButton("0 Sacrafice Leader(s) - Cost: 99999999 Clicks"));
frameMain.add(labelcps);
frameMain.add(labelCount);
for(int i = 0; i<buttonAuto.size(); i++){
buttonAuto.get(i).addActionListener(new buttonBuyAction() );
buttonAuto.get(i).setActionCommand(Integer.toString(i));
frameMain.add(buttonAuto.get(i));
}
running = true;
}
/*
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop(){
if(!running)
return;
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
*/
static void tick(){
//do stuff
for(AutoClicker clicker: clickers){
clickCount += (clicker.getCPS() / 60)* clicker.getNumberOwned();
System.out.println("added " + (clicker.getCPS() / 60)* clicker.getNumberOwned()
+ " from " + clicker.getNumberOwned() + " " + clicker.getName() +"'s");
}
}
static void render(){
double cpst = 0;
for(AutoClicker clicker: clickers){
cpst += (clicker.getCPS())* clicker.getNumberOwned();
}
labelCount.setText("[ Click Count: " + (int)clickCount + " ]");
labelcps.setText("[ Click Per Second: " + ((int)(cpst*10))/10.0 + " ]");
for(int i = 0; i < clickers.size(); i++){
if((int)clickers.get(i).getCost()>clickCount){
if(buttonAuto.get(i).isEnabled())
buttonAuto.get(i).setEnabled(false);
}else{
if(!buttonAuto.get(i).isEnabled())
buttonAuto.get(i).setEnabled(true);
}
}
}
}
这是我的 AutoClicker class:
public class AutoClicker {
private static String name;
private static double cps;
private static double cost;
private static int numberOwned;
public AutoClicker(String nameIn, double cpsIn, int costIn){
name = nameIn;
cps = cpsIn;
cost = costIn;
numberOwned = 0;
}
public String getName(){
return name;
}
public double getCPS(){
return cps;
}
public double getCost(){
return cost;
}
public int getNumberOwned(){
return numberOwned;
}
public void buy(){
numberOwned++;
cost*=1.174;
}
}
非常感谢! ^_^
- 去掉大部分静态修饰符。尤其是 AutoClicker class 中的所有内容。当这些字段是静态的时,它们成为 class 而不是对象的字段,因此每个 AutoClicker 对象与所有其他对象共享相同的字段 -- 这不是您想要的。
事实上,可能唯一应该是静态的应该是 main 方法,仅此而已。然后你可以改变这个:
public static void main(String[] args){
init();
run();
}
对此:
public static void main(String[] args){
Main main = new Main();
main.init();
main.run();
}
还有
- 您已经声明了 cpst 变量两次,一次是 class 的一个字段,一次是
render()
方法的局部变量,最后一个隐藏了 class 字段 --您确定要这样做吗? - 如评论中所述,您正在主线程中调用
run()
方法中的代码。如果您的代码启动得当,这将在 Swing 事件线程中调用,并会完全冻结您的程序。如果您随后更正此问题并将 Runnable 放置在线程中并对其调用start()
,那么现在您将在后台线程中改变 Swing 组件——所有这些都是危险的事情。请阅读:课程:Swing 中的并发,了解如何解决此问题。