I'm trying to mimic a ScrollPane by simply inheriting from a Panel which itself moves its child around.
Should be a simple task but the child doesn't get clipped properly, meaning if I scroll around using setScrollPosition(Point) the content is visible although its outside the parent Panel.
public class ScrollFrame
extends Container
{
public ScrollFrame() {
setLayout(null);
}
public void paint(Graphics g) {
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
super.paint(g);
}
public void setScrollPosition(Point p) {
setScrollPosition(p.x, p.y);
}
public void setScrollPosition(int x, int y) {
synchronized (getTreeLock()) {
Component component = getComponent(0);
int viewPortWidth = getWidth(),
viewPortHeight = getHeight(),
componentWidth = component.getWidth(),
componentHeight = component.getHeight(),
componentX = component.getX(),
componentY = component.getY();
if (x < 0) {
x = 0;
} else if (x > 0 && x + viewPortWidth > componentWidth) {
x = componentWidth - viewPortWidth;
if (x < 0)
x = 0;
}
if (y < 0) {
y = 0;
} else if (y > 0 && y + viewPortHeight > componentHeight) {
y = componentHeight - viewPortHeight;
if (y < 0)
y = 0;
}
component.setLocation(x * -1, y * -1);
validate();
}
}
public Point getScrollPosition() {
synchronized (getTreeLock()) {
Point p = getComponent(0).getLocation();
p.x *= -1;
p.y *= -1;
return p;
}
}
}
Problem: The child component added to the ScrollFrame is visible outside the boundaries of the ScrollFrame.
And finally a SSCCE for some C&P testing, just click into the red area and move the mouse up and down:
import java.awt.*;
import java.awt.event.*;
public class TestScrollPane extends Frame implements MouseListener,
MouseMotionListener
{
/* starting point */
public static void main(String[] args)
{
TestScrollPane window = new TestScrollPane();
window.setSize(800, 480);
window.setVisible(true);
}
/*
* a translucent element to be placed above all other components to receive
* the MouseEvents
*/
public class GlassPane extends Component
{
public void paint(Graphics g)
{
g.setColor(Color.RED);
g.fillRect(0, 0, getWidth(), getHeight());
super.paint(g);
}
}
public class ScrollContainer extends Container
{
public ScrollContainer()
{
setLayout(null);
}
public void paint(Graphics g)
{
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
super.paint(g);
}
public void printComponents(Graphics g)
{
Component c = getComponent(0);
Point p = c.getLocation();
Graphics cg = g.create();
try {
cg.clipRect(0, 0, getWidth(), getHeight());
cg.translate(p.x * -1, p.y * -1);
c.paintAll(cg);
} finally {
cg.dispose();
}
}
public void setScrollPosition(Point p)
{
setScrollPosition(p.x, p.y);
}
public void setScrollPosition(int x, int y)
{
synchronized (getTreeLock()) {
Component component = getComponent(0);
int viewPortWidth = getWidth(), viewPortHeight = getHeight(), componentWidth = component
.getWidth(), componentHeight = component.getHeight(), componentX = component
.getX(), componentY = component.getY();
if (x < 0) {
x = 0;
} else if (x > 0 && x + viewPortWidth > componentWidth) {
x = componentWidth - viewPortWidth;
if (x < 0)
x = 0;
}
if (y < 0) {
y = 0;
} else if (y > 0 && y + viewPortHeight > componentHeight) {
y = componentHeight - viewPortHeight;
if (y < 0)
y = 0;
}
component.setLocation(x * -1, y * -1);
}
}
public Point getScrollPosition()
{
synchronized (getTreeLock()) {
Point p = getComponent(0).getLocation();
p.x *= -1;
p.y *= -1;
return p;
}
}
}
private ScrollContainer scrollPane;
private Panel scrollPaneContainer;
private GlassPane glassPane;
private boolean scrolling = false;
private Point scrollingStartMouse;
private Point scrollingStartPane;
public TestScrollPane()
{
/* simple test window */
super("TestScrollPane");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e)
{
e.getWindow().dispose();
System.exit(0);
}
});
setLayout(null);
/*
* the ScrollPane provides the ability to show only a limited of a much
* larger child element. Note that the ScrollPane is a container for
* only ONE element, but the child element may act as a container, e.g.
* a Panel
*/
scrollPane = new ScrollContainer();
scrollPane.addMouseListener(this);
scrollPane.setBounds(30, 50, 300, 300);
/*
* the element we place in the scrollpane, a panel with null layout to
* place the children
*/
scrollPaneContainer = new Panel();
scrollPaneContainer.setLayout(null);
/* add some random buttons for testing purposes */
for (int i = 0; i < 30; ++i) {
Button button = new Button("Click Me " + i);
button.addMouseListener(this);
button.setBounds(0, 40 * i, 100, 30);
scrollPaneContainer.add(button);
}
/*
* a translucent component on top of all elements placed inside the
* scrollPaneContainer to receive the MouseEvent's and properly scroll
* the ScrollPane or propagate the event
*/
glassPane = new GlassPane();
glassPane.setBounds(0, 0, 1, 1);
glassPane.addMouseListener(this);
glassPane.addMouseMotionListener(this);
/*
* we do need to add the GlassPane first to place it above all other
* elements
*/
// scrollPaneContainer.add(glassPane);
/*
* the GlassPane and the scrollPaneContainer need to have the same size.
* you have to set a size on the scrollPaneContainer else there won't be
* any scrolling ;)
*/
scrollPaneContainer.setSize(100, 1190);
scrollPaneContainer.setPreferredSize(new Dimension(100, 1190));
/* place the scrollPaneContainer (Panel) inside the ScrollPane */
scrollPane.add(scrollPaneContainer);
scrollPane.setBounds(30, 30, 150, 300);
glassPane.setBounds(30, 30, 30, 300);
Panel all = new Panel();
all.setLayout(null);
all.setBounds(30, 30, 400, 400);
all.add(glassPane);
all.add(scrollPane);
add(all);
}
/* MouseListener implementation */
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
if (e.getSource().equals(glassPane)) {
scrolling = false;
}
}
public void mousePressed(MouseEvent e)
{
if (e.getSource().equals(glassPane)) {
scrolling = true;
scrollingStartMouse = e.getPoint();
scrollingStartPane = scrollPane.getScrollPosition();
}
}
/* MouseMotionListener implementation */
public void mouseDragged(MouseEvent e)
{
if (scrolling) {
Point currentPos = e.getPoint();
int mouseDeltaX = currentPos.x - scrollingStartMouse.x;
int mouseDeltaY = currentPos.y - scrollingStartMouse.y;
scrollPane.setScrollPosition(scrollingStartPane.x - mouseDeltaX,
scrollingStartPane.y - mouseDeltaY);
}
}
public void mouseMoved(MouseEvent e)
{
}
void log(String message)
{
System.out.println(message);
}
void log(String message, MouseEvent e)
{
log(e.getComponent().getClass().getName() + ": " + message);
}
}
Related
I have obtained from somewhere else a Java Swing code for a bouncing Ball. The code uses a class "Ball" which extends a JPanel.
Can Anyone help me converting this code to extends JFrame instead.
I want to do that so I could be able to call it from another frame class.
Here is the code:
public class Ball extends JPanel{
int x=0, y=0;
int angleX = 1, angleY = 1;
public void move(){
if (x + angleX <0) {
angleX =1;
} else if (x + angleX >getWidth()-50){
angleX =-1;
} else if (y + angleY <0) {
angleY =1;
} else if (y + angleY >getHeight()-50){
angleY =-1;
}
x = x + angleX;
y = y + angleY;
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.fillOval(x, y, 50, 50);
}
public static void main(String[] args){
JFrame jfrm= new JFrame("BounceBall");
jfrm.setSize(400,400);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfrm.setVisible(true);
Ball bl = new Ball();
Component add = jfrm.add(bl);
while (true){
bl.move();
bl.repaint();
try{
Thread.sleep(10);
}catch(InterruptedException e){
}
}
}
}
Just extend JFrame and make some constructor for Ball class.
You can make an instance from Ball class from any other JFrame classes.
Ball bl = new Ball();/*then call methods*/
Or just call Balls main method in two ways:
Ball.main(null);
String args[]={/*some arguments*/}; Ball.main(args);
Here is your Ball class which now extends JFrame
import java.awt.Graphics;
import javax.swing.JFrame;
public class Ball extends JFrame {
public Ball() {
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
int x = 0, y = 0;
int angleX = 1, angleY = 1;
public void move() {
if (x + angleX < 0) {
angleX = 1;
} else if (x + angleX > getWidth() - 50) {
angleX = -1;
} else if (y + angleY < 0) {
angleY = 1;
} else if (y + angleY > getHeight() - 50) {
angleY = -1;
}
x = x + angleX;
y = y + angleY;
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.fillOval(x, y, 50, 50);
}
public static void main(String[] args) {
Ball bl = new Ball();
while (true) {
bl.move();
bl.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}
I have this game/test class of an flappy bird example, and i have a Login Screen, upon clicking a JButton "loggin" in this screen class i would like to call the flappyBird class Below.
I have Tried something like this but with no luck
if(event == jButtonLogin){
this.dispose();
FlappyBird bird = new FlappyBird();
bird.setVisible();
//since it has Jframe in it i though this logic would work.
IF someone can point me the right way please
public class FlappyBird implements ActionListener, MouseListener, KeyListener {
//private static final long serialVersionUID = 1L;
public static FlappyBird flappyBird; //creating a static flappybird so it can be acessed within main
public final int WIDTH = 800, HEIGHT = 600; //scren size of the game
public int highScore = 0;
public Renderer renderer;
public Random rand;
public Rectangle bird;
public int ticks, yMotion, score; //bird movement
public boolean gameOver, started;
public ArrayList<Rectangle> columns; //arrrayList of Recatangles names column
public FlappyBird()
{
JFrame jframe = new JFrame(); //main frame of game
Timer timer = new Timer(20,this);
renderer = new Renderer();
rand = new Random();
jframe.setSize(WIDTH, HEIGHT);
jframe.setLocationRelativeTo(null);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// jframe.setResizable(false);
jframe.setVisible(true);
jframe.addMouseListener(this);
jframe.addKeyListener(this);
jframe.setTitle("FlappyTest");
jframe.add(renderer); //need to create what were rendering
bird = new Rectangle(50 - 10,HEIGHT/2 - 10,20,20);
columns = new ArrayList<Rectangle>();
addColumn(true);
addColumn(true);
addColumn(true);
addColumn(true);
timer.start();
}
public void addColumn(boolean start){
int space = 350;
int width = 100;
int height = 50 + rand.nextInt(300); // height of column //minum = 50 // and talles being random at 300
if (start) //if first pipes
{
columns.add(new Rectangle(WIDTH + width + columns.size() * 200, HEIGHT - height - 100, width, height)); //top pipe
columns.add(new Rectangle(WIDTH + width + (columns.size() - 1) * 200, 0, width, HEIGHT - height - space)); // bot pipe
}
else
{
columns.add(new Rectangle(columns.get(columns.size() - 1).x + 300, HEIGHT - height - 100, width, height)); //top pipe
columns.add(new Rectangle(columns.get(columns.size() - 1).x, 0, width, HEIGHT - height - space)); //bot pipe
}
}
public void paintColumn(Graphics g, Rectangle column) //passing theses two vriable on the method
{
g.setColor(Color.green); //darker()
g.fillRect(column.x, column.y, column.width, column.height);
}
public void jump()
{
if(gameOver)
{
bird = new Rectangle(50 - 10,HEIGHT/2 - 10,20,20);
columns.clear();
yMotion = 0;
score = 0;
addColumn(true);
addColumn(true);
addColumn(true);
addColumn(true);
gameOver = false;
}
if(!started)
{
started = true;
}
else if(!gameOver)
{
if (yMotion > 0)
{
yMotion = 0;
}
yMotion -=15;
}
}
public void actionPerformed(ActionEvent arg0) //action being performed on the timer (20,THIS)
{
int speed = 10; //columns speed
ticks++; //keeping count of each tick of the bird
if(started)
{
for(int i = 0;i < columns.size(); i++)
{
Rectangle column = columns.get(i);
column.x -= speed;
}
if(ticks % 2 == 0 && yMotion < 15)
{
yMotion += 2;
}
for(int i = 0;i < columns.size(); i++) // for the whole columns ArrayList
{
Rectangle column = columns.get(i); // grab column at whichever i postion
if(column.x + column.y < 0) // column x.y less than 0
{
columns.remove(column); //remove that current column
if(column.y == 0) //if the column.y == 0 when it turns 0 and you have no more starting columns
{
addColumn(false); // you add the other columns false // infinite loop
}
}
}
bird.y += yMotion;
for(Rectangle column : columns)
{ // FOR EACH RECTANGLE column IN COLUMNS
if(column.y == 0 && bird.x + bird.width / 2 > column.x + column.width / 2 - 10 && bird.x + bird.width / 2 < column.x + column.width / 2 + 10)
{
score++;
}
if(column.intersects(bird))
{ //colision detection with pipes
gameOver = true;
if(bird.x < column.x)
{
bird.x = column.x - bird.width;
}
else
{
if(column.y != 0){ //if its not the top column
bird.y = column.y - bird.height;
}
else if(bird.y < column.height)
{
bird.y = column.height;
}
}
}
}
if(bird.y > HEIGHT - 100) // if the Y becomes greater then the ground or if its less than 0
{
gameOver = true;
}
if(bird.y + yMotion >= HEIGHT - 120)
bird.y = HEIGHT - 100 - bird.height;
}
renderer.repaint(); //EVERY 20 WE CALL REPAINT USING THE RENDERER TO UPDATE IT+
}
public void repaint(Graphics g) //MAIN SCREEN REPAINT
{
//System.out.println("Teste");
System.out.println(bird.y);
g.setColor(Color.BLACK); //bground of the screen
g.fillRect(0,0,WIDTH,HEIGHT);
g.setColor(Color.BLUE); //blue line
g.drawLine(0, HEIGHT-100, WIDTH, HEIGHT-100);
g.setColor(Color.WHITE); //White Screen
g.fillRect(0,HEIGHT-98,WIDTH, HEIGHT-100);
g.setColor(Color.WHITE); //adding bird component
g.fillRect(bird.x,bird.y,bird.width,bird.height);
for (Rectangle column : columns)
{
paintColumn(g, column);
}
g.setColor(Color.RED);
g.setFont(new Font("Arial",1,100));
if(!started)
{
g.drawString("Click to Start!", 75, HEIGHT / 2 - 50);
}
if(gameOver)
{
g.drawString("GAME OVER!", 75, HEIGHT / 2 - 50);
if(score > highScore){
highScore = score;
}
}
if(!gameOver && started)
{
g.drawString(String.valueOf(score),WIDTH/2-25, 100);
}
g.setColor(Color.WHITE);
g.setFont(new Font("Arial",1,20));
g.drawString("High Score : " + highScore, 10, 50);
}
public static void main(String[] args)
{
flappyBird = new FlappyBird(); // creating a new instance of flappybird
}
#Override
public void mouseClicked(MouseEvent arg0)
{
jump();
}
#Override
public void mouseEntered(MouseEvent arg0)
{
}
#Override
public void mouseExited(MouseEvent arg0)
{
}
#Override
public void mousePressed(MouseEvent arg0)
{
}
#Override
public void mouseReleased(MouseEvent arg0)
{
}
#Override
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_SPACE)
{
jump();
}
}
#Override
public void keyReleased(KeyEvent arg0)
{
}
#Override
public void keyTyped(KeyEvent arg0)
{
}
}
Consider looking into layout managers to achieve the behavior of a state-based game.
Ex: In your main method, rather than calling new FlappyBird() you would instead call something like new Login().
Be careful in the creation of the Login object - you don't want to necessarily reinvent the wheel by "opening" and creating a second JFrame (an undesirable band-aid solution can be done by hiding JFrames but that isn't what you want).
Instead, as MadProgrammer hinted at - Layout managers can instantly allow your application swap environments. Some retooling is in order to accomplish this design, but overall it is more modular, scalable (if you want to include an options page), and more OOP-oriented.
Ultimately, from the Login object, the user will be able to click a button that swaps the Layout to the Play Layout (which is where all of your FlappyBird stuff is).
Recently I have been building an application that draws images on a JFrame, everything is great, but when the window goes off screen, the images that have been drawn have disappeared, and I have been wondering if there is a way to avoid that? Thanks
import javax.swing.*;
import java.awt.;
import java.awt.event.;
public class Pokemoneur extends JFrame implements AdjustmentListener,
ActionListener, MouseListener, Runnable {
private JButton a = new JButton("Reset");
private int nbi = 7;
private JPanel frame;
private int n;
private int x2, y2;
private static int temp2;
private Object src;
private Thread t;
private JButton[] v = new JButton[nbi];
private ImageIcon[] imagei = new ImageIcon[7];
private JPanel canevas = new JPanel();
private JTextField nombre = new JTextField(7);
private JScrollBar js = new JScrollBar(0, 0, 0, 0, 100);
private JPanel panboutton = new JPanel(new GridLayout(1, 8));
private JPanel panjs = new JPanel(new BorderLayout(5, 5));
private JPanel frame2 = new JPanel(new GridLayout(2, 1, 5, 5));
private Graphics g;
public Pokemoneur() {
startGUI();
list();
this.setVisible(true);
}
public void startGUI() {
int max = 1000;
frame = (JPanel) this.getContentPane();
for (int i = 0; i < imagei.length; i++) {
}
frame.add(canevas);
frame.add(frame2, "North");
frame2.add(panboutton);
frame2.add(panjs);
js.setValue(6);
nombre.setText("" + js.getValue());
for (int i = 0; i < nbi; i++) {
imagei[i] = new ImageIcon(getClass()
.getResource("pok" + i + ".png"));
v[i] = new JButton(imagei[i]);
panboutton.add(v[i]);
}
panjs.add(js);
js.setMaximum(max);
panjs.add(nombre, "East");
frame.setPreferredSize(new Dimension(500, 500));
frame.setBorder(BorderFactory.createTitledBorder("Marc André 2014"));
panjs.setBorder(BorderFactory.createTitledBorder("Numbers of Pokemons"));
canevas.setBorder(BorderFactory.createTitledBorder("Party"));
frame.add(a, "South");
g = canevas.getGraphics();
this.pack();
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void run() {
for (int i = 0; i < v.length; i++) {
if (src == v[i]) {
for (int j = 0; j < js.getValue(); j++) {
int x = (int) (Math.random() * canevas.getWidth());
int y = (int) (Math.random() * canevas.getHeight());
int n = 0;
do {
n = (int) (Math.random() * nbi);
} while (n == i);
if (x > 80)
x -= 80;
if (y > 80)
y -= 80;
g.drawImage(imagei[n].getImage(), x, y, null);
}
x2 = (int) (Math.random() * canevas.getWidth());
y2 = (int) (Math.random() * canevas.getHeight());
if (x2 > 80)
x2 -= 80;
if (y2 > 80)
y2 -= 80;
g.drawImage(imagei[i].getImage(), x2, y2, null);
temp2 = i;
do {
n = (int) (Math.random() * nbi);
} while (n == temp2);
g.drawImage(imagei[n].getImage(), x2 + 13, y2, null);
}
}
}
public void list() {
js.addAdjustmentListener(this);
for (int i = 0; i < nbi; i++) {
v[i].addActionListener(this);
}
a.addActionListener(this);
canevas.addMouseListener(this);
}
public void adjustmentValueChanged(AdjustmentEvent x) {
nombre.setText("" + js.getValue());
}
public void actionPerformed(ActionEvent ae) {
src = ae.getSource();
if (src == a) {
try {
g.setColor(canevas.getBackground());
g.fillRect(0, 0, canevas.getWidth(), canevas.getHeight());
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
g = canevas.getGraphics();
g.setColor(canevas.getBackground());
g.fillRect(0, 0, canevas.getWidth(), canevas.getHeight());
t = new Thread(this);
t.start();
}
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println(x2 + "," + y2 + "\n" + x + " " + y);
// if((x>=x2 && x<=x2+80)&&(x>=x2 && y<=y2+80)){
if ((x >= x2 && x <= x2 + 80) && (y >= y2 && y <= y2 + 80)) {
System.out.println("True");
g.setColor(canevas.getBackground());
g.fillRect(0, 0, canevas.getWidth(), canevas.getHeight());
System.out.println("in");
g.drawImage(imagei[temp2].getImage(), x2, y2, null);
System.out.println(temp2);
System.out.println("end");
} else {
System.out.println("false");
}
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
new Pokemoneur();
}
}
The problem is that when the user move the Jframe when the images have been drawn off the screen, the image don't stay...
Before: http://i.stack.imgur.com/KHIvm.png
After : http://i.stack.imgur.com/koZSI.png
You ask:
but when the window goes off screen, the images that have been drawn have disappeared, and I have been wondering if there is a way to avoid that?
This means that you have a bug in your code somewhere, in code that you're not in fact showing us.
Perhaps you're drawing with a Graphics object that you've obtained by calling getGraphics() on a component, but all I can do is make a wild A$$ed guess at this point. If you are doing this, don't. Calling getGraphics() on a component will get you a Graphics object that will not persist on repeat paints, and will result in images that likewise don't persist. Draw instead in the paintComponent(Graphics g) method of a JPanel that is displayed in the JFrame as is well described in the Performing Custom Painting with Swing tutorials. But most important, please put just a little effort into asking your question so we don't have to guess at code not seen.
Well when I am pressing any of the key arrows, the red box moves, yes it moves 10px and then stops for 1 second & continues moving, instead of move right away without stopping.
example of the occurring issue:
(source: gyazo.com)
Can you see how it stopped for 1 or 0.5 secs and continued?
How can I fix it?
I am using KeyEventDispatcher
My key detecting:
Whole src:
public class Game extends Frame {
private class Keyboard implements KeyEventDispatcher {
private Game game;
public Keyboard(Game game) {
this.game = game;
}
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
this.movement(e);
} else if (e.getID() == KeyEvent.KEY_RELEASED) {
} else if (e.getID() == KeyEvent.KEY_TYPED) {
}
return false;
}
public void movement(KeyEvent e) {
int keyCode = e.getKeyCode();
switch( keyCode ) {
case KeyEvent.VK_UP:
game.movePlayer(0, -10);
break;
case KeyEvent.VK_DOWN:
game.movePlayer(0, 10);
break;
case KeyEvent.VK_LEFT:
game.movePlayer(-10, 0);
break;
case KeyEvent.VK_RIGHT :
game.movePlayer(10, 0);
break;
}
}
}
private static final long serialVersionUID = 1L;
private int coordinateX = 1;
private int coordinateY = 1;
public int width = 300;
public int height = width / 16 * 9;
public int scale = 3;
public int mouseY = MouseInfo.getPointerInfo().getLocation().y;
public int mouseX = MouseInfo.getPointerInfo().getLocation().x;
private Player player = new Player(0, 0);
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
frame.setSize(width, height);
frame.setResizable(false);
frame.setTitle("First game");
JPanel j = new JPanel();
j.setVisible(true);
JLabel text = new JLabel("coords");
j.add(text);
frame.add(this);
frame.pack();
frame.add(j);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher(new Keyboard(this));
}
private void movePlayer(int x, int y) {
/**
* Main region area
*/
int pX = 0, pY = 0;
if (y == 0) { // x
if (player.getX() + x + 100 > frame.getContentPane().getWidth() || player.getX() + x < 0) {
if (player.getX() + x < 0) {
player.setX(0);
return;
}
if (player.getX() + x > 0) {
player.setX(frame.getContentPane().getWidth() - 100);
return;
}
return;
}
pX = x;
}
else if (x == 0) { // y
if (player.getY() + y + 100 > frame.getContentPane().getHeight() || player.getY() + y < 0) {
if (player.getY() + y < 0) {
player.setY(0);
return;
}
if (player.getY() + y > 0) {
player.setY(frame.getContentPane().getHeight() - 100);
return;
}
return;
}
pY = y;
}
player.updatePosition(pX, pY);
}
public void update() {
}
public void render() {
bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.RED);
g.fillRect(player.getX(), player.getY(), 100, 100);
g.dispose();
bs.show();
}
}
Frame.java:
public class Frame extends Canvas {
public static final long serialVersionUID = 8L;
public static JFrame frame = new JFrame();
public static Threads thread;
public static Game game;
public Graphics g;
public BufferStrategy bs;
/**
* #param args
*/
public static void main(String[] args) {
thread = new Threads(new Game());
thread.start();
}
}
The problem is the repeat rate for KeyStrokes. This is controlled by the OS.
The solution is to use a Swing Timer to schedule the animation as soon as the key is pressed.
See Motion Using the Keyboard for more information and a complete working example.
Also, you should NOT be using a KeyListener but intead should be using KeyBindings.
I'm trying to create a custom extension of BasicSliderUI. I'm just trying to make the thumb a circle (note I'm in the Windows L&F). I've created a very simple implementation that just calls g.drawOval, but whenever I drag it, it leaves a "trail" behind. Any ideas why this is?
thanks,
Jeff
You need to call repaint on the whole thing, you cant just draw the oval on top of it. Swing will by default only repaint what needs to be repainted, which usually isn't the whole control. When are you drawing the circle?
If you want to get rid of "trail" when you drag you should write your custom TrackListener and control trumb position related to mouse move.
Look at my implementation:
public class LightSliderUI extends BasicSliderUI{
private final Color rangeColor = Color.BLUE;
private final BasicStroke stroke = new BasicStroke(2f);
private transient boolean upperDragging;
public LightSliderUI(JSlider b) {
super(b);
}
public static ComponentUI createUI(JComponent c) {
return new LightSliderUI((JSlider)c);
}
#Override
protected void calculateThumbSize() {
super.calculateThumbSize();
thumbRect.setSize(thumbRect.width, thumbRect.height);
}
/** Creates a listener to handle track events in the specified slider.*/
#Override
protected TrackListener createTrackListener(JSlider slider) {
return new RangeTrackListener();
}
#Override
protected void calculateThumbLocation() {
// Call superclass method for lower thumb location.
super.calculateThumbLocation();
// Adjust upper value to snap to ticks if necessary.
if (slider.getSnapToTicks()) {
int upperValue = slider.getValue() + slider.getExtent();
int snappedValue = upperValue;
int majorTickSpacing = slider.getMajorTickSpacing();
int minorTickSpacing = slider.getMinorTickSpacing();
int tickSpacing = 0;
if (minorTickSpacing > 0) {
tickSpacing = minorTickSpacing;
} else if (majorTickSpacing > 0) {
tickSpacing = majorTickSpacing;
}
if (tickSpacing != 0) {
// If it's not on a tick, change the value
if ((upperValue - slider.getMinimum()) % tickSpacing != 0) {
float temp = (float)(upperValue - slider.getMinimum()) / (float)tickSpacing;
int whichTick = Math.round(temp);
snappedValue = slider.getMinimum() + (whichTick * tickSpacing);
}
if (snappedValue != upperValue) {
slider.setExtent(snappedValue - slider.getValue());
}
}
}
// Calculate upper thumb location. The thumb is centered over its
// value on the track.
if (slider.getOrientation() == JSlider.HORIZONTAL) {
int upperPosition = xPositionForValue(slider.getValue() + slider.getExtent());
thumbRect.x = upperPosition - (thumbRect.width / 2);
thumbRect.y = trackRect.y;
} else {
int upperPosition = yPositionForValue(slider.getValue() + slider.getExtent());
thumbRect.x = trackRect.x;
thumbRect.y = upperPosition - (thumbRect.height / 2);
}
slider.repaint();
}
/** Returns the size of a thumb.
* Parent method not use size from LaF
* #return size of trumb */
#Override
protected Dimension getThumbSize() {
return Dimensions.getSliderThumbSize();
}
private Shape createThumbShape(int width, int height) {
Ellipse2D shape = new Ellipse2D.Double(0, 0, width, height);
return shape;
}
#Override
public void paintTrack(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Stroke old = g2d.getStroke();
g2d.setStroke(stroke);
g2d.setPaint(Colors.TEXT_STEEL);
Color oldColor = Colors.TEXT_STEEL;
Rectangle trackBounds = trackRect;
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2,
trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2);
int lowerX = thumbRect.width / 2;
int upperX = thumbRect.x + (thumbRect.width / 2);
int cy = (trackBounds.height / 2) - 2;
g2d.translate(trackBounds.x, trackBounds.y + cy);
g2d.setColor(rangeColor);
g2d.drawLine(lowerX - trackBounds.x, 2, upperX - trackBounds.x, 2);
g2d.translate(-trackBounds.x, -(trackBounds.y + cy));
g2d.setColor(oldColor);
}
g2d.setStroke(old);
}
/** Overrides superclass method to do nothing. Thumb painting is handled
* within the <code>paint()</code> method.*/
#Override
public void paintThumb(Graphics g) {
Rectangle knobBounds = thumbRect;
int w = knobBounds.width;
int h = knobBounds.height;
Graphics2D g2d = (Graphics2D) g.create();
Shape thumbShape = createThumbShape(w - 1, h - 1);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate(knobBounds.x, knobBounds.y);
g2d.setColor(Color.WHITE);
g2d.fill(thumbShape);
g2d.setColor(Colors.BIOLIN_BLUE_TINT);
g2d.draw(thumbShape);
g2d.dispose();
}
/** Listener to handle model change events. This calculates the thumb
* locations and repaints the slider if the value change is not caused by dragging a thumb.*/
public class ChangeHandler implements ChangeListener {
#Override
public void stateChanged(ChangeEvent arg0) {
calculateThumbLocation();
slider.repaint();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
JSlider slider = new JSlider(0, 100);
slider.setPaintTicks(true);
slider.setUI(new LightSliderUI(slider));
frame.add(slider);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
/** Listener to handle mouse movements in the slider track.*/
public class RangeTrackListener extends TrackListener {
#Override
public void mouseClicked(MouseEvent e) {
if (!slider.isEnabled()) {
return;
}
currentMouseX -= thumbRect.width / 2; // Because we want the mouse location correspond to middle of the "thumb", not left side of it.
moveUpperThumb();
}
public void mousePressed(MouseEvent e) {
if (!slider.isEnabled()) {
return;
}
currentMouseX = e.getX();
currentMouseY = e.getY();
if (slider.isRequestFocusEnabled()) {
slider.requestFocus();
}
boolean upperPressed = false;
if (slider.getMinimum() == slider.getValue()) {
if (thumbRect.contains(currentMouseX, currentMouseY)) {
upperPressed = true;
}
} else {
if (thumbRect.contains(currentMouseX, currentMouseY)) {
upperPressed = true;
}
}
if (upperPressed) {
switch (slider.getOrientation()) {
case JSlider.VERTICAL:
offset = currentMouseY - thumbRect.y;
break;
case JSlider.HORIZONTAL:
offset = currentMouseX - thumbRect.x;
break;
}
//upperThumbSelected = true;
upperDragging = true;
return;
}
upperDragging = false;
}
#Override
public void mouseReleased(MouseEvent e) {
upperDragging = false;
slider.setValueIsAdjusting(false);
super.mouseReleased(e);
}
#Override
public void mouseDragged(MouseEvent e) {
if (!slider.isEnabled()) {
return;
}
currentMouseX = e.getX();
currentMouseY = e.getY();
if (upperDragging) {
slider.setValueIsAdjusting(true);
moveUpperThumb();
}
}
#Override
public boolean shouldScroll(int direction) {
return false;
}
/** Moves the location of the upper thumb, and sets its corresponding value in the slider.*/
public void moveUpperThumb() {
int thumbMiddle = 0;
switch (slider.getOrientation()) {
case JSlider.HORIZONTAL:
int halfThumbWidth = thumbRect.width / 2;
int thumbLeft = currentMouseX - offset;
int trackLeft = trackRect.x;
int trackRight = trackRect.x + (trackRect.width - 1);
int hMax = xPositionForValue(slider.getMaximum() -
slider.getExtent());
if (drawInverted()) {
trackLeft = hMax;
}
else {
trackRight = hMax;
}
thumbLeft = Math.max(thumbLeft, trackLeft - halfThumbWidth);
thumbLeft = Math.min(thumbLeft, trackRight - halfThumbWidth);
setThumbLocation(thumbLeft, thumbRect.y);//setThumbLocation
thumbMiddle = thumbLeft + halfThumbWidth;
slider.setValue(valueForXPosition(thumbMiddle));
break;
default:
return;
}
}
}
}