在正在运行的线程中更改弹跳球的颜色

时间:2014-04-23 14:17:09

标签: java swing colors

我是Java新手。我开始通过创建一个弹跳球GUI来学习。

除了一件事,我已经设法做了我想做的一切。每当它从框架边框反弹时,我都无法改变它的颜色。

我知道我不能使用getGraphics进行绘图,但在这种情况下我也不能使用绘制方法,因为我已经将它用于本程序开头的初始设置。如果我从循环中调用paint方法,它确实会改变颜色,但布局北侧的所有JButton都会神秘地消失。

使整个事情变得更加复杂的一件事就是我在Runnable Interface的void run方法中循环球的事实。

我无法弄清楚如何解决它。

你们可以在IDE中复制我的代码。一件不起作用的事情是球保持黑色并且不会改变它的颜色。其他一切都运行正常。

所以请帮我弄清楚如何在球弹跳时改变球的颜色。

由于

代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Ball extends JFrame implements Runnable, ActionListener {

    private JButton start;
    private JButton stop;
    private JButton fast;
    private JButton slow;
    private JButton reset;
    private int ball_x;
    private int ball_y;
    private int dx = 10;
    private int dy = 20;
    private int size = 50;
    private boolean active;
    private int i = 20;
    private int R = 255;
    private int G = 0;
    private int B = 255;
    private Color rgb;


    private MyPanel screen;

    private class MyPanel extends JPanel {
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            ball_x = screen.getWidth() / 2 - 25;
            ball_y = screen.getHeight() / 2 - 25;
            i = 20;
            g.setColor(rgb);
            g.fillOval(ball_x, ball_y, size, size);
        }

        public void clr() {

            if (R <= 10) {
                R = 255;
            }
            R = R - 10;


            if (G >= 255) {
                G = 0;
            }

            G = G + 15;


            if (B <= 20) {
                B = 255;
            }

            B = B - 20;

        }
    }


    public void start() {
        active = true;
        start.setText("Start");
        start.setEnabled(false);
        start.setText("Jumping...");
        Thread th = new Thread(this); // Thread anlegen
        th.start(); // Thread starten
    }

    public void stop() {
        if (active) {
            start.setText("Continue");
        }
        active = false;
        start.setEnabled(true);
    }

    public void reset() {
        active = false;
        size = 50;
        screen.repaint();
        start.setText("Start");
        start.setEnabled(true);
    }

    public void slow() {
        i = i + 2;
        if (i >= 60) {
            i = 60;
        }
    }

    public void fast() {
        i = i - 2;
        if (i <= 5) {
            i = 5;
        }
    }

    public void actionPerformed(ActionEvent ereignis) {

        if (ereignis.getSource() == start) {
            start();
        }

        if (ereignis.getActionCommand() == "G+") {
            fast();
        }

        if (ereignis.getActionCommand() == "G-") {
            slow();
        }

        if (ereignis.getActionCommand() == "Reset") {
            reset();
        }

        if (ereignis.getActionCommand() == "Pause") {
            stop();
        }

    }

    public Ball() {

        this.setTitle("Jumping Ball \u00a9 The One");
        Container panel = new Container();
        panel.setLayout(new BorderLayout());
        JPanel subpanel = new JPanel();
        //subpanel.setLayout(new GridLayout());
        screen = new MyPanel();
        this.setVisible(true);
        this.setSize(1366, 768);
        this.setContentPane(panel);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        start = new JButton("Start");
        fast = new JButton("G+");
        slow = new JButton("G-");
        reset = new JButton("Reset");
        stop = new JButton("Pause");
        subpanel.add(start);
        subpanel.add(fast);
        subpanel.add(slow);
        subpanel.add(reset);
        subpanel.add(stop);
        panel.add(subpanel, "North");
        panel.add(screen, "Center");
        start.addActionListener(this);
        stop.addActionListener(this);
        reset.addActionListener(this);
        slow.addActionListener(this);
        fast.addActionListener(this);

    }

    public void run() {

        while (active) {
            screen.getGraphics().clearRect(ball_x, ball_y, size, size);

            if (ball_x > (screen.getWidth() - 30) || ball_x < 25) {
                dx = -dx;
                size = size + 3;
                screen.clr();

            }

            if (ball_y > (screen.getHeight() - 30) || ball_y < 25) {
                dy = -dy;
                size = size + 3;
                screen.clr();

            }

            ball_x = ball_x + dx;
            ball_y = ball_y + dy;

            rgb = new Color(R, G, B);

            screen.getGraphics().setColor(rgb);
            screen.getGraphics().fillOval(ball_x, ball_y, size, size);
            try {
                Thread.sleep(i);
            } catch (InterruptedException x) {
                x.printStackTrace();
            }
        }

    }


    public static void main(String[] args) {
        Ball bouncer = new Ball();

    } // End of Method Main


}

谢谢

2 个答案:

答案 0 :(得分:3)

完成后,您的示例有几个关键问题:

  • 错误synchronized

  • 过早地调用setVisible()

  • 它依赖于框架的几何体,而不是封闭的面板。

相反,请使用Swing here从引用Timer的示例开始。请注意,每个repaint()的颜色会发生变化,每次弹跳都会播放声音。添加成员变量bounced

private boolean bounced;

当球反弹时,请在bounced = true的{​​{1}}方法中设置actionPerformed()

Timer

if (ballX - RADIUS < 0) { … bounced = true; } else if (ballX + RADIUS > BOX_WIDTH) { … bounced = true; } 中,相应地更改颜色。

paintComponent()

使用较小的g.setColor(clut.peek()); if (bounced) { clut.add(clut.remove()); bounced = false; } 可能更容易看到更改。

clut

答案 1 :(得分:1)

嗯,我得到了它的工作,但我不认为这是最好的方法!我不得不放弃Threads并选择Timer。

我到处都在阅读一个不应该混合AWT和Swing但我没有看到除panel.setLayout(new BorderLayout());public void paintComponent(Graphics g)

之外的任何其他可能性

这显然混合了AWT和Swing Components,但我没有找到任何纯粹的Swing方法。

无论如何这是我的整个代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Ball extends JFrame implements ActionListener {

    private JButton start;
    private JButton stop;
    private JButton fast;
    private JButton slow;
    private JButton reset;
    private int ball_x;
    private int ball_y;
    private int dx = 10;
    private int dy = 20;
    private boolean active;
    private int i = 30;
    private int R = 255;
    private int G = 255;
    private int B = 0;
    private Color rgb;
    private Timer trigger = new Timer(i, this);

    private MyPanel screen;

    private class MyPanel extends JPanel {

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (start.getText() == "Start") {
                ball_x = screen.getWidth() / 2 - 50;
                ball_y = screen.getHeight() / 2 - 50;
            }

            if (start.getText() == "Jumping...") {
                g.clearRect(ball_x, ball_y, 100, 100);
            }

            ball_x = ball_x + dx;
            ball_y = ball_y + dy;

            rgb = new Color(R, G, B);
            g.setColor(rgb);

            g.fillOval(ball_x, ball_y, 100, 100);

            if (ball_x > (screen.getWidth() - 100) || ball_x < 10) {
                dx = -dx;
                screen.clr();
            }

            if (ball_y > (screen.getHeight() - 100) || ball_y < 10) {
                dy = -dy;
                screen.clr();
            }

        }

        public void clr() {

            if (R <= 10) {
                R = 255;
            }
            R = R - 10;

            if (G <= 20) {
                G = 255;
            }

            G = G - 20;

            if (B >= 255) {
                B = 0;

            }

            B = B + 15;

        }
    }

    public void start() {

        active = true;
        start.setText("Start");
        start.setEnabled(false);
        start.setText("Jumping...");
        trigger.start();
        screen.repaint();

    }

    public void stop() {
        if (active) {
            start.setText("Continue");
        }
        active = false;
        start.setEnabled(true);
        trigger.stop();

    }

    public void reset() {
        active = false;
        start.setText("Start");
        start.setEnabled(true);
        i = 100;
        trigger.stop();
        screen.repaint();
    }

    public void slow() {
        i = i + 10;
        if (i >= 100) {
            i = 100;
        }

        trigger.setDelay(i);
    }

    public void fast() {
        i = i - 10;
        if (i <= 10) {
            i = 10;
        }
        trigger.setDelay(i);
    }

    public void actionPerformed(ActionEvent ereignis) {

        if ((ereignis.getSource() == start) || (trigger.isRunning() == true)) {
            start();
        }

        if (ereignis.getActionCommand() == "G+") {
            fast();
        }

        if (ereignis.getActionCommand() == "G-") {
            slow();
        }

        if (ereignis.getActionCommand() == "Reset") {
            reset();
        }

        if (ereignis.getActionCommand() == "Pause") {
            stop();
        }

    }

    public Ball() {

        this.setTitle("Jumping Ball \u00a9 The One");
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        this.setContentPane(panel);
        JPanel subpanel = new JPanel();
        panel.add(subpanel, "North");
        screen = new MyPanel();
        screen.setBackground(Color.WHITE);
        panel.add(screen, "Center");
        start = new JButton("Start");
        fast = new JButton("G+");
        slow = new JButton("G-");
        reset = new JButton("Reset");
        stop = new JButton("Pause");
        subpanel.add(start);
        subpanel.add(fast);
        subpanel.add(slow);
        subpanel.add(reset);
        subpanel.add(stop);
        start.addActionListener(this);
        stop.addActionListener(this);
        reset.addActionListener(this);
        slow.addActionListener(this);
        fast.addActionListener(this);
        this.setSize(1280, 720);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        Ball fenster = new Ball();

    } // Ende der Methode Main
}

我知道这不是专业的做法,但这是我能做的最好的事情,而且它做了我想做的事。

如果有人能在我的代码中指出一些绝对的禁忌,我会非常高兴。

感谢名单