我的代码应该在随机位置绘制三次随机大小的图像。出于某种原因,当我使用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);
}
}
}
答案 0 :(得分:1)
你似乎对Swing中的绘画效果有误解。 Swing会在你认为你的组件需要重新绘制的时候调用你的paintComponent
,这可能由于许多不同的原因而发生,其中许多是你无法控制的。
Swing中的绘画是破坏性的,也就是说,每次调用paintComponent
方法时,都需要从头开始重新绘制组件的整个状态,绘画不是很准确。
这意味着您需要以某种有意义的方式存储您想要绘制的事物的状态,并且需要重新使用这些值。
请查看Painting in AWT and Swing和Performing Custom Painting,了解有关绘画如何在Swing中工作的详细信息
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 -- Java和Java: maintaining aspect ratio of JPanel background image可能的(缩放)替代方案
我还要查看Reading/Loading an Image以获得更好的加载图像的机制