Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 行isn';t被吸引到JPanel_Java_Multithreading_Swing_Paintcomponent - Fatal编程技术网

Java 行isn';t被吸引到JPanel

Java 行isn';t被吸引到JPanel,java,multithreading,swing,paintcomponent,Java,Multithreading,Swing,Paintcomponent,这是一个动画,在该动画中,给定数量的图标从帧的左侧开始,然后穿过屏幕跑到右侧。每个图标都被绘制到它自己的JPanel,该JPanel在容器的单列GridLayout中填充一行,并且每个JPanel在它自己的线程上运行。(必须使用线程,即使Swing计时器可能是更好的方法。) 一条终点线也应该画在集装箱上,但它没有出现。我已经尝试将赛车手的JPanel不透明度设置为false,但这不起作用。我怎样才能让其他线程允许完成线的绘制 不起作用的代码: gui = new JPanel() { @

这是一个动画,在该动画中,给定数量的图标从帧的左侧开始,然后穿过屏幕跑到右侧。每个图标都被绘制到它自己的JPanel,该JPanel在容器的单列GridLayout中填充一行,并且每个JPanel在它自己的线程上运行。(必须使用线程,即使Swing计时器可能是更好的方法。)

一条终点线也应该画在集装箱上,但它没有出现。我已经尝试将赛车手的JPanel不透明度设置为false,但这不起作用。我怎样才能让其他线程允许完成线的绘制

不起作用的代码:

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教程中的部分,了解一些基础知识。有几个关键点:

  • 您需要重写getPreferredSize()方法,使组件具有首选大小,以便布局管理器可以执行其工作。如果未指定首选尺寸,则尺寸可能为零,因此无需绘制

  • 绘画方法只适用于绘画。您永远不应该在绘制方法中修改组件的状态,因为您无法控制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);