[英]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 的宽度/高度来让球从它上面弹开?
完毕
我建议通过实现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.