繁体   English   中英

如何让球从我的 JSlider 上“弹跳”? (我已经让它反弹了)

[英]How do I get the ball to "bounce" off of my JSlider? (I have already gotten it to bounce)

我搜索了这个网站,但找不到任何关于从 JSlider 上弹跳球的问题的帖子。 我修改了代码以使球从打开的窗口的侧面反弹并通过 JSlider 面板加速,但是球(圆圈)在 JSlider 面板后面下降。 当它在窗口周围弹跳时,它会穿过 JSlider,我希望球能够将 JSlider 视为窗口的底部。 下面显示的代码是我的构造函数。

import java.awt.*;
import java.awt.event.*;
import javax. swing. *;
import javax.swing.event.*;
public class SpeedControlPanel extends JPanel
{

  private final int WIDTH = 600;
  private final int HEIGHT = 400;
  private final int BALL_SIZE = 50;
  private Circle bouncingBall; // the object that moves
  private Timer timer;
  private int moveX, moveY; // increment to move each time
  private JPanel pSpeeder;
  private JSlider sSpeeder;
  private JLabel lSpeeder;
  Dimension height;
  // --------------------------------------------
  // Sets up the panel, including the timer
  // for the animation
  // --------------------------------------------


      public SpeedControlPanel ()
      {
        timer = new Timer(30, new ReboundListener());
        this.setLayout (new BorderLayout());
        bouncingBall = new Circle(BALL_SIZE);
        moveX = moveY = 5;
        // Set up a slider object here
        setPreferredSize (new Dimension (WIDTH, HEIGHT));
        setBackground(Color.black);
        lSpeeder = new JLabel("Timer Delay");
        lSpeeder.setAlignmentX(Component.LEFT_ALIGNMENT);

        sSpeeder = new JSlider(JSlider.HORIZONTAL, 0, 200, 30);
        sSpeeder.setMajorTickSpacing(40);
        sSpeeder.setMinorTickSpacing(10);
        sSpeeder.setPaintTicks(true);
        sSpeeder.setPaintLabels(true);
        sSpeeder.setAlignmentX(Component.LEFT_ALIGNMENT);

        sSpeeder.addChangeListener(new SlideListener());

        pSpeeder = new JPanel();
        pSpeeder.add(lSpeeder);
        pSpeeder.add(sSpeeder);

        add(pSpeeder, BorderLayout.SOUTH);
        timer.start();
      }

  // ---------------------
  // Draw the ball
  // ---------------------
      public void paintComponent (Graphics page)
      {
        super.paintComponent (page);
        bouncingBall.draw(page);
      }
  // ***************************************************
  // An action listener for the timer
  // ***************************************************
  public class ReboundListener implements ActionListener
  {
  // ----------------------------------------------------
  // actionPerformed is called by the timer -- it updates
  // the position of the bouncing ball
  // ----------------------------------------------------
      public void actionPerformed(ActionEvent action)
          {

          bouncingBall.move(moveX, moveY);
          // change direction if ball hits a side
          int x = bouncingBall.getX();
          int y = bouncingBall.getY();


          int slidePanelHt = pSpeeder.getSize().height; 

          if (x < 0 || x >= WIDTH - BALL_SIZE)
          moveX = moveX * -1;
          if (y <= 0 || y >= HEIGHT - BALL_SIZE)
          moveY = moveY * -1;
          repaint();
          }
  }
  // ***************************************************
  // A change listener for the slider.
  // ***************************************************
      private class SlideListener implements ChangeListener
          {
          // ------------------------------------------------
          // Called when the state of the slider has changed;
          // resets the delay on the timer.
          // ------------------------------------------------
              public void stateChanged (ChangeEvent event)
              {
                timer.setDelay(sSpeeder.getValue());
              }
          }
}

有没有办法修改 JSlider 的宽度/高度来让球从它上面弹开?

  1. 创建一个包含所有内容的包装器 JPanel,并给它一个 BorderLayout
  2. 将您的绘图/动画 JPanel 放入 BorderLayout.CENTER 位置的包装器中
  3. 将您的 JSlider 放入 BorderLayout.PAGE_END 位置的包装器 JPanel 中
  4. 将包装器添加到 GUI 而不是绘图/动画 JPanel

完毕

我建议通过实现MVC Pattern将 gui 与其控制分开。
拥有一个包含视图 (gui) 需要的所有信息的模型:

/*
 * The model contains the information for the view and information from the view
 * The model is independent of the user interface.
 */
class Model{

    private final int WIDTH = 600;
    private final int HEIGHT = 400;

    private int x,y, delay;
    private final int radius;

    Model(int radius) {
        this.radius = radius;
        x= radius;  y= radius; delay = 30; //default values
    }

    void move(int moveX, int moveY) {
        x += moveX; y+= moveY;
    }

    int getX() { return x;  }
    void setX(int x) { this.x = x; }

    int getY() {return y;}
    void setY(int y) { this.y = y; }

    int getRaduis() {return radius;}

    int getDelay() {return delay;}

    void setDelay(int delay) {this.delay = delay;}

    int getWidth() {return WIDTH;}

    int getHeiht() {return HEIGHT;  }
}

有一个使用模型显示 gui 的视图。 请注意,按照Hovercraft Full Of Eels 的建议,滑块和动画位于两个单独的JPanel

/*
 * View is just that: a dumb as possible display 
 */
class View extends JPanel {

    View(Model model) {
        setLayout (new BorderLayout());
        add(new BallPane(model));                          //as explained in Hovercraft Full Of Eels
        add(new SliderPane(model), BorderLayout.PAGE_END); //answer
    }

    class BallPane extends JPanel {

        private final Model model;

        BallPane(Model model) {
            this.model = model;
            setPreferredSize (new Dimension (model.getWidth(), model.getHeiht()));
            setBackground(Color.black);
        }

        // ---------------------
        // Draw the ball
        // ---------------------
        @Override
        public void paintComponent (Graphics page)  {
            super.paintComponent (page);
            page.setColor(Color.CYAN);
            page.fillOval(model.getX(), model.getY(), model.getRaduis()*2, model.getRaduis()*2);
        }
    }

    class SliderPane extends JPanel {

        private final Model model;
        private final JSlider sSpeeder;
        SliderPane(Model model) {
            this.model = model;
            sSpeeder = new JSlider(JSlider.HORIZONTAL, 0, 200, 30);
            sSpeeder.setMajorTickSpacing(40);
            sSpeeder.setMinorTickSpacing(10);
            sSpeeder.setPaintTicks(true);
            sSpeeder.setPaintLabels(true);
            sSpeeder.setAlignmentX(Component.LEFT_ALIGNMENT);
            sSpeeder.addChangeListener(new SlideListener());
            add(sSpeeder);
        }

        // ***************************************************
        // A change listener for the slider.
        // ***************************************************
        private class SlideListener implements ChangeListener
        {
            // ------------------------------------------------
            // Called when the state of the slider has changed;
            // resets the delay on the timer.
            // ------------------------------------------------
            @Override
            public void stateChanged (ChangeEvent event)
            {
                model.setDelay(sSpeeder.getValue());
            }
        }
    }
}

将它们放在一起:请参阅以下mvce :它添加了一个控制模型和视图的控制器。
为了方便和简单,可以将以下代码复制粘贴到一个名为BouncingBall.java文件中,然后运行。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;   
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/*
 * The controller wires the view and model, and does the processing.
 */
public class BouncingBall {

    private final int BALL_SIZE = 25;
    private int moveX =5, moveY =5; // increment to move each time
    private final Timer timer;
    private final Model model;
    private JPanel view;

    BouncingBall() {

        model = new Model(BALL_SIZE);
        timer = new Timer(model.getDelay(), new ReboundListener());
        makeAndShowGui();
        timer.start();
    }

    private void makeAndShowGui() {
        JFrame window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        view = new View(model);
        window.add(view);
        window.pack();
        window.setResizable(false);
        window.setVisible(true);
    }

    private void updateGui() {
        // change direction if ball hits a side
        int x = model.getX();
        int y = model.getY();

        if (x < 0 || x >= model.getWidth() - model.getRaduis()*2) {
            moveX = moveX * -1;
        }

        if (y <= 0 || y >= model.getHeiht() - model.getRaduis()*2) {
            moveY = moveY * -1;
        }

        model.setX(x+moveX);
        model.setY(y+moveY);
        timer.setDelay(model.getDelay()); //update timer
        view.repaint();
    }

    // ***************************************************
    // An action listener for the timer
    // ***************************************************
    public class ReboundListener implements ActionListener  {

        // ----------------------------------------------------
        // actionPerformed is called by the timer -- it updates
        // the position of the bouncing ball
        // ----------------------------------------------------
        @Override
        public void actionPerformed(ActionEvent action) {
            updateGui();
        }
    }

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

/*
 * The model contains the information for the view and information from the view
 * The model is independent of the user interface.
 */
class Model{

    private final int WIDTH = 600;
    private final int HEIGHT = 400;

    private int x,y, delay;
    private final int radius;

    Model(int radius) {
        this.radius = radius;
        x= radius;  y= radius; delay = 30; //default values
    }

    void move(int moveX, int moveY) {
        x += moveX; y+= moveY;
    }

    int getX() { return x;  }
    void setX(int x) { this.x = x; }

    int getY() {return y;}
    void setY(int y) { this.y = y; }

    int getRaduis() {return radius;}

    int getDelay() {return delay;}

    void setDelay(int delay) {this.delay = delay;}

    int getWidth() {return WIDTH;}

    int getHeiht() {return HEIGHT;  }
}

/*
 * View is just that: a dumb as possible display 
 */
class View extends JPanel {

    View(Model model) {
        setLayout (new BorderLayout());
        add(new BallPane(model));                          //as explained in Hovercraft Full Of Eels
        add(new SliderPane(model), BorderLayout.PAGE_END); //answer
    }

    class BallPane extends JPanel {

        private final Model model;

        BallPane(Model model) {
            this.model = model;
            setPreferredSize (new Dimension (model.getWidth(), model.getHeiht()));
            setBackground(Color.black);
        }

        // ---------------------
        // Draw the ball
        // ---------------------
        @Override
        public void paintComponent (Graphics page)  {
            super.paintComponent (page);
            page.setColor(Color.CYAN);
            page.fillOval(model.getX(), model.getY(), model.getRaduis()*2, model.getRaduis()*2);
        }
    }

    class SliderPane extends JPanel {

        private final Model model;
        private final JSlider sSpeeder;
        SliderPane(Model model) {
            this.model = model;
            sSpeeder = new JSlider(JSlider.HORIZONTAL, 0, 200, 30);
            sSpeeder.setMajorTickSpacing(40);
            sSpeeder.setMinorTickSpacing(10);
            sSpeeder.setPaintTicks(true);
            sSpeeder.setPaintLabels(true);
            sSpeeder.setAlignmentX(Component.LEFT_ALIGNMENT);
            sSpeeder.addChangeListener(new SlideListener());
            add(sSpeeder);
        }

        // ***************************************************
        // A change listener for the slider.
        // ***************************************************
        private class SlideListener implements ChangeListener
        {
            // ------------------------------------------------
            // Called when the state of the slider has changed;
            // resets the delay on the timer.
            // ------------------------------------------------
            @Override
            public void stateChanged (ChangeEvent event)
            {
                model.setDelay(sSpeeder.getValue());
            }
        }
    }
}

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM