Java 图形 - 使用构造函数两次删除旧图形
Java Graphics - Using constructor twice delete older graphic
我有一个程序可以在不同位置显示一个 class 的多个元素。为此,我多次使用 class 的构造函数。但问题是只显示了最后一个元素,而没有显示其他元素。
框架的初始化和调用构造函数的地方:
private void initComponents() {
setExtendedState(MAXIMIZED_BOTH);
int width = (int) getContentPane().getBounds().getWidth();
int height = (int) getContentPane().getBounds().getHeight();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new gleis(0, 0, 0, 0));
add(new gleis(1, 0, 1, 0));
add(new gleis(2, 0, 2, 0));
this.setVisible(true);
}
名为'gleis'的元素的class:
public class gleis extends JPanel {
int xposition;
int yposition;
int id;
int status;
public gleis(int xpos, int ypos, int id, int status){
this.xposition = xpos * 11;
this.yposition = ypos * 11 + 4;
this.id = id;
this.status = status;
System.out.println(this.id);
}
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
g.setColor(Color.black);
g.fillRect(this.xposition, this.yposition, 11, 4);
if (this.status == 0)
g.setColor(Color.gray);
else if (this.status == 1)
g.setColor(Color.red);
else if (this.status == 2)
g.setColor(Color.yellow);
else
g.setColor(Color.gray);
g.fillRect(this.xposition + 2, this.yposition + 1, 7, 2);
}
}
那么如何显示我想要的所有元素?
您可能将组件添加到 JFrame 的 contentPane,该组件使用 BorderLayout 作为其默认布局,因此最后输入的组件覆盖了所有其他组件,因为它们被默认添加到BorderLayout.CENTER 位置。
根据你的代码和我对你的用例的假设,我建议改变你的整个方法:
- 使用一个扩展 JPanel 的 class 作为您的绘图 JPanel,并覆盖其 paintComponent 方法。
- 将此 JPanel 添加到您的 JFrame。
- 将 gleis class 的名称更改为 Gleis 以使其符合 Java 命名约定,并使其符合逻辑 class,而不是 GUI 组件 class,所以不要让它覆盖 paintComponent。
- 给Gleis一个
public void draw(Graphics2D g2)
方法。
- 将尽可能多的 Gleis 对象添加到您的绘图 JPanel,然后在 JPanel 的 paintComponent 方法中绘制它们,方法是遍历绘图 JPanel 持有的 Gleis 的 ArrayList,在每个 Gleis 实例上调用
draw(...)
。
例如:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class GleisMain {
private static void createAndShowGui() {
GleisPainter gleisPainter = new GleisPainter();
gleisPainter.addGleis(new Gleis(10, 10, 0, 0));
gleisPainter.addGleis(new Gleis(20, 20, 1, 1));
gleisPainter.addGleis(new Gleis(30, 30, 2, 2));
// I try to avoid having classes extend JFrame and instead use JFrames when needed
JFrame frame = new JFrame("Gleis Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(gleisPainter);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// a single class that extend JPanel and that draws all the Gleis objects
class GleisPainter extends JPanel {
// an ArrayList to hold all the Gleis objects
private List<Gleis> gleisList = new ArrayList<>();
// to allow outside classes to add Gleis objects
public void addGleis(Gleis gleis) {
gleisList.add(gleis);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// loop through our gleis list and draw each instance
Graphics2D g2 = (Graphics2D) g;
for (Gleis gleis : gleisList) {
gleis.draw(g2); // by calling its draw(...) method
}
}
}
// don't have this extend JPanel
class Gleis {
// fields should be private
private int xposition;
private int yposition;
private int id;
private int status;
public Gleis(int xpos, int ypos, int id, int status) {
this.xposition = xpos * 11;
this.yposition = ypos * 11 + 4;
this.id = id;
this.status = status;
System.out.println(this.id);
}
// give this a public draw method where each instance can draw itself
public void draw(Graphics2D g2) {
g2.setColor(Color.black);
// you'll want to avoid "magic" numbers like you're using here:
g2.fillRect(this.xposition, this.yposition, 11, 4);
if (this.status == 0)
g2.setColor(Color.gray);
else if (this.status == 1)
g2.setColor(Color.red);
else if (this.status == 2)
g2.setColor(Color.yellow);
else
g2.setColor(Color.gray);
// ditto about use of "magic" numbers
g2.fillRect(this.xposition + 2, this.yposition + 1, 7, 2);
}
}
我有一个程序可以在不同位置显示一个 class 的多个元素。为此,我多次使用 class 的构造函数。但问题是只显示了最后一个元素,而没有显示其他元素。
框架的初始化和调用构造函数的地方:
private void initComponents() {
setExtendedState(MAXIMIZED_BOTH);
int width = (int) getContentPane().getBounds().getWidth();
int height = (int) getContentPane().getBounds().getHeight();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new gleis(0, 0, 0, 0));
add(new gleis(1, 0, 1, 0));
add(new gleis(2, 0, 2, 0));
this.setVisible(true);
}
名为'gleis'的元素的class:
public class gleis extends JPanel {
int xposition;
int yposition;
int id;
int status;
public gleis(int xpos, int ypos, int id, int status){
this.xposition = xpos * 11;
this.yposition = ypos * 11 + 4;
this.id = id;
this.status = status;
System.out.println(this.id);
}
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
g.setColor(Color.black);
g.fillRect(this.xposition, this.yposition, 11, 4);
if (this.status == 0)
g.setColor(Color.gray);
else if (this.status == 1)
g.setColor(Color.red);
else if (this.status == 2)
g.setColor(Color.yellow);
else
g.setColor(Color.gray);
g.fillRect(this.xposition + 2, this.yposition + 1, 7, 2);
}
}
那么如何显示我想要的所有元素?
您可能将组件添加到 JFrame 的 contentPane,该组件使用 BorderLayout 作为其默认布局,因此最后输入的组件覆盖了所有其他组件,因为它们被默认添加到BorderLayout.CENTER 位置。
根据你的代码和我对你的用例的假设,我建议改变你的整个方法:
- 使用一个扩展 JPanel 的 class 作为您的绘图 JPanel,并覆盖其 paintComponent 方法。
- 将此 JPanel 添加到您的 JFrame。
- 将 gleis class 的名称更改为 Gleis 以使其符合 Java 命名约定,并使其符合逻辑 class,而不是 GUI 组件 class,所以不要让它覆盖 paintComponent。
- 给Gleis一个
public void draw(Graphics2D g2)
方法。 - 将尽可能多的 Gleis 对象添加到您的绘图 JPanel,然后在 JPanel 的 paintComponent 方法中绘制它们,方法是遍历绘图 JPanel 持有的 Gleis 的 ArrayList,在每个 Gleis 实例上调用
draw(...)
。
例如:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class GleisMain {
private static void createAndShowGui() {
GleisPainter gleisPainter = new GleisPainter();
gleisPainter.addGleis(new Gleis(10, 10, 0, 0));
gleisPainter.addGleis(new Gleis(20, 20, 1, 1));
gleisPainter.addGleis(new Gleis(30, 30, 2, 2));
// I try to avoid having classes extend JFrame and instead use JFrames when needed
JFrame frame = new JFrame("Gleis Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(gleisPainter);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// a single class that extend JPanel and that draws all the Gleis objects
class GleisPainter extends JPanel {
// an ArrayList to hold all the Gleis objects
private List<Gleis> gleisList = new ArrayList<>();
// to allow outside classes to add Gleis objects
public void addGleis(Gleis gleis) {
gleisList.add(gleis);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// loop through our gleis list and draw each instance
Graphics2D g2 = (Graphics2D) g;
for (Gleis gleis : gleisList) {
gleis.draw(g2); // by calling its draw(...) method
}
}
}
// don't have this extend JPanel
class Gleis {
// fields should be private
private int xposition;
private int yposition;
private int id;
private int status;
public Gleis(int xpos, int ypos, int id, int status) {
this.xposition = xpos * 11;
this.yposition = ypos * 11 + 4;
this.id = id;
this.status = status;
System.out.println(this.id);
}
// give this a public draw method where each instance can draw itself
public void draw(Graphics2D g2) {
g2.setColor(Color.black);
// you'll want to avoid "magic" numbers like you're using here:
g2.fillRect(this.xposition, this.yposition, 11, 4);
if (this.status == 0)
g2.setColor(Color.gray);
else if (this.status == 1)
g2.setColor(Color.red);
else if (this.status == 2)
g2.setColor(Color.yellow);
else
g2.setColor(Color.gray);
// ditto about use of "magic" numbers
g2.fillRect(this.xposition + 2, this.yposition + 1, 7, 2);
}
}