Java 行isn';t被吸引到JPanel
这是一个动画,在该动画中,给定数量的图标从帧的左侧开始,然后穿过屏幕跑到右侧。每个图标都被绘制到它自己的JPanel,该JPanel在容器的单列GridLayout中填充一行,并且每个JPanel在它自己的线程上运行。(必须使用线程,即使Swing计时器可能是更好的方法。) 一条终点线也应该画在集装箱上,但它没有出现。我已经尝试将赛车手的JPanel不透明度设置为false,但这不起作用。我怎样才能让其他线程允许完成线的绘制 不起作用的代码:Java 行isn';t被吸引到JPanel,java,multithreading,swing,paintcomponent,Java,Multithreading,Swing,Paintcomponent,这是一个动画,在该动画中,给定数量的图标从帧的左侧开始,然后穿过屏幕跑到右侧。每个图标都被绘制到它自己的JPanel,该JPanel在容器的单列GridLayout中填充一行,并且每个JPanel在它自己的线程上运行。(必须使用线程,即使Swing计时器可能是更好的方法。) 一条终点线也应该画在集装箱上,但它没有出现。我已经尝试将赛车手的JPanel不透明度设置为false,但这不起作用。我怎样才能让其他线程允许完成线的绘制 不起作用的代码: gui = new JPanel() { @
gui = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(finishLineXPos, 0, finishLineXPos, windowHeight);
}
};
完整代码:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class Races2 {
private JFrame frame;
private JPanel gui; // to hold all components
private int finishLineXPos; // x-coordinate of finish line
private Icon racerImg;
private int racerImgWidth;
private int racerImgHeight;
private int numOfRacers;
private ArrayList<Racer> racers;
private Racer winner;
private int windowHeight;
private int windowWidth;
public Races(int num) {
numOfRacers = num;
racerImg = new ImageIcon("races.png");
racerImgWidth = racerImg.getIconWidth();
racerImgHeight = racerImg.getIconHeight();
windowHeight = racerImgHeight * numOfRacers;
windowWidth = racerImgWidth * 20;
finishLineXPos = racerImgWidth * 18; // two icon widths from the right
frame = new JFrame("Off to the Races - by Brienna Herold");
frame.setResizable(false); // prevents window resizing which affects painting
gui = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(finishLineXPos, 0, finishLineXPos, windowHeight);
}
};
gui.setLayout(new GridLayout(numOfRacers,1));
gui.setPreferredSize(new Dimension(windowWidth, windowHeight));
// Create and add racers to gui panel
racers = new ArrayList<Racer>();
for (int i = 0; i < numOfRacers; i++) {
Racer racer = new Racer();
gui.add(racer);
racers.add(racer);
}
// Start racers
for (Racer racer : racers) {
Thread racerThread = new Thread(racer);
racerThread.start();
}
frame.add(gui);
frame.pack();
frame.setVisible(true);
}
protected class Racer extends JPanel implements Runnable {
private int lastPosX;
private int posX;
public Racer() {
posX = 0;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
racerImg.paintIcon(this, g, posX, 0);
posX += Math.random() * 20;
}
@Override
public void run() {
// While the race has not been won yet, proceed with race
while (winner == null) {
repaint();
try {
Thread.sleep(100); // slows down racing a bit
} catch (InterruptedException ex) {
ex.printStackTrace();
}
// If racer passes specified x-coordinate, set it as winner
if (posX >= finishLineXPos) {
System.out.println("Winner: " + this.getName());
winner = this;
}
}
}
}
}
import javax.swing.*;
导入java.awt.*;
导入java.util.ArrayList;
公务舱比赛2{
私有JFrame;
私有JPanel gui;//保存所有组件
私有int finishLineXPos;//终点线的x坐标
私人图标赛车;
私人国际赛车场;
私人赛马场;
私人赛车手;
私人赛车手;
私人赛车冠军;
私家车高度;
私有窗口宽度;
公共竞赛(整数){
numoracers=num;
racerImg=新的图像图标(“races.png”);
racerImgWidth=racerImg.getIconWidth();
racerImgHeight=racerImg.getIconHeight();
窗高=车圈高度*车圈数;
窗宽=racerImgWidth*20;
finishLineXPos=racerImgWidth*18;//右起两个图标宽度
frame=新JFrame(“出发参加比赛-由Brienna Herold编写”);
frame.setresizeable(false);//防止影响绘制的窗口大小调整
gui=新的JPanel(){
@凌驾
公共组件(图形g){
超级组件(g);
g、 抽绳(finishLineXPos,0,finishLineXPos,窗高);
}
};
setLayout(新的GridLayout(numoracers,1));
setPreferredSize(新维度(窗口宽度、窗口高度));
//创建赛车手并将其添加到gui面板
racers=新ArrayList();
对于(int i=0;i=finishLineXPos){
System.out.println(“获胜者:+this.getName());
赢家=这个;
}
}
}
}
}
每个图标都被绘制到自己的JPanel,该JPanel在容器的单列GridLayout中填充一行
首先,你需要学习如何做定制绘画。首先阅读Swing教程中的部分,了解一些基础知识。有几个关键点:
setPositionX(…)
的方法来控制应该绘制图像的位置。然后在线程(或计时器)中调用此方法来更改位置,并在组件上调用repaint()racer.setOpaque(false)
的方法
另一种方法是重写paint()方法。(这是在paintComponent()方法中进行自定义绘制的一般规则的一个例外)。如果您阅读了我提供的教程链接,您将看到使用此方法将导致在所有赛车部件喷漆后完成赛车面板的喷漆
frame.setResizable(false); // prevents window resizing which affects painting
这是没有必要的。影响绘制的唯一原因是您正在绘制方法中更改零部件的状态。见我上面的评论
racerImg.paintIcon(this, g, posX, 0);
人们通常使用drawImage(…)方法来绘制图像。没有理由仅仅为了绘制图像而创建图标
racerImg = new ImageIcon("races.png");
不要使用图像图标读取文件。使用ImageIO.read(…)读取图像。然后,只需按上述方式绘制图像
每个JPanel都在自己的线程上运行
这似乎是一个愚蠢的要求,因为它给比赛带来了一种不同的随机性。您已经有了为图像移动生成随机距离的逻辑,那么为什么需要单独的线程呢。相反,您应该只有一个线程,然后遍历
posX = 0;
setOpaque(false);