如何使球从JSlider弹回? (我已经弹起了)

时间:2019-02-19 03:06:34

标签: java swing animation jframe jslider

我已经搜索了该网站,找不到任何询问与从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的宽度/高度,使球弹起来呢?

2 个答案:

答案 0 :(得分:1)

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

完成

答案 1 :(得分:0)

我建议通过实现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());
            }
        }
    }
}

enter image description here