如何修复paint组件而不是调用paintComponent?

时间:2017-04-04 23:21:16

标签: java swing

我查看了一些类似于我的其他问题,但是当我尝试修复它们时,它们似乎没有任何帮助,我将如何解决这个问题,因为它是阻止我的程序打印矩形的唯一因素,这是至关重要的。

以下是整个程序的代码,因为我不确定问题出在哪里,只有问题所在。评论的内容我目前没有使用,但是我将它保留在那里,以防我以后找到它的用途。非常感谢

目前,我的程序没有绘制任何类型的矩形,因为重绘不会调用paintcomponent。我的问题基本上是询问为什么在我开始时没有打印任何内容。

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.logging.Logger;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

/**
* Write a description of class Game here.
* 
* @author Adam Steele 
* @version 1.0.0
*/
public class Game extends JPanel implements MouseListener
{
// logger
private static final Logger LOGGER = Logger.getLogger(Game.class.getName());

// variables
private boolean isGolden; // Class wide boolean for whether rectangle is golden
private int score; // Stores the score
private int noOfAttempts; // stores number of rectangles that are created
private int goldTimer; // attempts before fail & new rectangle is created

// graphics
private Rectangle box;
private JFrame frame;
private JPanel panel;

// testing
private ArrayList<Rect> rects = new ArrayList<Rect>();


/**
 * Constructor for objects of class Game
 */
public Game()
{
    setup();
}

public void setup()
{
    LOGGER.info("setup has been called");

    // initalise frame
    frame = new JFrame();
    final int FRAME_WIDTH = 800;
    final int FRAME_HEIGHT = 600;

    // set frame attributes
    frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
    frame.setTitle("Gold Picker");

    // initalise panel
    panel = new JPanel();
    panel.addMouseListener(this);
    // add things to panel - ie. score, time limit, etc.
    // panel.add();

    JLabel amLabel = new JLabel("I am a GUI label.");
    panel.add(amLabel);
    JButton button = new JButton("Button");
    button.setBackground(Color.YELLOW);
    button.setForeground(Color.GREEN);
    panel.add(button);

    // add panel to frame
    frame.add(panel);

    // Make frame visible
    showFrame();

    LOGGER.info("Game window has been created");

    // (re)set variables
    score = 0;
    noOfAttempts = 0;
    goldTimer = 30;

    // this is to check variable initalisation
    LOGGER.info("Variables have been initalised at: score = " + score + ", noOfAttempts = " + noOfAttempts + ", goldTimer = " + goldTimer);  

    // start game
    decideGolden();
}

public void showFrame()
{
    frame.setVisible(true);
}

/**
 * A method that decides if the rectangle will be golden based on a random chance
 */
public void decideGolden()
{
    double goldProportion = Math.random() * 1;
    double goldChance = Math.random() * 1;
    //System.out.println(goldChance + " " + goldProportion);
    if(goldChance <= goldProportion) {
        isGolden = true;
    } else {
        isGolden = false;
    }

    LOGGER.info("isGolden has been set to " + isGolden);

    timedRect();
}

/**
 * Method for generating rectangled on timed intervals 
 */
public void timedRect()
{

    /*
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() 
        {

        }
    }, 20000, 20000 );
    /*
    if(isGolden) {
        repaint();
    } else {
        createNormalRectangle();
    }


    new java.util.Timer().schedule( 
    new java.util.TimerTask() {
        @Override
        public void run() {

        }
    }, 
    20000); */

    LOGGER.info("timedRect has been called");

    for(int i = 0; i < goldTimer; i++) {
        try {
            LOGGER.info("try has been reached");
            //repaint();
            drawRectangle();
            Thread.sleep(20000); // wait 20 seconds..
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

@Override
protected void paintComponent(Graphics g)
{
    super.paintComponent(g); 

    LOGGER.info("paintComponent has been called with " + g);
    /*
    int x = 400;
    int y = 300;
    // Using Math.random() or .nextInt() we could make random gold rects
    int width = 100;
    int height = 100; 

    LOGGER.info("x = " + x + ", y = " + y + ", width = " + width + ", height = " + height);

    if(isGolden) {
            //g.drawRect(x, y, width, height);
            g.setColor(Color.BLACK);
            g.fillRect(x, y, 100, 100); // g.fillRect(x, y, size, size);
    } else {
            //g.drawRect(x, y, width, height);
            g.setColor(Color.BLACK);
            g.fillRect(x, y, 100, 100);
    }
    */

    Graphics2D g2d = (Graphics2D) g;
    for(Rect rectangle : rects) { // for each Rect object in rect ArrayList .. 
        rectangle.paint(g2d);
    }

} 

/**
 * 
 */
public void drawRectangle()
{

    int x = (int) (Math.random() * getWidth());
    int y = (int) (Math.random() * getHeight());
    int width = (int) (Math.random() * (getWidth() / 4));
    int height = (int) (Math.random() * (getHeight() / 4));
   // LOGGER.info("x = " + x + ", y = " + y + ", width = " + width + ", height = " + height);




    if (x + width > getWidth()) {
        x = getWidth() - width;
    }

    if (y + height > getHeight()) {
        y = getHeight() - height;
    }

    Color color = new Color(
            (int) (Math.random() * 255),
            (int) (Math.random() * 255),
            (int) (Math.random() * 255));

    rects.add(new Rect(x, y, width, height, color));

   repaint();
   // LOGGER.info("repaint has been called, check if paintComponent has been called..");
} 

/** 
 * these methods are needed to override the MouseListener 
 * ..and hence needed to implement the MouseListener
 * ..which will probably only be used for testing
 * ..actionlistener maybe more appropriate
*/ 

@Override
public void mouseClicked(MouseEvent e) {
    LOGGER.info("Mouse has been clicked");

    drawRectangle();
}

public void mouseExited(MouseEvent e) {

}

public void mousePressed(MouseEvent e) {

}

public void mouseReleased(MouseEvent e) {

}

public void mouseEntered(MouseEvent e) {

}

}

Rect类,以防需要

Rect class
import java.awt.*;

/**
* Deaals with misc properties of rect
* Inherits the Rectangle class from java.awt.Rectangle
public class Rect extends Rectangle
{
private Color color;

 /**
 * Constructor for objects of class Rect
 */
public Rect(int x, int y, int width, int height, Color color)
{
    super(x, y, width, height);
    this.color = color;
}

public void paint(Graphics2D g2d) 
{
    g2d.setColor(color);
    g2d.fill(this);
}
}

2 个答案:

答案 0 :(得分:1)

基本上,您实际上从未将Game添加到可以显示它的任何内容上,因此它永远不会被绘制。

在绘制组件之前,必须将其添加到在屏幕上实现的容器中。

您遇到的问题之一是您的Game课程承担了很多责任,应该专注于展示和管理游戏状态,而不是创建基本用户界面。

您将遇到的另一个问题是timedRect方法会阻止EDT,阻止任何内容被绘制

这是一个基本的&#34;例如(我没有对其进行测试,因为我没有Rect课程),但从概念上讲,它应该让您更接近目标。

实际上,我有一个单独的&#34;主要&#34;启动应用程序的类,设置初始状态,创建UI并使球滚动。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import org.w3c.dom.css.Rect;

public class Game extends JPanel implements MouseListener {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                LOGGER.info("setup has been called");

                // initalise frame
                JFrame frame = new JFrame();
                final int FRAME_WIDTH = 800;
                final int FRAME_HEIGHT = 600;

                // set frame attributes
                frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
                frame.setTitle("Gold Picker");

                // initalise panel
                JPanel panel = new Game();
                // add things to panel - ie. score, time limit, etc.
                // panel.add();

                JLabel amLabel = new JLabel("I am a GUI label.");
                panel.add(amLabel);
                JButton button = new JButton("Button");
                button.setBackground(Color.YELLOW);
                button.setForeground(Color.GREEN);
                panel.add(button);

                // add panel to frame
                frame.add(panel);
                frame.setVisible(true);

                LOGGER.info("Game window has been created");
            }
        });
    }
// logger

    private static final Logger LOGGER = Logger.getLogger(Game.class.getName());

// variables
    private boolean isGolden; // Class wide boolean for whether rectangle is golden
    private int score; // Stores the score
    private int noOfAttempts; // stores number of rectangles that are created
    private int goldTimer; // attempts before fail & new rectangle is created

    private int gameLoops = 0;

// graphics
    private Rectangle box;

// testing
    private ArrayList<Rect> rects = new ArrayList<Rect>();

    /**
     * Constructor for objects of class Game
     */
    public Game() {
        addMouseListener(this);
        // (re)set variables
        score = 0;
        noOfAttempts = 0;
        goldTimer = 30;

        // this is to check variable initalisation
        LOGGER.info("Variables have been initalised at: score = " + score + ", noOfAttempts = " + noOfAttempts + ", goldTimer = " + goldTimer);

        decideGolden();
    }

    /**
     * A method that decides if the rectangle will be golden based on a random
     * chance
     */
    public void decideGolden() {
        double goldProportion = Math.random() * 1;
        double goldChance = Math.random() * 1;
        //System.out.println(goldChance + " " + goldProportion);
        if (goldChance <= goldProportion) {
            isGolden = true;
        } else {
            isGolden = false;
        }

        LOGGER.info("isGolden has been set to " + isGolden);

        timedRect();
    }

    /**
     * Method for generating rectangled on timed intervals
     */
    public void timedRect() {
        Timer timer = new Timer(2000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (gameLoops < goldTimer) {
                    LOGGER.info("try has been reached");
                    //repaint();
                    drawRectangle();
                    gameLoops++;
                } else {
                    ((Timer) (e.getSource())).stop();
                }
            }
        });
        timer.start();
        LOGGER.info("timedRect has been called");
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        LOGGER.info("paintComponent has been called with " + g);
        Graphics2D g2d = (Graphics2D) g;
        for (Rect rectangle : rects) { // for each Rect object in rect ArrayList .. 
            rectangle.paint(g2d);
        }

    }

    /**
     *
     */
    public void drawRectangle() {

        int x = (int) (Math.random() * getWidth());
        int y = (int) (Math.random() * getHeight());
        int width = (int) (Math.random() * (getWidth() / 4));
        int height = (int) (Math.random() * (getHeight() / 4));
        // LOGGER.info("x = " + x + ", y = " + y + ", width = " + width + ", height = " + height);

        if (x + width > getWidth()) {
            x = getWidth() - width;
        }

        if (y + height > getHeight()) {
            y = getHeight() - height;
        }

        Color color = new Color(
                (int) (Math.random() * 255),
                (int) (Math.random() * 255),
                (int) (Math.random() * 255));

        rects.add(new Rect(x, y, width, height, color));

        repaint();
        LOGGER.info("repaint has been called, check if paintComponent has been called..");
    }

    /**
     * these methods are needed to override the MouseListener ..and hence needed
     * to implement the MouseListener ..which will probably only be used for
     * testing ..actionlistener maybe more appropriate
     */
    @Override
    public void mouseClicked(MouseEvent e) {
        LOGGER.info("Mouse has been clicked");

        drawRectangle();
    }

    public void mouseExited(MouseEvent e) {

    }

    public void mousePressed(MouseEvent e) {

    }

    public void mouseReleased(MouseEvent e) {

    }

    public void mouseEntered(MouseEvent e) {

    }

    public class Rect extends Rectangle {

        private Color color;

        /**
         * Constructor for objects of class Rect
         */
        public Rect(int x, int y, int width, int height, Color color) {
            super(x, y, width, height);
            this.color = color;
        }

        public void paint(Graphics2D g2d) {
            g2d.setColor(color);
            g2d.fill(this);
        }
    }
}

答案 1 :(得分:0)

为什么在拥有JPanel实例时扩展JPanel?扩展类时,将继承其所有功能。 不要使用你的实例“panel.add”,而是摆脱你的JPanel实例并使用this.add。

这导致我的下一个声明: 你的类应该扩展JComponent,你没有覆盖paintcomponent,因为JPanel没有要覆盖的paintcomponent()方法。

了解如何正确实现JComponent和JFrame以及它们如何结合在一起。通常将所有绘图添加到JComponent,然后说frame.add(component),其中component是JComponent类型。

尝试以这种方式重新实现您的代码并分离您的课程,现在您不必遵循这种确切的格式,但是根据您发布的内容,我认为您已经迷失了。

  1. 实现一个扩展JFrame的类,这将是你的框架。
  2. 实现一个“知道”如何绘制矩形形状的类。您必须将它放在一个名为draw(Graphics2D g2){}。
  3. 的方法中
  4. 实现一个扩展JComponent的类,这个类可能有一个“矩形”对象的arraylist。

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        // initialize your rectangle objects here
        for(Rectangles rects: whateveryourarraylistvariable) {
            rects.draw(g2);
        }
    }
    
  5. 祝你好运