我正在Java Swing中创建一个基本的Tic-Tac-Toe应用程序,为此,我开始研究绘图。但是,当JPanel
的子类包含JLabel
的子类的多个实例时,我遇到了一个问题,它以paintComponent(Graphic)
数组格式覆盖了GridLayout
方法嵌入自身。问题是只绘制了此数组中的第一个元素。
JLabel
的自定义子类的示例:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JLabel;
@SuppressWarnings("serial")
public class DrawLabel extends JLabel {
private boolean hasPaint;
public DrawLabel() {
super();
this.hasPaint = false;
}
public void draw() {
hasPaint = true;
repaint();
}
public void clear() {
hasPaint = false;
repaint();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (hasPaint) {
g2.drawOval(getX(), getY(), getWidth(), getHeight());
} else {
g2.clearRect(getX(), getY(), getWidth(), getHeight());
}
}
}
JPanel
的自定义子类的示例:
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class DrawPanel extends JPanel {
private Dimension size;
private DrawLabel[][] fields;
public DrawPanel(Dimension d) {
super();
this.size = d;
this.fields = new DrawLabel[size.height][size.width];
this.setLayout(new GridLayout(size.height, size.width));
for (int i = 0; i < size.height; i++) {
for (int j = 0; j < size.width; j++) {
this.fields[i][j] = new DrawLabel();
this.add(fields[i][j]);
}
}
}
public void draw(int row, int col) {
fields[row][col].draw();
}
public void clear() {
for (int i = 0; i < size.height; i++) {
for (int j = 0; j < size.width; j++) {
fields[i][j].clear();
}
}
}
}
一个引发问题的场景的例子:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
public class Driver {
public static void main(String[] args) {
DrawPanel board = new DrawPanel(new Dimension(2, 1));
JFrame canvas = new JFrame();
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
canvas.add(board, BorderLayout.CENTER);
canvas.pack();
canvas.setLocationRelativeTo(null);
canvas.setVisible(true);
board.draw(0, 0); // This gets painted.
board.draw(0, 1); // This does not get painted!
}
}
奇怪的是,如果更改DrawPanel.draw(int, int)
以设置元素的文本而不是绘制它,则只更新第二个元素,而第一个元素不更新,这与原始问题完全相反。
我试图查找与子组件绘制相关的其他问题和问题,但我还没有找到像这样的问题,似乎GridLayout
中第一个以外的每个实例都不可绘制以同样的方式。可能有什么不对?
感谢您的时间和精力!
答案 0 :(得分:4)
g2.drawOval(getX(), getY(), getWidth(), getHeight());
组件的绘制是相对于组件进行的,而不是绘制组件的面板.getX / Y()方法返回组件相对于父组件的位置。
因此,如果每个组件的大小为(200,200),则第一个组件的椭圆将使用
绘制g2.drawOval(0, 0, 200, 200);
第二部分将在以下位置绘制:
g2.drawOval(200, 0, 200, 200);
但由于该组件的宽度仅为200像素,因此200的起始x位置超出了组件的范围,因此无需绘制任何内容。
而只是使用:
g2.drawOval(0, 0, getWidth(), getHeight());