我搜索了这个网站,找不到任何提出有关从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的视图。请注意,滑块和动画位于JPanel
提出的两个单独的
Hovercraft Full Of Eelss上:
/*
* 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());
}
}
}
}