因此,有一段時間覆蓋JComponent的paint方法給了我麻煩,我永遠不知道爲什麼。我正在研究一個項目,該項目將拍攝黑白圖像並將其繪製在屏幕上,其中畫面中的每個像素都是屏幕上的50 x 50框,顯然有些繪畫將在屏幕外完成,但這是可以的,因爲它將是一個2D移動屏幕的自上而下的遊戲。無論我嘗試過什麼,它在運行時都不會在屏幕上畫任何東西,它與我的1:50邏輯沒有任何關係,因爲當我試圖繪製一個簡單的矩形時,它甚至沒有繪製這個矩形。所以問題必須出現在繪畫方法中,但我無法弄清楚什麼是錯誤的。我知道這是很多代碼,但有人可以讓我知道什麼是錯的? (我知道有很多是沒有被尚未使用方法,只是忽略那些那些)爲什麼我的Paint surface方法不起作用?
這是JFrame類:
(你必須爲黑白圖像的路徑在這個類中繪製)
`package Code;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//class that stores all of the painting methods and the GUI methods:
public class Window extends JFrame{
double WINDOWWIDTH, WINDOWHEIGHT;
JPanel TitlePanel;
JButton PlayGame, Quit;
JLabel Title;
Map DigitizedMap;
PaintSurface PS;
int x = 0;
int y = 0;
int TilesAcross;
int TilesDown;
public Window(){
WINDOWWIDTH = 1200;
WINDOWHEIGHT = (Math.floor(WINDOWWIDTH/50)*0.66) * 50;
TilesAcross = (int) (WINDOWWIDTH/50);
TilesDown = (int) (WINDOWHEIGHT/50);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize((int) WINDOWWIDTH, (int) WINDOWHEIGHT);
this.setTitle("Stealth Client || Version 1.0");
//all of the code for the user interface will go here:
//DrawStartInterface(this);
//creating the digitized verion of the map for the paint method to use:
MapLoader ML = new MapLoader("C:\\Users\\Greg\\Desktop\\TestMap.png");
DigitizedMap = ML.ConvertMap();
PS = new PaintSurface();
TitlePanel = new JPanel();
TitlePanel.add(PS, BorderLayout.CENTER);
this.add(TitlePanel);
this.setVisible(true);
this.setResizable(false);
}
private void DrawStartInterface(JFrame f){
//all of the starting UI:
TitlePanel = new JPanel(new GridBagLayout());
TitlePanel.setBackground(Color.DARK_GRAY);
Title = new JLabel("STEALTH");
Title.setForeground(Color.ORANGE);
Title.setFont(new Font("Calabri", Font.BOLD, 48));
addItem(TitlePanel, Title, 0, 0, 1, 1, 1);
PlayGame = new JButton("Play");
PlayGame.setBackground(Color.BLACK);
PlayGame.setForeground(Color.ORANGE);
PlayGame.setFont(new Font("Calabri", Font.BOLD, 36));
PlayGame.addActionListener(new ActionEvent());
addItem(TitlePanel, PlayGame, 0, 1, 1, 1, 1);
Quit = new JButton("Quit");
Quit.setBackground(Color.BLACK);
Quit.setForeground(Color.ORANGE);
Quit.setFont(new Font("Calabri", Font.BOLD, 36));
Quit.addActionListener(new ActionEvent());
addItem(TitlePanel, Quit, 0, 2, 1, 1, 1);
f.add(TitlePanel);
}
private class ActionEvent implements ActionListener{
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
//which action has been heard:
if(e.getSource() == PlayGame){
//plays the game:
StartGame();
} else if(e.getSource() == Quit){
//Quits the game:
Terminate();
}
}
}
public void Terminate(){
//exits the game:
System.exit(0);
}
//Starts the game:
private void StartGame(){
TitlePanel.add(PS);
}
//The paint Surface class that will be stored in the panel and paint the game:
class PaintSurface extends JComponent{
@Override
public void paint (Graphics g){
//basic graphics shizel wizel:
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawRect(100, 100, 100, 100);
render(g2);
System.out.println("Painted");
}
private void render(Graphics2D g2){
//renders only the squares within a certain distance of the center of the screen:
int PlayerTileX = (int) Math.ceil((x + (WINDOWWIDTH/2))/50); // This is the x tile that the player is in
int PlayerTileY = (int) Math.ceil((y + (WINDOWHEIGHT/2))/50); // this is the y tile that the player is in
//now we are going through only the tiles around the player and rendering them:
int XOffset = x - (int) (PlayerTileX - (Math.ceil(TilesAcross/2)));
int YOffset = y - (int) (PlayerTileY - (Math.ceil(TilesDown/2)));
for (int i = (int) (PlayerTileX - (Math.ceil(TilesAcross/2))); i < (int) (PlayerTileX + (Math.ceil(TilesAcross/2))); i++){
for (int n = (int) (PlayerTileY - (Math.ceil(TilesDown/2))); n < (int) (PlayerTileY + (Math.ceil(TilesDown/2))); n++){
//this is where only the coorect boxes will be rendered because of the limiting for loops:
//The if statement for determining what type of thing it is:
if (DigitizedMap.getTile(i, n) == 1){
//Rendering the walls:
g2.drawRect((int)(((i * 50) % WINDOWWIDTH) - XOffset), (int)(((i * 50) % WINDOWHEIGHT) - YOffset), 50, 50);
}
}
}
}
}
//used to add things to panels:
public void addItem(JPanel p, JComponent c, int x, int y, int width, int height,
int align /* Defines the spot on the coordinate */) {
GridBagConstraints gc = new GridBagConstraints();
gc.gridx = x;
gc.gridy = y;
gc.gridwidth = width;
gc.gridheight = height;
gc.insets = new Insets(10, 10, 10, 10);
switch (align) {
case 1:
gc.anchor = GridBagConstraints.NORTH;
break;
case 2:
gc.anchor = GridBagConstraints.EAST;
break;
case 3:
gc.anchor = GridBagConstraints.SOUTH;
break;
case 4:
gc.anchor = GridBagConstraints.WEST;
break;
case 5:
gc.anchor = GridBagConstraints.CENTER;
break;
}
p.add(c, gc);
}
}
`
這裏是Starthere類(類,它包含的主要方法):
package Code;
public class StartHere {
public static void main(String[] args) {
//Creating the frame:
final Window Frame = new Window();
}
}
這裏是地圖類存儲所有O F中的地圖數據:
package Code;
public class Map {
//the Array for all of the codes:
double Tiles[][];
int width;
int height;
//setters and getters for the width and height:
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
//the constructor for the double map:
public Map(long Width, long Height){
Tiles = new double[(int) Width][(int) Height];
}
//this is where the double array is going to be set:
public void setTile(int x, int y, double type){
Tiles[x][y] = type;
}
//this gets the given tile code:
public double getTile(int x, int y){
return Tiles[x][y];
}
}
最後,這裏是地圖加載器類,它負責從圖像文件加載地圖:
package Code;
import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class MapLoader {
BufferedImage MapImage;
public MapLoader(String MapPath){
//loading the map image from the specified map path:
try {
MapImage = ImageIO.read(new File(MapPath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Map ConvertMap(){
Map m = new Map(MapImage.getWidth(), MapImage.getHeight());
//now to read the individual pixels of the image and determine the code for the map object:
for(int i = 0; i < MapImage.getWidth(); i++){
for(int n = 0; n < MapImage.getHeight(); n++){
if (MapImage.getRGB(i, n) == Color.BLACK.getRGB()){
//Black = Wall = 1
m.setTile(i, n, 1);
System.out.print("1");
} else {
//else it is nothing so White = Space = 0
m.setTile(i, n, 0);
System.out.print("0");
}
}
System.out.println("");
}
return m;
}
}
謝謝你這麼多的人,幫助這有一直困擾着我好幾天,而且我沒有想法。
而且,這裏是我一直在使用一個例子文件: Example File
1)總是重寫paintComponent,而不是繪畫。任何體面的圖形教程都會告訴你這一點。 2)如果你重寫了,在你的覆蓋範圍內,總是調用super的繪畫方法'super.paintComponent(...)'。 3)以這樣的方式創建你的代碼,以便每個類都可以獨立測試和調試,使用小模擬類來幫助你做到這一點。 4)通過這種方式,如果遇到錯誤,您可以創建併發布您的[mcve]供我們測試,而不是要求我們瀏覽整個大型程序。 –
請注意,您從不**調用'DrawStartInterface(...)'!支持建議:請學習並遵循Java命名約定,因爲這樣做可以幫助他人更好地理解您的代碼。 –