跳绳用Java动画撕裂 [英] Skipping and Tearing in Java Animation

查看:269
本文介绍了跳绳用Java动画撕裂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下code绘制与两个较小的正方形里面旋转一个正方形。只要您按键盘上的箭头,整个系统将在该方向移动。但是我有一些问题与图像撕裂,有时跳跃(其小,但仍然存在)。我想知道是否有人知道我怎么能解决这些问题的w / o大量改变code。

 进口java.awt中的*。
java.awt.event中导入*。
进口的javax.swing *。
进口静态java.awt.Color中的*。公共类GUI继承JPanel实现的ActionListener,的KeyListener
{
    INT的x,y,X1,Y1,X2,Y2,changeX,changeY,changeX2,changeY2;
    JFrame的框架;
    运行时 - [R;
    公共静态无效的主要(字串[] args)
    {
        新的GUI();
    }
    公共GUI()
    {
        尝试
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }赶上(例外五)
        {
            e.printStackTrace();
        }        的setSize(1020,770);
        的setBackground(白色);
        setOpaque(真);
        调用setVisible(真);        X = 0;
        Y = 0;
        X1 = 0;
        Y1 = 0;
        X2 = 0;
        Y2 = 0;
        changeX = 1;
        changeY = 0;
        changeX2 = 1;
        changeY2 = 0;
        R =调用Runtime.getRuntime();        帧=新的JFrame();
        frame.setSize(1020,819);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenuBar());
        frame.validate();
        frame.setBackground(白色);
        frame.addKeyListener(本);
        frame.setTitle(GUI);
        frame.setContentPane(本);
        frame.setVisible(真);
        frame.createBufferStrategy(2);        TIMER T =新的Timer(100本);
        t.se​​tActionCommand(抽奖);
        t.start();        重绘();
    }
    公共的JMenuBar createMenuBar()
    {
        的JMenuBar菜单栏=新的JMenuBar();        JMenu的fileMenu =新JMenu,(文件);
        JMenuItem的保存=新的JMenuItem(保存);
        save.setMnemonic(KeyEvent.VK_S);
        save.setContentAreaFilled(假);
        save.setOpaque(假);
        save.addActionListener(本);
        JMenuItem的负载=新的JMenuItem(装载);
        load.setMnemonic(KeyEvent.VK_L);
        load.setContentAreaFilled(假);
        load.setOpaque(假);
        load.addActionListener(本);
        JMenuItem的退出=新的JMenuItem(退出);
        quit.setMnemonic(KeyEvent.VK_Q);
        quit.setContentAreaFilled(假);
        quit.setOpaque(假);
        quit.addActionListener(本);
        fileMenu.add(保存);
        fileMenu.add(负载);
        fileMenu.addSeparator();
        fileMenu.add(退出);
        fileMenu.setContentAreaFilled(假);
        fileMenu.setBorderPainted(假);
        fileMenu.setOpaque(假);        JMenu的editMenu =新JMenu,(编辑);
        JMenuItem的撤消=新的JMenuItem(撤消);
        undo.setMnemonic(KeyEvent.VK_U);
        undo.setContentAreaFilled(假);
        undo.setOpaque(假);
        undo.addActionListener(本);
        JMenuItem的重做=新的JMenuItem(重做);
        redo.setMnemonic(KeyEvent.VK_R);
        redo.setContentAreaFilled(假);
        redo.setOpaque(假);
        redo.addActionListener(本);
        editMenu.add(撤销);
        editMenu.add(重做);
        editMenu.setContentAreaFilled(假);
        editMenu.setBorderPainted(假);
        editMenu.setOpaque(假);        JMenu的helpMenu =新JMenu,(帮助);
        JMenuItem的控制=新的JMenuItem(控制);
        controls.setMnemonic(KeyEvent.VK_C);
        controls.setContentAreaFilled(假);
        controls.setOpaque(假);
        controls.addActionListener(本);
        有关的JMenuItem =新的JMenuItem(关于);
        about.setMnemonic(KeyEvent.VK_A);
        about.setContentAreaFilled(假);
        about.setOpaque(假);
        about.addActionListener(本);
        helpMenu.add(对照);
        helpMenu.addSeparator();
        helpMenu.add(约);
        helpMenu.setContentAreaFilled(假);
        helpMenu.setBorderPainted(假);
        helpMenu.setOpaque(假);        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(helpMenu);
        返回菜单栏;
    }
    公共无效的paintComponent(图形G)
    {
        g.clearRect(0,0,1020,770);
        g.setColor(黑色);
        g.fillRect(X,Y​​,100,100);
        g.setColor(RED);
        g.fillRect(X1,y1,50,50);
        g.setColor(蓝);
        g.fillRect(X2,y2,25,25);
        g.dispose();
    }
    公共无效的变化()
    {
        如果(X1> = X + 50安培;&放大器; changeY == 0&放大器;&放大器; changeX == 1)
        {
            changeX = 0;
            changeY = 1;
        }
        否则,如果(Y> = Y + 50安培;&安培; changeX == 0安培;&安培; changeY == 1)
        {
            changeX = -1;
            changeY = 0;
        }
        否则如果(X1&下; = X&放大器;&放大器; changeX == - 1和;&放大器; changeY == 0)
        {
            changeX = 0;
            changeY = -1;
        }
        否则,如果(Y< = Y&放大器;&安培; changeY == - 1安培;&安培; changeX == 0)
        {
            changeX = 1;
            changeY = 0;
        }
        X1 + = changeX * 5;
        Y1 + = changeY * 5;
    }
    公共无效change2()
    {
        如果(X2> = X1 + 25安培;&安培; changeY2 == 0安培;&安培; changeX2 == 1)
        {
            changeX2 = 0;
            changeY2 = 1;
        }
        否则如果(Y2&GT = Y1 + 25安培;&放大器; changeX2 == 0&放大器;&放大器; changeY2 == 1)
        {
            changeX2 = -1;
            changeY2 = 0;
        }
        否则,如果(X2< = X1&放大器;&安培; changeX2 == - 1安培;&安培; changeY2 == 0)
        {
            changeX2 = 0;
            changeY2 = -1;
        }
        否则,如果(Y< = Y1,放大器;&安培; changeY2 == - 1安培;&安培; changeX2 == 0)
        {
            changeX2 = 1;
            changeY2 = 0;
        }
        2 + = changeX2 * 2;
        Y2 + = changeY2 * 2;
    }
    公共无效的actionPerformed(ActionEvent的五)
    {
        如果(e.getActionCommand()。equalsIgnoreCase(抽奖))
        {
            r.runFinalization();
            r.gc();
            更改();
            change2();
            重绘();
        }
    }
    公共无效键pressed(KeyEvent e而)
    {
        如果(e.getKey code()== KeyEvent.VK_UP)
        {
            如果(γ-10 -10 = 0)
            {
                y轴= 10;
                Y1- = 10;
                的Y2 = 10;
            }
        }
        如果(e.getKey code()== KeyEvent.VK_DOWN)
        {
            如果(Y + 110℃; =的getHeight())
            {
                Y + = 10;
                Y1 + = 10;
                Y2 + = 10;
            }
        }
        如果(e.getKey code()== KeyEvent.VK_LEFT)
        {
            如果(X-10 -10 = 0)
            {
                X轴= 10;
                X1- = 10;
                X2- = 10;
            }
        }
        如果(e.getKey code()== KeyEvent.VK_RIGHT)
        {
            如果(X + 110℃; =的getWidth())
            {
                X + = 10;
                X1 + = 10;
                2 + = 10;
            }
        }
        重绘();
    }
    公共无效调用keyReleased(KeyEvent e而)
    {
    }
    公共无效的keyTyped(KeyEvent e而)
    {
    }
}


解决方案

您不是构建在的 EDT javax.swing中的一个实例。定时器 使这个容易,操作事件处理程序上的 EDT

附录1:您的可能的决定你需要的双缓冲,但首先比较code下面你看看。如果你走这条路线,你可以看看这个的教程

附录2:下面的例子演示了如何保持屏幕外的缓冲区,但有时更容易使用的 的JP​​anel(布尔的isDoubleBuffered) 构造类似的效果。

 进口java.awt.event.KeyAdapter;
进口java.awt.Dimension中;
进口java.awt.EventQueue中;
进口java.awt.Graphics;
进口java.awt.event.ActionEvent中;
进口java.awt.event.ActionListener;
进口java.awt.event.KeyEvent中;
进口javax.swing.JFrame中;
进口javax.swing.JPanel中;
进口javax.swing.Timer中;
进口静态java.awt.Color中的*。/ ** @see http://stackoverflow.com/questions/2114455 * /
公共类GUI继承JPanel实现的ActionListener {    INT的x,y,X1,Y1,X2,Y2,changeY,changeY2;
    INT changeX = 1; INT changeX2 = 1;
    TIMER T =新的Timer(100本);    公共静态无效的主要(字串[] args){
        EventQueue.invokeLater(新的Runnable(){            @覆盖
            公共无效的run(){
                新的GUI(真)。显示();
            }
        });
    }    公共GUI(布尔doubleBuffered){
        超(doubleBuffered);
        this.set preferredSize(新尺寸(320,240));
    }    私人无效显示(){
        JFrame的帧=新的JFrame(GUI);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addKeyListener(新的KeyListener());
        frame.add(本);
        frame.pack();
        frame.setVisible(真);
        t.start();
    }    @覆盖
    公共无效的paintComponent(图形G){
        g.setColor(白色);
        g.fillRect(0,0,的getWidth(),的getHeight());
        g.setColor(黑色);
        g.fillRect(X,Y​​,100,100);
        g.setColor(RED);
        g.fillRect(X1,Y1,50,50);
        g.setColor(蓝);
        g.fillRect(X2,Y2,25,25);
    }    公共无效的变化(){
        如果(X1> = X + 50安培;&放大器; changeY == 0&放大器;&放大器; changeX == 1){
            changeX = 0;
            changeY = 1;
        }否则如果(Y> = Y + 50安培;&安培; changeX == 0安培;&安培; changeY == 1){
            changeX = -1;
            changeY = 0;
        }否则如果(X1< = X&放大器;&安培; changeX == -1放大器;&安培; changeY == 0){
            changeX = 0;
            changeY = -1;
        }否则如果(Y< = Y&放大器;&安培; changeY == -1放大器;&安培; changeX == 0){
            changeX = 1;
            changeY = 0;
        }
        X1 + = changeX * 5;
        Y1 + = changeY * 5;
    }    公共无效change2(){
        如果(X2> = X1 + 25安培;&安培; changeY2 == 0安培;&安培; changeX2 == 1){
            changeX2 = 0;
            changeY2 = 1;
        }否则如果(Y2&GT = Y1 + 25安培;&放大器; changeX2 == 0&放大器;&放大器; changeY2 == 1){
            changeX2 = -1;
            changeY2 = 0;
        }否则如果(X2< = X1&放大器;&安培; changeX2 == -1放大器;&安培; changeY2 == 0){
            changeX2 = 0;
            changeY2 = -1;
        }否则如果(Y< = Y1,放大器;&安培; changeY2 == -1放大器;&安培; changeX2 == 0){
            changeX2 = 1;
            changeY2 = 0;
        }
        2 + = changeX2 * 2;
        Y2 + = changeY2 * 2;
    }    @覆盖
    公共无效的actionPerformed(ActionEvent的五){
        更改();
        change2();
        重绘();
    }    私有类的KeyListener扩展KeyAdapter {        @覆盖
        公共无效键pressed(KeyEvent的E){
            INT D = 5;
            如果(e.getKey code()== KeyEvent.VK_UP){
                如果(γ - d取代; = 0){
                    Ÿ - = D;
                    Y1 - = D;
                    Y2 - = D;
                }
            }
            如果(e.getKey code()== KeyEvent.VK_DOWN){
                如果(Y + 100 + D&下; =的getHeight()){
                    Y + = D;
                    Y1 + = D;
                    Y2 + = D;
                }
            }
            如果(e.getKey code()== KeyEvent.VK_LEFT){
                如果(X - d取代; = 0){
                    点¯x - = D;
                    X1 - = D;
                    X2 - = D;
                }
            }
            如果(e.getKey code()== KeyEvent.VK_RIGHT){
                如果(X + 100 + D&下; =的getWidth()){
                    X + = D;
                    X1 + = D;
                    X2 + = D;
                }
            }
        }
    }
}

the following code draws a square with two smaller square rotating inside it. whenever you click an arrow on the keyboard, the whole system will move in that direction. however i'm having some problems with the image tearing and at times skipping (its small but still there). i was wondering if anybody knew how i could fix these issues w/o massively altering the code.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import static java.awt.Color.*;

public class GUI extends JPanel implements ActionListener, KeyListener
{
    int x, y, x1, y1, x2, y2, changeX, changeY, changeX2, changeY2;
    JFrame frame;
    Runtime r;
    public static void main(String[] args)
    {
        new GUI();
    }
    public GUI()
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        setSize(1020,770);
        setBackground(WHITE);
        setOpaque(true);
        setVisible(true);

        x = 0;
        y = 0;
        x1 = 0;
        y1 = 0;
        x2 = 0;
        y2 = 0;
        changeX=1;
        changeY=0;
        changeX2=1;
        changeY2=0;
        r = Runtime.getRuntime();

        frame = new JFrame();
        frame.setSize(1020,819);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenuBar());
        frame.validate();
        frame.setBackground(WHITE);
        frame.addKeyListener(this);
        frame.setTitle("GUI");
        frame.setContentPane(this);
        frame.setVisible(true);
        frame.createBufferStrategy(2);

        Timer t = new Timer(100,this);
        t.setActionCommand("Draw");
        t.start();

        repaint();
    }
    public JMenuBar createMenuBar()
    {
        JMenuBar menuBar = new JMenuBar();

        JMenu fileMenu = new JMenu("File");
        JMenuItem save = new JMenuItem("Save");
        save.setMnemonic(KeyEvent.VK_S);
        save.setContentAreaFilled(false);
        save.setOpaque(false);
        save.addActionListener(this);
        JMenuItem load = new JMenuItem("Load");
        load.setMnemonic(KeyEvent.VK_L);
        load.setContentAreaFilled(false);
        load.setOpaque(false);
        load.addActionListener(this);
        JMenuItem quit = new JMenuItem("Quit");
        quit.setMnemonic(KeyEvent.VK_Q);
        quit.setContentAreaFilled(false);
        quit.setOpaque(false);
        quit.addActionListener(this);
        fileMenu.add(save);
        fileMenu.add(load);
        fileMenu.addSeparator();
        fileMenu.add(quit);
        fileMenu.setContentAreaFilled(false);
        fileMenu.setBorderPainted(false);
        fileMenu.setOpaque(false);

        JMenu editMenu = new JMenu("Edit");
        JMenuItem undo = new JMenuItem("Undo");
        undo.setMnemonic(KeyEvent.VK_U);
        undo.setContentAreaFilled(false);
        undo.setOpaque(false);
        undo.addActionListener(this);
        JMenuItem redo = new JMenuItem("Redo");
        redo.setMnemonic(KeyEvent.VK_R);
        redo.setContentAreaFilled(false);
        redo.setOpaque(false);
        redo.addActionListener(this);
        editMenu.add(undo);
        editMenu.add(redo);
        editMenu.setContentAreaFilled(false);
        editMenu.setBorderPainted(false);
        editMenu.setOpaque(false);

        JMenu helpMenu = new JMenu("Help");
        JMenuItem controls = new JMenuItem("Controls");
        controls.setMnemonic(KeyEvent.VK_C);
        controls.setContentAreaFilled(false);
        controls.setOpaque(false);
        controls.addActionListener(this);
        JMenuItem about = new JMenuItem("About");
        about.setMnemonic(KeyEvent.VK_A);
        about.setContentAreaFilled(false);
        about.setOpaque(false);
        about.addActionListener(this);
        helpMenu.add(controls);
        helpMenu.addSeparator();
        helpMenu.add(about);
        helpMenu.setContentAreaFilled(false);
        helpMenu.setBorderPainted(false);
        helpMenu.setOpaque(false);

        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(helpMenu);
        return menuBar;
    }
    public void paintComponent(Graphics g)
    {
        g.clearRect(0, 0, 1020, 770);
        g.setColor(BLACK);
        g.fillRect(x,y,100,100);
        g.setColor(RED);
        g.fillRect(x1,y1,50,50);
        g.setColor(BLUE);
        g.fillRect(x2,y2,25,25);
        g.dispose();
    }
    public void change()
    {
        if(x1>=x+50&&changeY==0&&changeX==1)
        {
            changeX=0;
            changeY=1;
        }
        else if(y1>=y+50&&changeX==0&&changeY==1)
        {
            changeX=-1;
            changeY=0;
        }
        else if(x1<=x&&changeX==-1&&changeY==0)
        {
            changeX=0;
            changeY=-1;
        }
        else if(y1<=y&&changeY==-1&&changeX==0)
        {
            changeX=1;
            changeY=0;
        }
        x1+=changeX*5;
        y1+=changeY*5;
    }
    public void change2()
    {
        if(x2>=x1+25&&changeY2==0&&changeX2==1)
        {
            changeX2=0;
            changeY2=1;
        }
        else if(y2>=y1+25&&changeX2==0&&changeY2==1)
        {
            changeX2=-1;
            changeY2=0;
        }
        else if(x2<=x1&&changeX2==-1&&changeY2==0)
        {
            changeX2=0;
            changeY2=-1;
        }
        else if(y2<=y1&&changeY2==-1&&changeX2==0)
        {
            changeX2=1;
            changeY2=0;
        }
        x2+=changeX2*2;
        y2+=changeY2*2;
    }
    public void actionPerformed(ActionEvent e)
    {
        if(e.getActionCommand().equalsIgnoreCase("Draw"))
        {
            r.runFinalization();
            r.gc();
            change();
            change2();
            repaint();
        }
    }
    public void keyPressed(KeyEvent e)
    {
        if(e.getKeyCode()==KeyEvent.VK_UP)
        {
            if(y-10>=0)
            {
                y-=10;
                y1-=10;
                y2-=10;
            }
        }
        if(e.getKeyCode()==KeyEvent.VK_DOWN)
        {
            if(y+110<=getHeight())
            {
                y+=10;
                y1+=10;
                y2+=10;
            }
        }
        if(e.getKeyCode()==KeyEvent.VK_LEFT)
        {
            if(x-10>=0)
            {
                x-=10;
                x1-=10;
                x2-=10;
            }
        }
        if(e.getKeyCode()==KeyEvent.VK_RIGHT)
        {
            if(x+110<=getWidth())
            {
                x+=10;
                x1+=10;
                x2+=10;
            }
        }
        repaint();
    }
    public void keyReleased(KeyEvent e)
    {
    }
    public void keyTyped(KeyEvent e)
    {
    }
}

解决方案

You are not constructing on the EDT. An instance of javax.swing.Timer makes this easy, as the action event handler executes on the EDT.

Addendum 1: You may decide you need double buffering, but first compare the code below to yours and see. If you go that route, you might look at this tutorial.

Addendum 2: The example below shows how to maintain an offscreen buffer, but it is sometimes easier to use the JPanel(boolean isDoubleBuffered) constructor for a similar effect.

import java.awt.event.KeyAdapter;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import static java.awt.Color.*;

/** @see http://stackoverflow.com/questions/2114455 */
public class GUI extends JPanel implements ActionListener {

    int x, y, x1, y1, x2, y2, changeY, changeY2;
    int changeX = 1; int changeX2 = 1;
    Timer t = new Timer(100, this);

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new GUI(true).display();
            }
        });
    }

    public GUI(boolean doubleBuffered) {
        super(doubleBuffered);
        this.setPreferredSize(new Dimension(320, 240));
    }

    private void display() {
        JFrame frame = new JFrame("GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addKeyListener(new KeyListener());
        frame.add(this);
        frame.pack();
        frame.setVisible(true);
        t.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        g.setColor(WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(BLACK);
        g.fillRect(x, y, 100, 100);
        g.setColor(RED);
        g.fillRect(x1, y1, 50, 50);
        g.setColor(BLUE);
        g.fillRect(x2, y2, 25, 25);
    }

    public void change() {
        if (x1 >= x + 50 && changeY == 0 && changeX == 1) {
            changeX = 0;
            changeY = 1;
        } else if (y1 >= y + 50 && changeX == 0 && changeY == 1) {
            changeX = -1;
            changeY = 0;
        } else if (x1 <= x && changeX == -1 && changeY == 0) {
            changeX = 0;
            changeY = -1;
        } else if (y1 <= y && changeY == -1 && changeX == 0) {
            changeX = 1;
            changeY = 0;
        }
        x1 += changeX * 5;
        y1 += changeY * 5;
    }

    public void change2() {
        if (x2 >= x1 + 25 && changeY2 == 0 && changeX2 == 1) {
            changeX2 = 0;
            changeY2 = 1;
        } else if (y2 >= y1 + 25 && changeX2 == 0 && changeY2 == 1) {
            changeX2 = -1;
            changeY2 = 0;
        } else if (x2 <= x1 && changeX2 == -1 && changeY2 == 0) {
            changeX2 = 0;
            changeY2 = -1;
        } else if (y2 <= y1 && changeY2 == -1 && changeX2 == 0) {
            changeX2 = 1;
            changeY2 = 0;
        }
        x2 += changeX2 * 2;
        y2 += changeY2 * 2;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        change();
        change2();
        repaint();
    }

    private class KeyListener extends KeyAdapter {

        @Override
        public void keyPressed(KeyEvent e) {
            int d = 5;
            if (e.getKeyCode() == KeyEvent.VK_UP) {
                if (y - d >= 0) {
                    y -= d;
                    y1 -= d;
                    y2 -= d;
                }
            }
            if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                if (y + 100 + d <= getHeight()) {
                    y += d;
                    y1 += d;
                    y2 += d;
                }
            }
            if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                if (x - d >= 0) {
                    x -= d;
                    x1 -= d;
                    x2 -= d;
                }
            }
            if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                if (x + 100 + d <= getWidth()) {
                    x += d;
                    x1 += d;
                    x2 += d;
                }
            }
        }
    }
}

这篇关于跳绳用Java动画撕裂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆