JFrame 没有按预期工作
JFrame not working as expected
我正在制作一个小程序,让您可以使用 JPanel
上的箭头键画线。但是我遇到了两个问题。谁能解释我的代码有什么问题?
- 即使添加的第一个点是宽度的一半和高度的一半,绘图也不会从
JPanel
的中心开始。
- 线条只绘制一段,并重置到原点,无法绘制。
代码如下:
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);
}
我对你的代码做了一些修改。
我通过调用 SwingUtilities invokeLater 方法启动了 Java Swing 应用程序。您应该始终以这种方式启动 Java Swing 应用程序。
我用的是JFrame。您不应扩展 Swing 组件或任何 Java class,除非您重写其中一种方法。
我使用了按键绑定,这样我就可以使用 WASD 键和方向键。 WASD键对左撇子比较方便
我对每个键都使用了抽象操作,以将控制器逻辑与视图逻辑分开。
这是工作代码:
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();
}
}
}
我正在制作一个小程序,让您可以使用 JPanel
上的箭头键画线。但是我遇到了两个问题。谁能解释我的代码有什么问题?
- 即使添加的第一个点是宽度的一半和高度的一半,绘图也不会从
JPanel
的中心开始。 - 线条只绘制一段,并重置到原点,无法绘制。
代码如下:
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);
}
我对你的代码做了一些修改。
我通过调用 SwingUtilities invokeLater 方法启动了 Java Swing 应用程序。您应该始终以这种方式启动 Java Swing 应用程序。
我用的是JFrame。您不应扩展 Swing 组件或任何 Java class,除非您重写其中一种方法。
我使用了按键绑定,这样我就可以使用 WASD 键和方向键。 WASD键对左撇子比较方便
我对每个键都使用了抽象操作,以将控制器逻辑与视图逻辑分开。
这是工作代码:
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();
}
}
}