在 CardLayout 中重绘字符串
Redraw strings in CardLayout
我已经使用 CardLayout 制作了一款游戏,并且有一个用于排行榜的 JPanel。在排行榜中,我读取了两个文件(一个有名称,一个有时间),对它们进行排序并绘制前 5 个最快的时间,如下所示:
private void setBoard(){
reset();
try{
br = new BufferedReader (new FileReader("username.txt"));
accounts = ""+br.readLine().trim();
arrNames = accounts.split(" ");
br.close();
br = new BufferedReader (new FileReader("time.txt"));
allTimes = ""+br.readLine().trim();
arrTimesTemp = allTimes.split(" ");
arrTime = new double [arrTimesTemp.length];
br.close();
} catch (Exception er){
System.out.print("Error" + er);
}
for (int i=0;i<arrTime.length;i++)
arrTime[i]=Double.parseDouble(arrTimesTemp[i]);;
scores = new Score[arrTime.length];
for (int i=0;i<arrTime.length;i++)
scores[i] = new Score (arrNames[i],arrTime[i]);
Arrays.sort(scores, new MyComparator());
System.out.println("\n\n\n");
for (int i=0;i<arrTime.length;i++)
System.out.println(arrTime[i]+" "+arrNames[i]);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(title, getWidth()/2-title.getWidth()/2+10, 125, this);
g.drawImage(txt, getWidth()/2-txt.getWidth()/2+10, 250, this);
setBoard();
g.setFont(new Font("Serif", Font.PLAIN, 25));
g.setColor(Color.white);
for (int i=0;i<5;i++){
g.drawString((i+1)+"-", numX, lineY);
g.drawString(scores[i].getName(), nameX, lineY);
g.drawString(""+scores[i].getTime(), timeX, lineY);
g.drawString("s", 515, lineY);
lineY+=40;
}
}
第一次打开排行榜没有问题。但是,如果我 return 到菜单然后返回排行榜,则不会绘制字符串,但会绘制图像。我也没有得到任何错误。我不明白为什么会这样。
我如何return进入菜单:
public void actionPerformed(ActionEvent e) {
if (e.getSource()==back)
RunGame.card.first(RunGame.c);
}
如何从菜单进入排行榜:
else if (e.getSource()==d) //d is a JButton
RunGame.card.show(RunGame.c,"Leaderboard");
leaderboard first time
leaderboard when return to it
I solved my problem. I just had to reset numX nameX timeX lineY each time I switched to leaderboard
好吧,我们吸取了教训,全局状态是一件坏事...
好的,由于我花了一些时间将示例放在一起,所以我 post 它是为了演示共享状态的基本概念。
此示例创建了一个在主视图之间共享的 LeaderBoardModel
。这允许在代码的不同方面之间共享状态,而无需明确了解它的实际工作方式 - 模型成为一个独立的工作单元并且可以管理它自己的状态。
这里的另一个方面是尽可能快地保持绘制路径 - 因此,即使在这个示例中,也可以考虑对列表进行排序和拆分以进行优化......但我们并没有尝试达到 200fps ...所以,平衡...
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
LeaderBoardModel model = new LeaderBoardModel();
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridx = 0;
gbc.gridy = 0;
CardLayout cardLayout = new CardLayout();
JPanel mainPane = new JPanel(cardLayout);
mainPane.add(new GamePanel(model), "main");
mainPane.add(new LeaderBoardPanel(model), "leaderBoard");
cardLayout.show(mainPane, "main");
frame.add(mainPane, gbc);
JPanel buttons = new JPanel(new GridBagLayout());
JButton main = new JButton("Main");
JButton board = new JButton("Board");
buttons.add(main);
buttons.add(board);
main.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(mainPane, "main");
}
});
board.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(mainPane, "leaderBoard");
}
});
gbc.weightx = 1;
gbc.weighty = 0;
gbc.gridy++;
frame.add(buttons, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
// I'd prefer to use interfaces as a base line concept, but, this is
// is a demonstration of a concept, not a tutorial
public class Score implements Comparable<Score> {
private String name;
private int score;
public Score(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
@Override
public int compareTo(Score o) {
return o.score - score;
}
@Override
public String toString() {
return name + " ~ " + score;
}
}
// I'd prefer to use interfaces as a base line concept, but, this is
// is a demonstration of a concept, not a tutorial
public class LeaderBoardModel {
private List<Score> scores;
public LeaderBoardModel() {
// This is where you'd consider loading the scores from
// the original file...
scores = new ArrayList<>(25);
Random rnd = new Random();
add(new Score("Shekhar", rnd.nextInt(99) + 1));
add(new Score("Priyanka", rnd.nextInt(99) + 1));
add(new Score("Vivi", rnd.nextInt(99) + 1));
add(new Score("Darwin", rnd.nextInt(99) + 1));
add(new Score("Hálfdan", rnd.nextInt(99) + 1));
add(new Score("Emmerson", rnd.nextInt(99) + 1));
add(new Score("Marie", rnd.nextInt(99) + 1));
add(new Score("Mikha'il", rnd.nextInt(99) + 1));
add(new Score("Jayanta", rnd.nextInt(99) + 1));
add(new Score("Theodosia", rnd.nextInt(99) + 1));
add(new Score("Sharleen", rnd.nextInt(99) + 1));
add(new Score("Kristian", rnd.nextInt(99) + 1));
add(new Score("Alberte", rnd.nextInt(99) + 1));
add(new Score("Maylis", rnd.nextInt(99) + 1));
add(new Score("Katayun", rnd.nextInt(99) + 1));
}
public void save() {
// Well, because it's nice to remember this stuff
}
public void add(Score score) {
// We could sort the list here, lots of ways to do it ...
// but waste the time if we don't actually need to
scores.add(score);
}
public List<Score> getScores() {
// Could use a flag to determine if this actually needs to be
// sorted or not ... but this is just a demonstration :/
Collections.sort(scores);
return Collections.unmodifiableList(scores);
}
}
public class GamePanel extends JPanel {
private LeaderBoardModel model;
private Random rnd = new Random();
public GamePanel(LeaderBoardModel model) {
this.model = model;
setLayout(new GridBagLayout());
JButton btn = new JButton("Win");
add(btn);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
model.add(new Score("l334", rnd.nextInt(99) + 100));
}
});
}
}
public class LeaderBoardPanel extends JPanel {
private LeaderBoardModel model;
public LeaderBoardPanel(LeaderBoardModel model) {
this.model = model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
String highScore = "High Score";
FontMetrics fm = g2d.getFontMetrics();
int xPos = (getWidth() - fm.stringWidth(highScore)) / 2;
int yPos = 10;
g2d.drawString(highScore, xPos, yPos + fm.getAscent());
yPos += fm.getHeight() * 2;
List<Score> scores = model.getScores();
scores = scores.subList(0, Math.min(10, scores.size() - 1));
for (Score score : scores) {
String name = score.getName();
String value = Integer.toString(score.getScore());
xPos = (getWidth() / 2) - fm.stringWidth(name) - 5;
g2d.drawString(name, xPos, yPos + fm.getAscent());
xPos = (getWidth() / 2) + 5;
g2d.drawString(value, xPos, yPos + fm.getAscent());
yPos += fm.getHeight();
}
g2d.dispose();
}
}
}
我已经使用 CardLayout 制作了一款游戏,并且有一个用于排行榜的 JPanel。在排行榜中,我读取了两个文件(一个有名称,一个有时间),对它们进行排序并绘制前 5 个最快的时间,如下所示:
private void setBoard(){
reset();
try{
br = new BufferedReader (new FileReader("username.txt"));
accounts = ""+br.readLine().trim();
arrNames = accounts.split(" ");
br.close();
br = new BufferedReader (new FileReader("time.txt"));
allTimes = ""+br.readLine().trim();
arrTimesTemp = allTimes.split(" ");
arrTime = new double [arrTimesTemp.length];
br.close();
} catch (Exception er){
System.out.print("Error" + er);
}
for (int i=0;i<arrTime.length;i++)
arrTime[i]=Double.parseDouble(arrTimesTemp[i]);;
scores = new Score[arrTime.length];
for (int i=0;i<arrTime.length;i++)
scores[i] = new Score (arrNames[i],arrTime[i]);
Arrays.sort(scores, new MyComparator());
System.out.println("\n\n\n");
for (int i=0;i<arrTime.length;i++)
System.out.println(arrTime[i]+" "+arrNames[i]);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(title, getWidth()/2-title.getWidth()/2+10, 125, this);
g.drawImage(txt, getWidth()/2-txt.getWidth()/2+10, 250, this);
setBoard();
g.setFont(new Font("Serif", Font.PLAIN, 25));
g.setColor(Color.white);
for (int i=0;i<5;i++){
g.drawString((i+1)+"-", numX, lineY);
g.drawString(scores[i].getName(), nameX, lineY);
g.drawString(""+scores[i].getTime(), timeX, lineY);
g.drawString("s", 515, lineY);
lineY+=40;
}
}
第一次打开排行榜没有问题。但是,如果我 return 到菜单然后返回排行榜,则不会绘制字符串,但会绘制图像。我也没有得到任何错误。我不明白为什么会这样。
我如何return进入菜单:
public void actionPerformed(ActionEvent e) {
if (e.getSource()==back)
RunGame.card.first(RunGame.c);
}
如何从菜单进入排行榜:
else if (e.getSource()==d) //d is a JButton
RunGame.card.show(RunGame.c,"Leaderboard");
leaderboard first time leaderboard when return to it
I solved my problem. I just had to reset numX nameX timeX lineY each time I switched to leaderboard
好吧,我们吸取了教训,全局状态是一件坏事...
好的,由于我花了一些时间将示例放在一起,所以我 post 它是为了演示共享状态的基本概念。
此示例创建了一个在主视图之间共享的 LeaderBoardModel
。这允许在代码的不同方面之间共享状态,而无需明确了解它的实际工作方式 - 模型成为一个独立的工作单元并且可以管理它自己的状态。
这里的另一个方面是尽可能快地保持绘制路径 - 因此,即使在这个示例中,也可以考虑对列表进行排序和拆分以进行优化......但我们并没有尝试达到 200fps ...所以,平衡...
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
LeaderBoardModel model = new LeaderBoardModel();
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridx = 0;
gbc.gridy = 0;
CardLayout cardLayout = new CardLayout();
JPanel mainPane = new JPanel(cardLayout);
mainPane.add(new GamePanel(model), "main");
mainPane.add(new LeaderBoardPanel(model), "leaderBoard");
cardLayout.show(mainPane, "main");
frame.add(mainPane, gbc);
JPanel buttons = new JPanel(new GridBagLayout());
JButton main = new JButton("Main");
JButton board = new JButton("Board");
buttons.add(main);
buttons.add(board);
main.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(mainPane, "main");
}
});
board.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(mainPane, "leaderBoard");
}
});
gbc.weightx = 1;
gbc.weighty = 0;
gbc.gridy++;
frame.add(buttons, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
// I'd prefer to use interfaces as a base line concept, but, this is
// is a demonstration of a concept, not a tutorial
public class Score implements Comparable<Score> {
private String name;
private int score;
public Score(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
@Override
public int compareTo(Score o) {
return o.score - score;
}
@Override
public String toString() {
return name + " ~ " + score;
}
}
// I'd prefer to use interfaces as a base line concept, but, this is
// is a demonstration of a concept, not a tutorial
public class LeaderBoardModel {
private List<Score> scores;
public LeaderBoardModel() {
// This is where you'd consider loading the scores from
// the original file...
scores = new ArrayList<>(25);
Random rnd = new Random();
add(new Score("Shekhar", rnd.nextInt(99) + 1));
add(new Score("Priyanka", rnd.nextInt(99) + 1));
add(new Score("Vivi", rnd.nextInt(99) + 1));
add(new Score("Darwin", rnd.nextInt(99) + 1));
add(new Score("Hálfdan", rnd.nextInt(99) + 1));
add(new Score("Emmerson", rnd.nextInt(99) + 1));
add(new Score("Marie", rnd.nextInt(99) + 1));
add(new Score("Mikha'il", rnd.nextInt(99) + 1));
add(new Score("Jayanta", rnd.nextInt(99) + 1));
add(new Score("Theodosia", rnd.nextInt(99) + 1));
add(new Score("Sharleen", rnd.nextInt(99) + 1));
add(new Score("Kristian", rnd.nextInt(99) + 1));
add(new Score("Alberte", rnd.nextInt(99) + 1));
add(new Score("Maylis", rnd.nextInt(99) + 1));
add(new Score("Katayun", rnd.nextInt(99) + 1));
}
public void save() {
// Well, because it's nice to remember this stuff
}
public void add(Score score) {
// We could sort the list here, lots of ways to do it ...
// but waste the time if we don't actually need to
scores.add(score);
}
public List<Score> getScores() {
// Could use a flag to determine if this actually needs to be
// sorted or not ... but this is just a demonstration :/
Collections.sort(scores);
return Collections.unmodifiableList(scores);
}
}
public class GamePanel extends JPanel {
private LeaderBoardModel model;
private Random rnd = new Random();
public GamePanel(LeaderBoardModel model) {
this.model = model;
setLayout(new GridBagLayout());
JButton btn = new JButton("Win");
add(btn);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
model.add(new Score("l334", rnd.nextInt(99) + 100));
}
});
}
}
public class LeaderBoardPanel extends JPanel {
private LeaderBoardModel model;
public LeaderBoardPanel(LeaderBoardModel model) {
this.model = model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
String highScore = "High Score";
FontMetrics fm = g2d.getFontMetrics();
int xPos = (getWidth() - fm.stringWidth(highScore)) / 2;
int yPos = 10;
g2d.drawString(highScore, xPos, yPos + fm.getAscent());
yPos += fm.getHeight() * 2;
List<Score> scores = model.getScores();
scores = scores.subList(0, Math.min(10, scores.size() - 1));
for (Score score : scores) {
String name = score.getName();
String value = Integer.toString(score.getScore());
xPos = (getWidth() / 2) - fm.stringWidth(name) - 5;
g2d.drawString(name, xPos, yPos + fm.getAscent());
xPos = (getWidth() / 2) + 5;
g2d.drawString(value, xPos, yPos + fm.getAscent());
yPos += fm.getHeight();
}
g2d.dispose();
}
}
}