JFrame 没有按预期工作

JFrame not working as expected

我正在制作一个小程序,让您可以使用 JPanel 上的箭头键画线。但是我遇到了两个问题。谁能解释我的代码有什么问题?

  1. 即使添加的第一个点是宽度的一半和高度的一半,绘图也不会从 JPanel 的中心开始。
  2. 线条只绘制一段,并重置到原点,无法绘制。

代码如下:

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

public class MyFrame extends JFrame{
    public MyFrame(){
        super("Drawing");
        add(new LinePanel());
    }

    public static void main(String[] args){
        MyFrame f = new MyFrame();
        f.setSize(500, 500);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(MyFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    class LinePanel extends JPanel{
        private Polygon points = new Polygon(new int[]{getWidth() / 2}, new int[]{getHeight() / 2}, 1);

        public LinePanel(){
            setFocusable(true);
            addKeyListener(new KeyAdapter(){
                @Override 
                public void keyPressed(KeyEvent e){
                    if(e.getKeyCode() == KeyEvent.VK_UP){
                        points.addPoint(points.xpoints[points.xpoints.length - 1], points.ypoints[points.ypoints.length - 1] - 10);
                    }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
                        points.addPoint(points.xpoints[points.xpoints.length - 1], points.ypoints[points.ypoints.length - 1] + 10);
                    }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
                        points.addPoint(points.xpoints[points.xpoints.length - 1] + 10, points.ypoints[points.ypoints.length - 1]);
                    }else if(e.getKeyCode() == KeyEvent.VK_LEFT){
                        points.addPoint(points.xpoints[points.xpoints.length - 1] - 10, points.ypoints[points.ypoints.length - 1]);
                    }
                    repaint();
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g){
            super.paintComponent(g);
            g.drawPolyline(points.xpoints, points.ypoints, points.npoints);
        }
    }
}

尝试将 Graphics 对象转换为 Graphics2D

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.translate((int) getWidth()/2, (int) getHeight()/2); // move to center
    g.drawPolyline(points.xpoints, points.ypoints, points.npoints);
}

我对你的代码做了一些修改。

  1. 我通过调用 SwingUtilities invokeLater 方法启动了 Java Swing 应用程序。您应该始终以这种方式启动 Java Swing 应用程序。

  2. 我用的是JFrame。您不应扩展 Swing 组件或任何 Java class,除非您重写其中一种方法。

  3. 我使用了按键绑定,这样我就可以使用 WASD 键和方向键。 WASD键对左撇子比较方便

  4. 我对每个键都使用了抽象操作,以将控制器逻辑与视图逻辑分开。

这是工作代码:

package com.ggl.testing;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class MyFrame implements Runnable {

    private JFrame frame;

    @Override
    public void run() {
        frame = new JFrame("Drawing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        LinePanel linePanel = new LinePanel();
        setKeyBindings(linePanel);
        frame.add(linePanel);

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

    private void setKeyBindings(LinePanel linePanel) {
        InputMap inputMap = linePanel
                .getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
        inputMap.put(KeyStroke.getKeyStroke("W"), "up arrow");
        inputMap.put(KeyStroke.getKeyStroke("S"), "down arrow");
        inputMap.put(KeyStroke.getKeyStroke("A"), "left arrow");
        inputMap.put(KeyStroke.getKeyStroke("D"), "right arrow");

        inputMap.put(KeyStroke.getKeyStroke("UP"), "up arrow");
        inputMap.put(KeyStroke.getKeyStroke("DOWN"), "down arrow");
        inputMap.put(KeyStroke.getKeyStroke("LEFT"), "left arrow");
        inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "right arrow");

        inputMap = linePanel.getInputMap(JPanel.WHEN_FOCUSED);
        inputMap.put(KeyStroke.getKeyStroke("UP"), "up arrow");
        inputMap.put(KeyStroke.getKeyStroke("DOWN"), "down arrow");
        inputMap.put(KeyStroke.getKeyStroke("LEFT"), "left arrow");
        inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "right arrow");

        linePanel.getActionMap().put("up arrow", new UpArrowAction(linePanel));
        linePanel.getActionMap().put("down arrow",
                new DownArrowAction(linePanel));
        linePanel.getActionMap().put("left arrow",
                new LeftArrowAction(linePanel));
        linePanel.getActionMap().put("right arrow",
                new RightArrowAction(linePanel));
    }

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

    public class LinePanel extends JPanel {

        private static final long serialVersionUID = 2504617322590404776L;

        private Point lastPoint;

        private Polygon points;

        public LinePanel() {
            this.setPreferredSize(new Dimension(400, 400));
            this.lastPoint = new Point(200, 200);
            this.points = new Polygon();
            this.points.addPoint(200, 200);
        }

        public void addPoint(int x, int y) {
            lastPoint = new Point(x, y);
            points.addPoint(x, y);
        }

        public Point getPreviousPoint() {
            return lastPoint;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawPolyline(points.xpoints, points.ypoints, points.npoints);
        }
    }

    public class UpArrowAction extends AbstractAction {

        private static final long serialVersionUID = 8463453082541763265L;

        private LinePanel linePanel;

        public UpArrowAction(LinePanel linePanel) {
            this.linePanel = linePanel;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            Point p = linePanel.getPreviousPoint();
            p.y -= 10;
            linePanel.addPoint(p.x, p.y);
            linePanel.repaint();
        }

    }

    public class DownArrowAction extends AbstractAction {

        private static final long serialVersionUID = 3619846728122990617L;

        private LinePanel linePanel;

        public DownArrowAction(LinePanel linePanel) {
            this.linePanel = linePanel;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            Point p = linePanel.getPreviousPoint();
            p.y += 10;
            linePanel.addPoint(p.x, p.y);
            linePanel.repaint();
        }

    }

    public class LeftArrowAction extends AbstractAction {

        private static final long serialVersionUID = -2772213334907267331L;

        private LinePanel linePanel;

        public LeftArrowAction(LinePanel linePanel) {
            this.linePanel = linePanel;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            Point p = linePanel.getPreviousPoint();
            p.x -= 10;
            linePanel.addPoint(p.x, p.y);
            linePanel.repaint();
        }

    }

    public class RightArrowAction extends AbstractAction {

        private static final long serialVersionUID = 8463453082541763265L;

        private LinePanel linePanel;

        public RightArrowAction(LinePanel linePanel) {
            this.linePanel = linePanel;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            Point p = linePanel.getPreviousPoint();
            p.x += 10;
            linePanel.addPoint(p.x, p.y);
            linePanel.repaint();
        }

    }
}