【问题标题】:Why does it draw lines in the wrong place?为什么它在错误的地方画线?
【发布时间】:2012-11-13 07:55:17
【问题描述】:

我对此有疑问...当我画一条线时,角色跟随我画的线,但计算机在其他地方画了一条线:

那么有人知道发生了什么吗?
My code:

@SuppressWarnings({"serial","rawtypes","unchecked"})
public class someGame extends JFrame implements MouseListener, KeyListener{

ArrayList lines = new ArrayList();
Point2D.Double start;
final Color BROWN = new Color(156,93,82);
Slider thread;
Rectangle cow = null;
boolean drawGuy = false;
public someGame(){
    super("Some Game");
    setSize(700,700);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    addMouseListener(this);
    addKeyListener(this);
}

public void paint(Graphics g){
    super.paint(g);
    g.setColor(Color.black);
    for(int i = 0; i < lines.size(); i++){
        Line2D.Double temp = (Line2D.Double) lines.get(i);
        int x1 = Integer.parseInt(""+Math.round(temp.getX1()));
        int x2 = Integer.parseInt(""+Math.round(temp.getX2()));
        int y1 = Integer.parseInt(""+Math.round(temp.getY1()));
        int y2 = Integer.parseInt(""+Math.round(temp.getY2()));

        g.drawLine(x1,x2,y1,y2);
    }

    if(drawGuy){
        try{
            URL url = this.getClass().getResource("resources/img/world/char.png");
            Image image = Toolkit.getDefaultToolkit().getImage(url);
            g.drawImage(image, cow.x, cow.y, this);
        } catch(Exception exc){}
    }
}

public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){
    start = new Point2D.Double(e.getX(),e.getY());
}
public void mouseReleased(MouseEvent e){
    Point2D.Double end = new Point2D.Double(e.getX(),e.getY());
    lines.add(new Line2D.Double(start,end));
    repaint();
}
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){
    if(e.getKeyChar()=='p'||e.getKeyChar()=='P'){
        thread = new Slider();
        thread.start();
        thread.action(true);
    }
    if(e.getKeyChar()=='q'||e.getKeyChar()=='Q'){
        thread.action(false);
        drawGuy = false;
        thread = null;
    }
}
private class Slider extends Thread{
    double velocity, gravity;
    boolean go = false;
    public void run(){
        if(go){
            initGuy();
            velocity = 0;
            gravity = 1;
        }
        while(go){
            try{
                Line2D.Double lineTaken = null;
                boolean onLine = false;
                int firstOnLine = -1;
                for(int i = lines.size()-1; i>=0; i--){
                    Line2D.Double temp = (Line2D.Double) lines.get(i);
                    if(temp.intersects(cow.x,cow.y,50,50)){
                        lineTaken = temp;
                        onLine = true;
                        if(firstOnLine!=i){
                            firstOnLine = i;
                            gravity = 0;
                        }
                        break;
                    }
                }
                if(onLine){
                    double grav = (lineTaken.y2-lineTaken.y1)/50;
                    double vlct = (lineTaken.x2-lineTaken.x1)/100;
                    if(velocity<5)velocity+=vlct;
                    if(gravity<2.5)gravity+=grav;
                }
                else{
                    gravity+=.2;
                }
                cow.x+=velocity;
                cow.y+=gravity;

                Thread.sleep(75);
                repaint();
            }catch(Exception e){break;}
        }
    }
    public void action(boolean b){
        go = b;
    }
    public void initGuy(){
        Line2D.Double firstLine = (Line2D.Double) lines.get(0);
        int x = Integer.parseInt(""+Math.round(firstLine.x1));
        int y = Integer.parseInt(""+Math.round(firstLine.y1));
        cow = new Rectangle(x+30,y-20,30,30);
        drawGuy = true;
    }
}

抱歉,代码很大,但我不知道出了什么问题... 非常感谢任何回答的人:)
...是的,主要方法是someGame g = new someGame();

【问题讨论】:

  • @DavidKroukamp o_o 我真的不知道那些东西,因为我不是很先进,而且我正在写一本书
  • “加上我正在做一本书”买一本更好的书,这本书听起来对你没有任何好处
  • +1 代表sscce;考虑 UIManager.getIcon() 作为占位符图片。
  • @Itachi 如果每个人都这么说,那么我建议该声明有分量,如果您的问题是由过时或简单编写错误的资源引起的,您应该更改它,它对你没有任何好处
  • @Itachi 如果这本书已经引导您发布充满不良做法的代码,那么不建议这样做。恕我直言,导致您误入歧途的来源是问题的一部分,当然,您可以选择忽略那些在您面前的人的建议。

标签: java swing keylistener java-2d mouselistener


【解决方案1】:

1) 你不应该在没有充分理由的情况下使用paint(..)。而是扩展JPanel 类并覆盖paintComponent(...)

2) 除非添加功能,否则不要扩展 JFrame

3) 不要忘记所有 Swing 组件的创建和操作都应该在 EDT 上完成 - Event Dispatch Thread

4) Java 命名约定是 CamelCase,类名的每个新词都应以大写开头,即SomeGame

5) 不要使用setSize 而是覆盖组件getPreferredSize 并返回所需的大小,而不是在设置可见之前在JFrame 上调用pack()

6) 使用Keybindings 而不是KeyListener

7) 使用MouseAdapter 而不是MouseListener

8) 不要扩展Threadrather implement Runnable 并创建start() 方法来启动可运行类中的线程(我在下面的代码中没有实现)

9) 执行长时间运行的任务(如加载图像)或执行任何其他工作不是一个好主意,除了在绘制方法中绘制对象的必要条件之外,您应该在类初始化时或至少在组件绘制方法之外加载图片等。 (我没有在下面的代码中实现这个)

10) 关于线条绘制不正确的最大问题是:

g.drawLine(x1,x2,y1,y2);

应该是drawLine(int x1,int y1,int x2,int y2):

g.drawLine(x1,y1,x2,y2);

代码如下(暂时没时间解释希望大家看懂):

我添加了一些额外的东西,例如投射到Graphics2D 并使用RenderHints 进行抗锯齿,正如@MadProgrammer 在下面的评论中所建议的那样。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.net.URL;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class SomeGame {

    public SomeGame() {
        JFrame frame = new JFrame("Some Game");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DrawPanel dp = new DrawPanel();
        frame.add(dp);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SomeGame();
            }
        });

    }
}

class DrawPanel extends JPanel {

    ArrayList lines = new ArrayList();
    Point2D.Double start;
    final Color BROWN = new Color(156, 93, 82);
    Slider thread;
    Rectangle cow = null;
    boolean drawGuy = false;

    public DrawPanel() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent me) {
                super.mouseReleased(me);
                Point2D.Double end = new Point2D.Double(me.getX(), me.getY());
                lines.add(new Line2D.Double(start, end));
                repaint();
            }

            @Override
            public void mousePressed(MouseEvent me) {
                super.mousePressed(me);
                start = new Point2D.Double(me.getX(), me.getY());
            }
        });
        setKeyBindings();
    }

    private void setKeyBindings() {
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_P, 0), "P");
        getActionMap().put("P", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                thread = new Slider(DrawPanel.this);
                thread.action(true);
                thread.start();
            }
        });
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "q");
        getActionMap().put("Q", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                thread.action(false);
                drawGuy = false;
                thread = null;
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(700, 700);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        //lets go 2D :)
        Graphics2D g2d = (Graphics2D) g;

        //turn on anti aliasing
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);


        g2d.setColor(Color.black);

        for (int i = 0; i < lines.size(); i++) {
            Line2D.Double temp = (Line2D.Double) lines.get(i);
            int x1 = Integer.parseInt("" + Math.round(temp.getX1()));
            int x2 = Integer.parseInt("" + Math.round(temp.getX2()));
            int y1 = Integer.parseInt("" + Math.round(temp.getY1()));
            int y2 = Integer.parseInt("" + Math.round(temp.getY2()));

            g2d.drawLine(x1, y1, x2, y2);
        }

        if (drawGuy) {
            try {
                URL url = this.getClass().getResource("resources/img/world/char.png");
                Image image = Toolkit.getDefaultToolkit().getImage(url);
                g.drawImage(image, cow.x, cow.y, this);
            } catch (Exception exc) {
            }
        }
    }

    private class Slider extends Thread {

        double velocity, gravity;
        boolean go = false;
        private final DrawPanel dp;

        private Slider(DrawPanel dp) {
            this.dp = dp;
        }

        public void run() {
            if (go) {
                initGuy();
                velocity = 0;
                gravity = 1;
            }
            while (go) {
                try {
                    Line2D.Double lineTaken = null;
                    boolean onLine = false;
                    int firstOnLine = -1;
                    for (int i = lines.size() - 1; i >= 0; i--) {
                        Line2D.Double temp = (Line2D.Double) lines.get(i);
                        if (temp.intersects(cow.x, cow.y, 50, 50)) {
                            lineTaken = temp;
                            onLine = true;
                            if (firstOnLine != i) {
                                firstOnLine = i;
                                gravity = 0;
                            }
                            break;
                        }
                    }
                    if (onLine) {
                        double grav = (lineTaken.y2 - lineTaken.y1) / 50;
                        double vlct = (lineTaken.x2 - lineTaken.x1) / 100;
                        if (velocity < 5) {
                            velocity += vlct;
                        }
                        if (gravity < 2.5) {
                            gravity += grav;
                        }
                    } else {
                        gravity += .2;
                    }
                    cow.x += velocity;
                    cow.y += gravity;

                    Thread.sleep(75);
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            dp.repaint();
                        }
                    });
                } catch (Exception e) {
                    break;
                }
            }
        }

        public void action(boolean b) {
            go = b;
        }

        public void initGuy() {
            Line2D.Double firstLine = (Line2D.Double) lines.get(0);
            int x = Integer.parseInt("" + Math.round(firstLine.x1));
            int y = Integer.parseInt("" + Math.round(firstLine.y1));
            cow = new Rectangle(x + 30, y - 20, 30, 30);
            drawGuy = true;
        }
    }
}

【讨论】:

  • @ltachi 您可能想阅读一下Performing Custom Painting2D Graphics
  • @MadProgrammer +1 谢谢在我的评论中,但没有在回答中重新发布:O
  • @DavidKroukamp 顺便说一下类名不是 someGame,我只是用 someGame 替换了它吗?
  • @Itachi 一个更适合良好实践的替代品是SomeGame :)
  • @DavidKroukamp 谢谢,顺便说一句,非常感谢......我完全忘记了 (x1,y1,etc) 的事情!!!谢谢!!!!
猜你喜欢
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
  • 2015-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 2013-10-24
相关资源
最近更新 更多