PaintComponent未被称为Java

时间:2015-09-17 01:41:39

标签: java image swing jpanel paintcomponent

我的代码应该在随机位置绘制三次随机大小的图像。出于某种原因,当我使用BlueJ运行此代码时,显示的所有内容都是灰色屏幕。我认为这是因为没有调用PaintComponent,但我不太确定。我的代码出了什么问题,如何解决?

class PanelHolder extends JPanel{//class PanelHolder extends JPanel
//variables
public boolean threesharks;
public int xcoord;
public int ycoord;
public int ratio;
public Image i;
public int w;
public int h;
public boolean background=true;
Color water = new Color(136, 180, 231);


public PanelHolder(){//constructor

    i = Toolkit.getDefaultToolkit().getImage("$harkz.png");

}
public void randomxy(){
    for(int x=0;x<3;x++){
        threesharks=true;
        ycoord=(int)(Math.random()*300+200);//use math.random to figure out coordinates and sizing
        xcoord=(int)(Math.random()*1000+0);//make a loop
        ratio=(int)(Math.random()*5+1);
        w=ratio*523;
        h=ratio*195;
        repaint();
        System.out.println("I'm in randomxy");

        //call repaint() each time
        //after three times, make threesharks=false
    }
    threesharks=false;
}
public void paintComponent(Graphics g){
    if(threesharks){
        setBackground(water);
        System.out.print("hi!");
        if(background){
            super.paintComponent(g);//set backgroun
            background=false;
        }
        g.drawImage(i, xcoord, ycoord, w, h, this);
    }
    }

}

1 个答案:

答案 0 :(得分:1)

你似乎对Swing中的绘画效果有误解。 Swing会在你认为你的组件需要重新绘制的时候调用你的paintComponent,这可能由于许多不同的原因而发生,其中许多是你无法控制的。

Swing中的绘画是破坏性的,也就是说,每次调用paintComponent方法时,都需要从头开始重新绘制组件的整个状态,绘画不是很准确。

这意味着您需要以某种有意义的方式存储您想要绘制的事物的状态,并且需要重新使用这些值。

请查看Painting in AWT and SwingPerforming Custom Painting,了解有关绘画如何在Swing中工作的详细信息

Random Ponies

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new PanelHolder());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    class PanelHolder extends JPanel {//class PanelHolder extends JPanel
//variables

        public boolean threesharks;
        public BufferedImage i;
        public boolean background = true;
        Color water = new Color(136, 180, 231);

        private Point[] points;
        private Image[] images;

        public PanelHolder() {
            //constructor

            try {
                i = ImageIO.read(...);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            randomxy();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(800, 800);
        }

        public void randomxy() {
            points = new Point[3];
            images = new Image[3];
            for (int x = 0; x < 3; x++) {
                points[x] = new Point();

                double ratio = (Math.random() * 6d) + 0.1d;
                int width = (int) (ratio * i.getWidth());
                int height = (int) (ratio * i.getHeight());
                points[x].y = Math.max(0, (int) (Math.random() * 800) - height);//use math.random to figure out coordinates and sizing
                points[x].x = Math.max(0, (int) (Math.random() * 800) - width);//make a loop

                images[x] = i.getScaledInstance(width, height, Image.SCALE_SMOOTH);

            }
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);//set backgroun
            g.setColor(water);
            g.fillRect(0, 0, getWidth(), getHeight());
            if (points != null && images != null) {
                for (int index = 0; index < points.length; index++) {
                    g.drawImage(images[index], points[index].x, points[index].y, this);
                }
            }
        }
    }

}

这是一个粗略的例子,使用Image#getScaledInstance,这通常不推荐,但适用于该示例。

有关详细信息,请查看The Perils of Image.getScaledInstance()

查看Quality of Image after resize very low -- JavaJava: maintaining aspect ratio of JPanel background image可能的(缩放)替代方案

我还要查看Reading/Loading an Image以获得更好的加载图像的机制