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.
Related
i made a SnakeGame and its working in its basics, but i started to texture my snake with images.
i wanted the textures to change the direction whenever the snake changes directions aswell. and it is working, the problem i have is that every time the snake changes direction all of the snake body parts change direction at the same time which leads to texture bugs, how can i change the texture for the next bodyPart per one Timer tick?
And also how can i edit the Texture for the last bodyPart only for a tail
the code below is only the code from the important class "gamepanel"
the texture code is in the method draw(Graphics g)
thanks for the help i could not find any solutions to this.
package game;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class gamepanel extends JPanel implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 42L;
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH*SCREEN_HEIGHT)/UNIT_SIZE;
int DELAY = 100;
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
int bodyParts = 6;
String str = String.valueOf(bodyParts);
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random;
Image apple = new ImageIcon(this.getClass().getResource("/images/redapple.png")).getImage();
Image headup = new ImageIcon(this.getClass().getResource("/images/headup.png")).getImage();
Image headr = new ImageIcon(this.getClass().getResource("/images/headr.png")).getImage();
Image headl = new ImageIcon(this.getClass().getResource("/images/headl.png")).getImage();
Image headd = new ImageIcon(this.getClass().getResource("/images/headd.png")).getImage();
Image bodyup = new ImageIcon(this.getClass().getResource("/images/bodyup.png")).getImage();
Image bodyd = new ImageIcon(this.getClass().getResource("/images/bodyd.png")).getImage();
Image bodyr = new ImageIcon(this.getClass().getResource("/images/bodyr.png")).getImage();
Image bodyl = new ImageIcon(this.getClass().getResource("/images/bodyl.png")).getImage();
gamepanel(){
random = new Random();
this.setPreferredSize(new Dimension(SCREEN_WIDTH,SCREEN_HEIGHT));
this.setBackground(new Color(33, 33, 33));
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
}
public void startGame() {
newApple();
running = true;
timer = new Timer(DELAY,this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
if(running) {
/* for(int i=0;i<SCREEN_HEIGHT/UNIT_SIZE;i++) {
g.drawLine(i*UNIT_SIZE, 0, i*UNIT_SIZE, SCREEN_HEIGHT);
g.drawLine(0, i*UNIT_SIZE, SCREEN_WIDTH, i*UNIT_SIZE);
} */
//g.setColor(new Color(73, 235, 116));
//g.fillOval(appleX,appleY, UNIT_SIZE, UNIT_SIZE);
g.drawImage(apple, appleX,appleY, UNIT_SIZE, UNIT_SIZE, null, null);
for(int i = 0;i< bodyParts; i++) {
//HEAD TEXTURE
if(i==0 && direction=='U') {
g.drawImage(headup,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
} else if(i==0 && direction=='R') {
g.drawImage(headr,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
} else if(i==0 && direction=='L') {
g.drawImage(headl,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
} else if(i==0 && direction=='D') {
g.drawImage(headd,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
//BODY TEXTURE
} else if(i!=0 && direction=='U') {
g.drawImage(bodyup,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
} else if(i!=0 && direction=='R') {
g.drawImage(bodyr,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
} else if(i!=0 && direction=='L') {
g.drawImage(bodyl,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
} else if(i!=0 && direction=='D') {
g.drawImage(bodyd,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null);
}
}
g.setColor(Color.red);
g.setFont(new Font("Arial",Font.BOLD,40));
FontMetrics metrics = getFontMetrics(g.getFont());
g.drawString("Score: "+applesEaten, (SCREEN_WIDTH - metrics.stringWidth("Score: "+applesEaten))/2, g.getFont().getSize());
}else {
gameOver(g);
}
}
public void newApple() {
appleX = random.nextInt((int)(SCREEN_WIDTH/UNIT_SIZE))*UNIT_SIZE;
appleY = random.nextInt((int)(SCREEN_HEIGHT/UNIT_SIZE))*UNIT_SIZE;
}
public void move() {
for(int i = bodyParts;i>0;i--) {
x[i] = x[i-1];
y[i] = y[i-1];
}
switch(direction) {
case 'U' :
y[0] = y[0] - UNIT_SIZE;
break;
case 'D' :
y[0] = y[0] + UNIT_SIZE;
break;
case 'L' :
x[0] = x[0] - UNIT_SIZE;
break;
case 'R' :
x[0] = x[0] + UNIT_SIZE;
break;
}
}
public void checkApple() {
int i = bodyParts;
if((x[i] == appleX) && (y[i] == appleY)) {
newApple();
} else if((x[0] == appleX) && (y[0] == appleY)) {
bodyParts++;
applesEaten++;
DELAY--;
newApple();
}
}
public void checkCollisions() {
//checks if head collides with body
for(int i = bodyParts; i>0;i--) {
if ((x[0]==x[i]) && (y[0]==y[i])) {
running = false;
}
}
// checks if head touches left border
if(x[0] < 0) {
running = false;
}
// check right border collide
if(x[0] > SCREEN_WIDTH) {
running = false;
}
// check top border
if(y[0] < 0) {
running = false;
}
//checkk bottom border
if(y[0] > SCREEN_HEIGHT) {
running = false;
}
if(!running) {
timer.stop();
}
}
public void gameOver(Graphics g) {
//SCORE
g.setColor(Color.red);
g.setFont(new Font("Arial",Font.BOLD,40));
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("Your Score: "+applesEaten, (SCREEN_WIDTH - metrics1.stringWidth("Your Score: "+applesEaten))/2, g.getFont().getSize());
//GAme Over Text
g.setColor(Color.red);
g.setFont(new Font("Arial",Font.BOLD,75));
FontMetrics metrics2 = getFontMetrics(g.getFont());
g.drawString("Game Over", (SCREEN_WIDTH - metrics2.stringWidth("Game Over"))/2, SCREEN_HEIGHT/2);
}
#Override
public void actionPerformed(ActionEvent e) {
if(running) {
move();
checkApple();
checkCollisions();
}
repaint();
}
public class MyKeyAdapter extends KeyAdapter{
#Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if(direction != 'R') {
direction = 'L';
}
break;
case KeyEvent.VK_RIGHT:
if(direction != 'L') {
direction = 'R';
}
break;
case KeyEvent.VK_UP:
if(direction != 'D') {
direction = 'U';
}
break;
case KeyEvent.VK_DOWN:
if(direction != 'U') {
direction = 'D';
}
break;
}
}
}
}
maybe try updating the textures for each body part starting from the head 1 per game frame at a time? like 0 = head piece and will be updated first, 1 is the next body part in line so will be updated in the next frame when the snake has moved 1 unit and therefore lining up the timings
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).
Okay so I am programming a GUI using java swing and I have been using some old code that I used to create a moving square, but now I have to use toggle buttons to make some shapes appear and disappear from the window. My program is supposed to have 4 different toggle buttons(have 3 at the moment) and each will have a specific purpose: Name will display my name in the center of the screen, rectangle will display a rectangle on the bottom right of the screen, and oval will display an oval on the bottom right also. I have tried to use a series of Boolean in order to dictate which shape appears, but for some reason each button will only toggle the rectangle and i dont know why. Is there something I am doing wrong that causes all the buttons to do the same thing?
here is my code so far. First one is my paintPanel:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PaintPanel extends JPanel
{
private static Color[] colors =
{ Color.RED, Color.BLACK, Color.PINK, Color.ORANGE };
private int colorNumber = 0;
private int shape = 0;
private int x = 0;
private int y = 0;
private int width = 100;
private int height = 100;
private String display = " ";
private String none = " ";
private int dx = 2;
private int dy = 2;
private boolean rectangle = true;
private boolean oval= true;
private boolean Name = true;
private boolean special = true;
private String displayString = "hello";
private boolean isStarted = true;
/*public void update()
{
if (isStarted)
{
x += dx;
y += dy;
}
//dx ++;
//dy ++;
if (y + height > getHeight())
{
dy = -Math.abs(dy);
shape++;
colorNumber = (colorNumber+1)%colors.length;
}
else if (y < 0)
{
dy = Math.abs(dy);
shape++;
colorNumber = (colorNumber+1)%colors.length;
}
if (x + width > getWidth())
{
dx = -Math.abs(dx);
shape++;
colorNumber = (colorNumber+1)%colors.length;
}
else if (x < 0)
{
dx = Math.abs(dx);
shape++;
colorNumber = (colorNumber+1)%colors.length;
}
}*/
public void input()
{
System.out.print("Button");
}
public void changeColor()
{
colorNumber = (colorNumber+1) % colors.length;
}
/*public void startStop()
{
//if (isStarted == true) isStarted = false;
//else isStarted = true;
isStarted = !isStarted;
}
*/
public void setDisplayText(String dt)
{
displayString = dt;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
int textx = x+w/2;
int texty = y+h/2;
FontMetrics fm = g.getFontMetrics();
int texth = fm.getHeight();
int textw = fm.stringWidth(display);
textx -= textw/2;
texty += texth/2;
texty -= 5;
if(Name == true)
{
g.setColor(Color.BLACK);
g.drawString(display, textx, texty);
Name = false;
}
else if(Name == false)
{
g.drawString(none, textx, texty);
Name = true;
}
if (oval == true)
{
g.setColor(Color.CYAN);
g.fillOval((5*w)/8, (5*h)/8, w/4, h/4);
oval = false;
}
else if(oval == false)
{
g.setColor(Color.WHITE);
g.fillOval((5*w)/8, (5*h)/8, w/4, h/4);
oval = true;
}
if(rectangle == true)
{
g.setColor(Color.PINK);
g.fillRect(w/2, h/2, w/2, h/2);
rectangle = false;
}
else if(rectangle == false)
{
g.setColor(Color.WHITE);
g.fillRect(w/2, h/2, w/2, h/2);
rectangle = true;
}
/*int w = getWidth();
int h = getHeight();
g.setColor(colors[colorNumber]);
if (shape % 2 == 0) //g.fillOval(x, y, width, height);
elseg.fillRect(x,y, width, height);
*/
/*
int textx = x+width/2;
int texty = y+height/2;
FontMetrics fm = g.getFontMetrics();
int texth = fm.getHeight();
int textw = fm.stringWidth(displayString);
textx -= textw/2;
texty += texth/2;
texty -= 5;
g.setColor(colors[(colorNumber+1)%colors.length]);
g.drawString(displayString, textx, texty);
*/
}
}
Whatever is commented out is because it will be implemented later for a special button.
And here is my main class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GuiTest extends JFrame
implements ActionListener
{
private Timer frameTimer;
private JToggleButton Name;
private JToggleButton oval;
private JToggleButton rectangle;
//private JTextField theText;
private PaintPanel paintPanel;
public GuiTest()
{
setTitle("Servando Hernandez");
setSize(500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel topPanel = new JPanel();
topPanel.setLayout(new GridLayout(1,4));
Name = new JToggleButton("Name");
Name.addActionListener(this);
oval = new JToggleButton("Oval");
oval.addActionListener(this);
rectangle = new JToggleButton("Rectangle");
rectangle.addActionListener(this);
//theText = new JTextField("HI");
//theText.addActionListener(this);
topPanel.add(Name);
topPanel.add(oval);
topPanel.add(rectangle);
//topPanel.add(theText);
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(topPanel, BorderLayout.SOUTH);
paintPanel = new PaintPanel();
contentPane.add(paintPanel, BorderLayout.CENTER);
//frameTimer = new Timer(50, this);
//frameTimer.start();
}
public void actionPerformed(ActionEvent e)
{
//System.out.println("Action performed");
if (e.getSource() == oval)
{
paintPanel.input();
}
/*else if (e.getSource() == frameTimer)
{
paintPanel.update();
}*/
if (e.getSource() == rectangle)
{
paintPanel.input();
}
if (e.getSource() == oval)
{
//System.out.println("start/stop");
paintPanel.input();
}
if (e.getSource() == Name)
{
paintPanel.input();
String text = e.getActionCommand();
paintPanel.setDisplayText("Servando Hernandez");
//System.out.println(text);
}
repaint();
}
public static void main(String[] args)
{
GuiTest gui = new GuiTest();
gui.setVisible(true);
}
}
Whatever is commented out is because it will be implemented later for a special button.
Well, don't include the code in the question. The code is irrelevant to the question and we don't want to waste time reading it or guessing why it is there?
private boolean Name = true;
Why is the variable name capitalized? None of the other variables start with a capital (which is correct). Be consistent!!!
if(Name == true)
{
g.setColor(Color.BLACK);
g.drawString(display, textx, texty);
Name = false;
}
else if(Name == false)
{
g.drawString(none, textx, texty);
Name = true;
}
You are making the if statement to complex. If a boolean variable isn't true then it is false. Just use:
if(name == true)
//if(name) // even simpler, you don't need the "== true"
{
g.setColor(Color.BLACK);
g.drawString(display, textx, texty);
}
else
{
g.drawString(none, textx, texty);
}
I don't understand your ActionListener code. It doesn't matter what button you click you always execute paintPanel.input().
See edit below for example of what the code should be.
Tidy up the code using these suggestions. If you still need more help then post a proper SSCCE that demonstrates the problem.
Edit:
You need to add properties to your PaintPanel class. For example:
public void setOval(Boolean oval)
{
this.oval = oval;
repaint();
}
Now in the ActionListener your code would be:
if (e.getSource() == oval)
{
paintPanel.setOval( oval.isSelected();
}
There is lots of confusing things in your code. For starters, you are toggling on/off the state of all your shapes every time your paintComponent() runs. You should be handling the state from your actionPerformed() method. For example:
if (e.getSource() == rectangle) {
// paintPanel.input(); // what's this doing anyways?
paintPanel.setShowRectangle(rectangle.isSelected());
}
At any rate, your other shapes aren't showing for various reasons...
Your display is an blank string. Try this and see:
g.drawString("Test", textx, texty);
You position is drawing it off the panel. I changed it (5 to 1) just to make it appear, but you'll probably want it somewhere else:
g.fillOval((1 * w) / 8, (1 * h) / 8, w / 4, h / 4);
I am making a JFrame holding several images that refresh using repaint(). The problem, however, was that the more images I added (or as the area that was being rendered increased) the framerate drastically decreased.
I was initially attempting to reduce the lag that Swing's unpredictable Timer experiences, but was unsuccessful. This time, I tried to call
repaint()
every 10 milliseconds based on system time. (To bypass the timer, desktop.screenPaint.drawWindow(); is called instead of repaint())
while(true)
{
long starttime = System.currentTimeMillis();
while(System.currentTimeMillis()-starttime < 10)
{
}
desktop.screenPaint.drawWindow();
desktop2.screenPaint.drawWindow();
}
Each "desktop" is just one of the draggable windows that you see if you run the code below. I noticed that when only "desktop" is added to "frame," there is no flickering. However, when "desktop2" is also added, flickering does not go away until the time until each refresh is set to 20 or more milliseconds. It is extremely strange, because when I was still using the timer, even thought the wait was set to 10 milliseconds, the framerate would lower to a frame every 20 milliseconds! I tested a little and noticed a trend: you will get flickering until the wait time to the amount of time that the 10 millisecond timer lagged behind. My question: Why is this happening? And is there any way to prevent the flickering, other than going back to the timer?
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.SwingUtilities.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;
import java.io.File;
import java.io.IOException;
public class Display extends JPanel
{
public static int width, height;
public static JFrame frame = new JFrame("");
private static int rh = 10;
public static Display desktop = new Display();
public static Display desktop2 = new Display();
public static void main(String[] args)
{
Dimension screen = new Dimension();
screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
width = (int)screen.getWidth();
height = (int)screen.getHeight();
frame.setLayout(null);
frame.setLocation(0, 0);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
desktop.setBounds(0, 0, 620, 500+rh);
desktop2.setBounds(1000, 200, 620, 500+rh);
frame.add(desktop);
frame.add(desktop2);
frame.setUndecorated(true);
frame.setSize(width, height);
frame.setVisible(true);
while(true)
{
long starttime = System.currentTimeMillis();
while(System.currentTimeMillis()-starttime < 10)
{
}
desktop.screenPaint.drawWindow();
//desktop2.screenPaint.drawWindow();
}
}
private BufferedImage image;
private Graphics2D g;
public Listener screenPaint = new Listener();
private Display identify;
public Display()
{
identify = this;
image = new BufferedImage(620, 500+rh, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D)image.getGraphics();
Timer timer = new Timer(1, screenPaint);
timer.start();
addMouseListener(new mMouse());
addMouseWheelListener(new wWheel());
setFocusable(true);
}
private BufferedImage toCompatibleImage(BufferedImage image)
{
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
if (image.getColorModel().equals(gfx_config.getColorModel()))
return image;
BufferedImage new_image = gfx_config.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
}
public void paint(Graphics view)
{
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
view.drawImage(toCompatibleImage(image), 0, 0, 620, 500+rh, null);
view.dispose();
}
private class Listener implements ActionListener
{
int y = 0;
int wy = 0;
int b = 500;
int c = 1500;
int iy = (int)(wy/(c/(double)b));
int a = -1;
int i = -1;
int j = -1;
boolean d = false;
boolean u = false;
int f = 0;
public void moveY(int sy)
{
f += sy;
}
public void actionPerformed(ActionEvent e)
{
//drawWindow();
}
public void drawWindow()
{
int lx = (int)(identify.getLocation().getX());
int ly = (int)(identify.getLocation().getY());
g.setColor(Color.white);
g.fillRect(0, 0, 620, 500+rh);
g.drawImage(new ImageIcon("image.png").getImage(), 0, wy+rh, 610, c, null);
if(c > b)
{
if(d || Mouse.withinRect(610+lx, (int)(-wy/(c/(double)b))+rh+ly, 10, (int)Math.ceil(Math.pow(b, 2)/(double)c)))
{
if(Mouse.pressLeft())
{
if(!d)d = true;
if(a == -1)a = Mouse.y()-(int)(-wy/(c/(double)b));
y = (int)((Mouse.y()-a)*(c/(double)b));
f = y;
g.setColor(Color.black);
}
else
{
if(d)d = false;
if(a != -1)a = -1;
g.setColor(new Color(60, 60, 60));
}
}
else
{
g.setColor(Color.gray);
if(a != -1)a = -1;
}
if(y == f){}
else if(y < f)
{
y += (int)((f-y)*0.1);
if(y < f)y++;
}
else
{
y -= (int)((y-f)*0.1);
if(y > f)y--;
}
if(y < 0)
{
y = 0;
f = 0;
}
else if(y > c-b)
{
y = c-b;
f = y;
}
wy = -y;
if(u || Mouse.withinRect(lx, ly, 620, 10))
{
if(Mouse.pressLeft())
{
if(!u)u = true;
if(i == -1)i = Mouse.x()-lx;
if(j == -1)j = Mouse.y()-ly;
identify.setLocation(Mouse.x()-i, Mouse.y()-j);
}
else
{
if(u)u = false;
if(i != -1)i = -1;
if(j != -1)j = -1;
}
}
else
{
if(u)u = false;
if(i != -1)i = -1;
if(j != -1)j = -1;
}
int scrollBarLength = (int)Math.ceil(Math.pow(b, 2)/(double)c);
g.fillRect(610, (int)(-wy/(c/(double)b))+rh, 10, scrollBarLength);
}
else
{
g.setColor(new Color(200, 200, 200));
g.fillRect(610, rh, 10, b);
}
g.setColor(new Color(50, 50, 50));
g.fillRect(0, 0, 620, rh);
if(identify == desktop)
repaint();
else if(false)
{}
}
}
}
public static boolean LMPress, LMRelease = false;
public static boolean LMRight, LMLeft = false;
private class mMouse extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
LMPress = true; LMRelease = false;
if(SwingUtilities.isRightMouseButton(e))
{
LMRight = true;
LMLeft = false;
}
else if(SwingUtilities.isLeftMouseButton(e))
{
LMLeft = true;
LMRight = false;
}
}
public void mouseReleased(MouseEvent e)
{
LMRelease = true; LMPress = false;
if(SwingUtilities.isRightMouseButton(e))
{
LMRight = true;
LMLeft = false;
}
else if(SwingUtilities.isLeftMouseButton(e))
{
LMLeft = true;
LMRight = false;
}
}
}
private class wWheel implements MouseWheelListener
{
public void mouseWheelMoved(MouseWheelEvent e)
{
int notches = e.getWheelRotation();
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {}
e.getScrollAmount();
screenPaint.moveY(e.getUnitsToScroll()*60); //desired pixel jump: 120
}
}
}
Mouse class:
import java.awt.*;
import java.awt.event.*;
public class Mouse {
public static int x() {
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
return (int) b.getX();
}
public static int y() {
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
return (int) b.getY();
}
public static boolean withinRect(int x, int y, int w, int h) {
if (x() >= x && x() < x + w && y() >= y && y() < y + h) return true;
else return false;
}
public static boolean press() {
return Display.LMPress;
}
public static boolean release() {
return Display.LMRelease;
}
public static boolean pressLeft() {
if (Display.LMPress && Display.LMLeft)
return true;
else return false;
}
public static boolean releaseLeft() {
if (Display.LMRelease && Display.LMLeft)
return true;
else return false;
}
public static boolean pressRight() {
if (Display.LMPress && Display.LMRight)
return true;
else return false;
}
public static boolean releaseRight() {
if (Display.LMRelease && Display.LMRight)
return true;
else return false;
}
}
Updating the view at 1 kHz is unrealistic; instead, consider the alternatives cited here. See this AnimationTest for an example of self-timing to determine your animation budget.
Addendum: The while(true) loop at the top is running at 100 Hz.
The available resolution of System.currentTimeMillis() may vary by platform.
Addendum: I am reopening this question because I was not able to fix it. Any more help?
Absent a Minimal, Complete, Tested and Readable Example, it's hard to say. You appear to be overriding paint(); was noted in Painting in AWT and Swing: The Paint Methods, "Swing programs should override paintComponent()." Moreover, you need to invoke super.paintComponent(), as shown here, to avoid visual artifacts.