簡體   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