从另一个 class 绘制对象到同一个 JFrame
Drawing objects from another class to the same JFrame
我的代码运行了,但是棋盘上没有看到石头
谁能帮忙!!我的目标是让棋盘上的石头 [就像宝石棋一样]
正如 @camickr 在评论中所写,执行此操作的正常方法是让电路板组件绘制其中的内容。
在具有图形用户界面的程序(以及其他程序)中,您通常应该将绘画代码(视图)与您知道要绘画什么分开代码(模型)。这个想法叫做Model-View-Controller.
在这里实施 MVC 意味着您的 Board
class 应该知道要绘制什么或如何绘制它,但不能同时知道两者。我建议有一个
BoardPainter extends JPanel
,视图:知道如何绘制事物本身,对于石头可以到达的每个位置都有一个 StonePainter
(它也扩展了 JPanel
)。它不会保留有关在何处绘制内容的信息;相反,它会在每次需要时从 MancalaState
中询问此信息。当游戏进行得更远时,您也会在这里生成动作:点击来源,点击目的地,
MancalaState
将是模型,它知道每个地方有多少石头,谁应该移动,决定游戏何时结束,等等。如果你在这里实现一个toString()
,你可以很容易地测试整个游戏是否正确运行,不管它是如何绘制的。
要将花盆 (StonePainter
s) 放置在 BoardPainter
中的正确位置,您可以使用现有的 LayoutManager
(甚至嵌套 JPanel),编写您自己的LayoutManager
,或者直接不使用 StonePainter
并直接从 BoardPainter
中的正确位置绘制它们。从我的角度来看,最简单的选择是第一个:
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class Demo {
/** paints a full board */
public static class BoardPainter extends JPanel {
private ArrayList<PotPainter> pots = new ArrayList<>();
private java.util.List<Integer> mancalaBoard; // <-- this would be an actual class
public BoardPainter(java.util.List<Integer> mancalaBoard) {
this.mancalaBoard = mancalaBoard;
setLayout(new BorderLayout());
// a 2x6 grid in the center
JPanel center = new JPanel();
center.setLayout(new GridLayout(2, 6));
for (int i=0; i<12; i++) {
PotPainter p = new PotPainter();
pots.add(p);
center.add(p);
}
add(center, BorderLayout.CENTER);
// one side
PotPainter east = new PotPainter();
pots.add(east);
add(east, BorderLayout.EAST);
east.setPreferredSize(new Dimension(100, 0));
// the other side
PotPainter west = new PotPainter();
pots.add(west);
add(west, BorderLayout.WEST);
west.setPreferredSize(new Dimension(100, 0));
}
public void paint(Graphics g) {
for (int i=0; i<mancalaBoard.size(); i++) {
pots.get(i).setStones(mancalaBoard.get(i));
}
super.paint(g);
}
}
/** paints a pot */
public static class PotPainter extends JPanel {
private static final int MARGIN = 2;
private static final int STONE_SIZE = 10;
private int stones = 0;
public void setStones(int stones) {
this.stones = stones;
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.BLACK);
g.drawOval(MARGIN, MARGIN, getWidth()-MARGIN*2, getHeight()-MARGIN*2);
Random r = new Random();
int d = Math.min(getWidth(), getHeight()) / 2;
Point center = new Point(getWidth()/2, getHeight()/2);
for (int i=0; i<stones; i++) {
g.drawOval(center.x + r.nextInt(d) - d/2, center.y + r.nextInt(d) - d/2,
STONE_SIZE, STONE_SIZE);
}
}
}
public static void main(String ...args) {
SwingUtilities.invokeLater(() -> {
JFrame jf = new JFrame("demo");
jf.add(new BoardPainter(new ArrayList<>(
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 4, 2))));
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(800, 300);
jf.setVisible(true);
});
}
}
示例输出:
我的代码运行了,但是棋盘上没有看到石头
谁能帮忙!!我的目标是让棋盘上的石头 [就像宝石棋一样]
正如 @camickr 在评论中所写,执行此操作的正常方法是让电路板组件绘制其中的内容。
在具有图形用户界面的程序(以及其他程序)中,您通常应该将绘画代码(视图)与您知道要绘画什么分开代码(模型)。这个想法叫做Model-View-Controller.
在这里实施 MVC 意味着您的 Board
class 应该知道要绘制什么或如何绘制它,但不能同时知道两者。我建议有一个
BoardPainter extends JPanel
,视图:知道如何绘制事物本身,对于石头可以到达的每个位置都有一个StonePainter
(它也扩展了JPanel
)。它不会保留有关在何处绘制内容的信息;相反,它会在每次需要时从MancalaState
中询问此信息。当游戏进行得更远时,您也会在这里生成动作:点击来源,点击目的地,MancalaState
将是模型,它知道每个地方有多少石头,谁应该移动,决定游戏何时结束,等等。如果你在这里实现一个toString()
,你可以很容易地测试整个游戏是否正确运行,不管它是如何绘制的。
要将花盆 (StonePainter
s) 放置在 BoardPainter
中的正确位置,您可以使用现有的 LayoutManager
(甚至嵌套 JPanel),编写您自己的LayoutManager
,或者直接不使用 StonePainter
并直接从 BoardPainter
中的正确位置绘制它们。从我的角度来看,最简单的选择是第一个:
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class Demo {
/** paints a full board */
public static class BoardPainter extends JPanel {
private ArrayList<PotPainter> pots = new ArrayList<>();
private java.util.List<Integer> mancalaBoard; // <-- this would be an actual class
public BoardPainter(java.util.List<Integer> mancalaBoard) {
this.mancalaBoard = mancalaBoard;
setLayout(new BorderLayout());
// a 2x6 grid in the center
JPanel center = new JPanel();
center.setLayout(new GridLayout(2, 6));
for (int i=0; i<12; i++) {
PotPainter p = new PotPainter();
pots.add(p);
center.add(p);
}
add(center, BorderLayout.CENTER);
// one side
PotPainter east = new PotPainter();
pots.add(east);
add(east, BorderLayout.EAST);
east.setPreferredSize(new Dimension(100, 0));
// the other side
PotPainter west = new PotPainter();
pots.add(west);
add(west, BorderLayout.WEST);
west.setPreferredSize(new Dimension(100, 0));
}
public void paint(Graphics g) {
for (int i=0; i<mancalaBoard.size(); i++) {
pots.get(i).setStones(mancalaBoard.get(i));
}
super.paint(g);
}
}
/** paints a pot */
public static class PotPainter extends JPanel {
private static final int MARGIN = 2;
private static final int STONE_SIZE = 10;
private int stones = 0;
public void setStones(int stones) {
this.stones = stones;
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.BLACK);
g.drawOval(MARGIN, MARGIN, getWidth()-MARGIN*2, getHeight()-MARGIN*2);
Random r = new Random();
int d = Math.min(getWidth(), getHeight()) / 2;
Point center = new Point(getWidth()/2, getHeight()/2);
for (int i=0; i<stones; i++) {
g.drawOval(center.x + r.nextInt(d) - d/2, center.y + r.nextInt(d) - d/2,
STONE_SIZE, STONE_SIZE);
}
}
}
public static void main(String ...args) {
SwingUtilities.invokeLater(() -> {
JFrame jf = new JFrame("demo");
jf.add(new BoardPainter(new ArrayList<>(
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 4, 2))));
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(800, 300);
jf.setVisible(true);
});
}
}
示例输出: