【问题标题】:How do I properly move drawn Polygon in Swing如何在 Swing 中正确移动绘制的多边形
【发布时间】:2019-03-05 22:07:25
【问题描述】:

我目前正在开发一款 2D 游戏,这将是一个谜题。我把所有东西都设置好了,把我所有的部分都添加到了我的板上(称为View)并且它们都正确对齐了。

我的下一步是通过MouseEvent#mousePressed 选择一块,以便能够使用KeyEvent#keyPressed 的箭头键移动它。我目前遇到的问题是,每当我移动或调整窗口大小时,我的作品都会自行重新绘制。如果我点击一个块并想要移动它,那么其他块也会移动(在某种程度上,它们不应该移动,因为一步大约等于 100 像素)。

如果有人能告诉我我的问题出在哪里并给我一些建议,我将不胜感激。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Puzzle {

    public static void main(String[] args) {
    SwingUtilities.invokeLater(Puzzle::new);
    }

    public Puzzle() {
    JFrame frame = new JFrame("Puzzle");
    frame.setSize(400, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    View view = new View();
    view.createPieces();
    frame.setContentPane(view);
    view.setFocusable(true);

    MouseAdapterMod listener = new MouseAdapterMod(view);
    view.addMouseListener(listener);
    view.addKeyListener(listener);

    frame.setVisible(true);
    }
}

class View extends JPanel {

    final List<Piece> pieces = new ArrayList<>();

    public View() {

    }

    void createPieces() {
    Piece topLeft = new Piece(100, 100, 0, Color.YELLOW);
    pieces.add(topLeft);
    }

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

    Graphics2D gc = (Graphics2D) g;
    for (Piece needle : pieces) {
        needle.translate(needle.getLocation().x, needle.getLocation().y);
        gc.setColor(needle.color);
        gc.fill(needle);
        gc.draw(needle);
    }
    }

}

class Piece extends Polygon {

    int x;
    int y;
    final Color color;
    Point location;

    Piece(int x, int y, int type, Color color) {
    this.x = x;
    this.y = y;
    this.color = color;
    this.location = new Point(x, y);

    int[] arrX = new int[] { 0, 100, 100, -100, -100, 0 };;
    int[] arrY = new int[] { 0, 0, -100, -100, 100, 100 };

    for (int drawIndex = 0; drawIndex < arrX.length; drawIndex++) {
        addPoint(arrX[drawIndex], arrY[drawIndex]);
    }
    }

    Point getLocation() {
    return location;
    }

    void setLocation(Point location) {
    this.location = location;
    }
}

class MouseAdapterMod implements MouseListener, KeyListener {

    final View view;
    Polygon current;

    public MouseAdapterMod(View view) {
    this.view = view;
    }

    @Override
    public void mousePressed(MouseEvent e) {
    for (Piece piece : view.pieces) {
        if (piece.contains(e.getX(), e.getY())) {
        current = piece;
        System.out.println(current);
        }
    }
    }

    @Override
    public void keyPressed(KeyEvent e) {
    switch (e.getKeyCode()) {
    case KeyEvent.VK_UP:
        current.translate(0, -100);
        view.repaint();
        break;
    case KeyEvent.VK_DOWN:
        current.translate(0, +100);
        view.repaint();
        break;
    case KeyEvent.VK_LEFT:
        current.translate(-100, 0);
        view.repaint();
        break;
    case KeyEvent.VK_RIGHT:
        current.translate(+100, 0);
        view.repaint();
        break;
    }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub
    }

    @Override
    public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub

    }

    @Override
    public void mouseClicked(MouseEvent e) {
    // TODO Auto-generated method stub

    }

    @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

    }
}

(抱歉缩进,stackoverflow 搞砸了)

编辑: 但问题是,最终我想使用Piece#setLocation 移动我的作品以始终跟踪它们当前的 x/y 坐标。我想,我需要在我的画中调用Piece#getLocation 来根据位置绘制它们,但我不知道如何。使用 Piece#setLocation 实际上什么也没做。

【问题讨论】:

  • 问题是在您的paintComponent 方法中,您每次绘制时都将当前x 和y 转换为增量。如果您删除 needle.translate 行,您将看到移动将按预期进行,但您需要重新设置起始设置
  • @Kudu2 删除translate(...) 的问题是它们不会被放置在正确的位置。我解决了这个翻译它,在绘画之前。但问题是,最终我想使用Piece#setLocation 移动我的作品以始终跟踪它们当前的 x/y 坐标。我想,我需要在我的绘画中调用Piece#getLocation 来根据位置绘制它们,但我不知道如何。
  • 好吧,您基本上忽略了我上一个问题的建议。我只是说你为每件作品创建了一个独特的多边形,然后你将多边形翻译到它在板上的起始位置。因此,现在当您移动 Piece 时,您只需再次平移 Polygon。通过尝试扩展 Polygon 并跟踪位置,您使您的代码变得过于复杂。只需使用 translate(...) 方法更改其位置,Graphics.draw(...) 将完成剩下的工作。
  • 另外,当您提出问题时,请发布正确的minimal reproducible example。你的问题是关于移动一块。您不需要 5 件来测试它,也不需要 5 种不同类型的件。所有这些代码都与问题无关,并且混淆了逻辑。保持代码简单并与问题直接相关。
  • @camickr 我没有忽略你的建议。问题是,当一块的位置发生变化时,我需要调用一个方法(我仍然需要实现),因此我创建了一个继承自Polygon 的类来实际跟踪每块的位置。一旦位置发生变化,我没有想到任何其他方法来调用方法。将随时将我的代码更新为 MCV。

标签: java swing listener polygon


【解决方案1】:

如果您从 this question 恢复到您的 Piece 代码,您可以通过以下方式移动棋子:

@Override
public void keyPressed(KeyEvent e) {
    switch (e.getKeyCode()) {
    case KeyEvent.VK_UP:
        view.translatePiece(0, -100);
        break;
    case KeyEvent.VK_DOWN:
        view.translatePiece(0, +100);
        break;
    case KeyEvent.VK_LEFT:
        view.translatePiece(-100, 0);
        break;
    case KeyEvent.VK_RIGHT:
        view.translatePiece(+100, 0);
        break;
    }
}

并添加到您的视图中:

void translatePiece(int dx, int dy) {
    if (current != null) {
        current.x += dx;
        current.y += dy;
        repaint();
    }
}

if (current != null) { ... } 测试将防止您的应用程序崩溃,如果您在单击某个片段之前按下箭头键,它目前就是这样做的。

【讨论】:

    【解决方案2】:

    您可以不平移多边形,而是平移位置并将其用于绘画:

    keyPressed 中,替换current.translate 以转换位置而不是整个多边形(例如,您可以覆盖Piece#translate 以调用current.getLocation().translate)。

    View#paintComponent 中,替换:

    needle.translate(needle.getLocation().x, needle.getLocation().y);
    

    gc.translate(needle.getLocation().x, needle.getLocation().y);
    

    并添加

    gc.translate(-needle.getLocation().x, -needle.getLocation().y);
    

    在你的 for 循环结束时。 这会将整个Graphics2D 转换为绘制多边形,然后将其还原。

    【讨论】:

    • 好吧,这个解决方案将所有部分放在正确的位置,但是使用MouseEvent#mousePressed 选择其中一个部分将不起作用,因为它会像所有部分都在同一个位置一样(所以点击左上角的部分将获得每一部分,而不仅仅是所需的左上角部分)。
    • 将鼠标位置平移到每块位置的对面来解决这个问题
    • Point mouse = e.getPoint(); mouse.translate(-needle.getLocation().x, -needle.getLocation().y); if (piece.contains(mouse)) {... 在 for 循环中
    • 在绘制 Piece 时执行 translate(...),然后尝试使用与该位置相反的位置调整鼠标点,因此 `contains(...) 方法工作是额外的工作,并且整个过程比较混乱。
    猜你喜欢
    • 2020-02-09
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2014-04-02
    相关资源
    最近更新 更多