为什么 repaint() 后方块不显示?
Why wont squares show up after repaint()?
我早些时候发布了这个问题,并被告知将其设为 SSCCE,所以这里开始(如果我可以做出任何改进,请随时告诉我):
我想知道为什么当我的按钮 "confirm" 被点击时旧方块消失并且重绘的方块没有出现在我的 GUI 上(用 swing 制作)。 Squares class 绘制了 200 个间隔开的正方形,其 ID(0、1、2 或 3 作为字符串)在内部从不同的 class 获得(为了这个问题的目的,我们假设它总是0 且不包括 class)。为了澄清:Squares 第一次完美地绘制了所有内容(也检索了正确的 ID),但我希望它在使用新 ID 单击按钮后重新绘制所有内容。
方块代码:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class Squares extends JPanel{
private ArrayList<Rectangle> squares = new ArrayList<Rectangle>();
private String stringID = "0";
public void addSquare(int x, int y, int width, int height, int ID) {
Rectangle rect = new Rectangle(x, y, width, height);
squares.add(rect);
stringID = Integer.toString(ID);
if(ID == 0){
stringID = "";
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontMetrics fm = g2.getFontMetrics();
int fontAscent = fm.getAscent();
g2.setClip(new Rectangle(0,0,Integer.MAX_VALUE,Integer.MAX_VALUE));
for (Rectangle rect : squares) {
g2.drawString(stringID, rect.x + 7, rect.y + 2 + fontAscent);
g2.draw(rect);
}
}
}
GUI 代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUIReserver extends JFrame implements Runnable{
private int myID;
private JButton confirm = new JButton("Check Availability and Confirm Reservation");
private JFrame GUI = new JFrame();
private Squares square;
public GUIReserver(int i) {
this.myID = i;
}
@Override
public void run() {
int rows = 50;
int seatsInRow = 4;
confirm.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
GUI.getContentPane().remove(square);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this does not show up at all (could be that it wasn't drawn, could be that it is out of view etc...)
GUI.repaint(); //the line in question
}
});
GUI.setLayout(new FlowLayout());
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setLocation(0,0);
GUI.setExtendedState(JFrame.MAXIMIZED_BOTH);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this shows up the way I wish
GUI.add(confirm);
GUI.pack();
GUI.setVisible(true);
}
}
主要代码:
public class AircraftSeatReservation {
static AircraftSeatReservation me = new AircraftSeatReservation();
private final int rows = 50;
private final int seatsInRow = 4;
private int seatsAvailable = rows * seatsInRow;
private Thread t3;
public static void main(String[] args) {
GUIReserver GR1 = new GUIReserver(3);
me.t3 = new Thread(GR1);
me.t3.start();
}
}
一个主要问题:您的 Squares JPanels 首选大小仅为 20 x 20,并且实际上可能是该大小,因为它似乎被添加到使用 FlowLayout 的容器中。接下来,您似乎要在远远超出该组件边界的位置进行绘图,因此这些绘图可能永远不会被看到。考虑允许您的 Squares 对象更大,并确保仅在该组件的边界内绘制。
另请注意,有些代码没有意义,包括:
private int myID;
private JTextField row, column, instru draft saved // ???
package question2;ction1, instruction2, seatLabel, rowLabel; // ???
我猜是
private int myID;
private JTextField row, column, instruction1, instruction2, seatLabel, rowLabel;
这不会为我们编译:
int rows = AircraftSeatReservation.getRows();
int seatsInRow = AircraftSeatReservation.getSeatsInRow(); // and shouldn't this take an int row parameter?
因为我们没有您的 AircraftSeatReservation class(希望您真的没有静态方法 class)。
而且我们无法编译或 运行 您当前的代码。我们不想看到你的整个程序,而是你应该将你的代码压缩成仍然可以编译的最小部分,没有与你的问题无关的额外代码,但仍然可以证明你的问题。因此,正如 Andrew Thompson 所建议的那样,为了获得更好的帮助,请创建并 post 您的 Minimal, Complete, and Verifiable example or Short, Self Contained, Correct Example.
我会尽可能地尝试 OOP-ify 你的问题,让你分而治之。这可能涉及:
- 创建一个
SeatClass
枚举,其中可能包含两个元素,FIRST 和 COACH。
- 创建一个非 GUI 座位 class,一个有几个字段,可能包括:int row,char seat(例如 A、B、C、D、E、F),一个 SeatClass 字段以供查看如果它是第一个 class 座位或教练,以及一个布尔保留字段,只有在座位被保留时才为真。
- 这个 class 也有一个 getId() 方法,returns 行号和座位字符的字符串连接。
- 创建一架非 GUI 飞机 class,一个拥有两个座位阵列,一个用于 SeatClass.FIRST 或第一个 class 个座位,一个用于 SeatClass.COACH .
- 它还有一个行数字段和一个座位数(列数)字段。
- 创建所有这些后,然后在您的 GUI 上工作 classes。
- 我会为 Seats 创建一个 GUI class,也许是 GuiSeat,让它包含一个 Seat 对象,也许让它扩展 JPanel,允许它显示它自己的 id String,它从它包含的 Seat 中获取对象,让它覆盖
getBackground(...)
,这样它的颜色将取决于座位是否已预订。
- 等等.......
我早些时候发布了这个问题,并被告知将其设为 SSCCE,所以这里开始(如果我可以做出任何改进,请随时告诉我): 我想知道为什么当我的按钮 "confirm" 被点击时旧方块消失并且重绘的方块没有出现在我的 GUI 上(用 swing 制作)。 Squares class 绘制了 200 个间隔开的正方形,其 ID(0、1、2 或 3 作为字符串)在内部从不同的 class 获得(为了这个问题的目的,我们假设它总是0 且不包括 class)。为了澄清:Squares 第一次完美地绘制了所有内容(也检索了正确的 ID),但我希望它在使用新 ID 单击按钮后重新绘制所有内容。 方块代码:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class Squares extends JPanel{
private ArrayList<Rectangle> squares = new ArrayList<Rectangle>();
private String stringID = "0";
public void addSquare(int x, int y, int width, int height, int ID) {
Rectangle rect = new Rectangle(x, y, width, height);
squares.add(rect);
stringID = Integer.toString(ID);
if(ID == 0){
stringID = "";
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontMetrics fm = g2.getFontMetrics();
int fontAscent = fm.getAscent();
g2.setClip(new Rectangle(0,0,Integer.MAX_VALUE,Integer.MAX_VALUE));
for (Rectangle rect : squares) {
g2.drawString(stringID, rect.x + 7, rect.y + 2 + fontAscent);
g2.draw(rect);
}
}
}
GUI 代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUIReserver extends JFrame implements Runnable{
private int myID;
private JButton confirm = new JButton("Check Availability and Confirm Reservation");
private JFrame GUI = new JFrame();
private Squares square;
public GUIReserver(int i) {
this.myID = i;
}
@Override
public void run() {
int rows = 50;
int seatsInRow = 4;
confirm.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
GUI.getContentPane().remove(square);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this does not show up at all (could be that it wasn't drawn, could be that it is out of view etc...)
GUI.repaint(); //the line in question
}
});
GUI.setLayout(new FlowLayout());
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setLocation(0,0);
GUI.setExtendedState(JFrame.MAXIMIZED_BOTH);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this shows up the way I wish
GUI.add(confirm);
GUI.pack();
GUI.setVisible(true);
}
}
主要代码:
public class AircraftSeatReservation {
static AircraftSeatReservation me = new AircraftSeatReservation();
private final int rows = 50;
private final int seatsInRow = 4;
private int seatsAvailable = rows * seatsInRow;
private Thread t3;
public static void main(String[] args) {
GUIReserver GR1 = new GUIReserver(3);
me.t3 = new Thread(GR1);
me.t3.start();
}
}
一个主要问题:您的 Squares JPanels 首选大小仅为 20 x 20,并且实际上可能是该大小,因为它似乎被添加到使用 FlowLayout 的容器中。接下来,您似乎要在远远超出该组件边界的位置进行绘图,因此这些绘图可能永远不会被看到。考虑允许您的 Squares 对象更大,并确保仅在该组件的边界内绘制。
另请注意,有些代码没有意义,包括:
private int myID;
private JTextField row, column, instru draft saved // ???
package question2;ction1, instruction2, seatLabel, rowLabel; // ???
我猜是
private int myID;
private JTextField row, column, instruction1, instruction2, seatLabel, rowLabel;
这不会为我们编译:
int rows = AircraftSeatReservation.getRows();
int seatsInRow = AircraftSeatReservation.getSeatsInRow(); // and shouldn't this take an int row parameter?
因为我们没有您的 AircraftSeatReservation class(希望您真的没有静态方法 class)。
而且我们无法编译或 运行 您当前的代码。我们不想看到你的整个程序,而是你应该将你的代码压缩成仍然可以编译的最小部分,没有与你的问题无关的额外代码,但仍然可以证明你的问题。因此,正如 Andrew Thompson 所建议的那样,为了获得更好的帮助,请创建并 post 您的 Minimal, Complete, and Verifiable example or Short, Self Contained, Correct Example.
我会尽可能地尝试 OOP-ify 你的问题,让你分而治之。这可能涉及:
- 创建一个
SeatClass
枚举,其中可能包含两个元素,FIRST 和 COACH。 - 创建一个非 GUI 座位 class,一个有几个字段,可能包括:int row,char seat(例如 A、B、C、D、E、F),一个 SeatClass 字段以供查看如果它是第一个 class 座位或教练,以及一个布尔保留字段,只有在座位被保留时才为真。
- 这个 class 也有一个 getId() 方法,returns 行号和座位字符的字符串连接。
- 创建一架非 GUI 飞机 class,一个拥有两个座位阵列,一个用于 SeatClass.FIRST 或第一个 class 个座位,一个用于 SeatClass.COACH .
- 它还有一个行数字段和一个座位数(列数)字段。
- 创建所有这些后,然后在您的 GUI 上工作 classes。
- 我会为 Seats 创建一个 GUI class,也许是 GuiSeat,让它包含一个 Seat 对象,也许让它扩展 JPanel,允许它显示它自己的 id String,它从它包含的 Seat 中获取对象,让它覆盖
getBackground(...)
,这样它的颜色将取决于座位是否已预订。 - 等等.......