栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

无法重绘我的JFrame / JPanel

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

无法重绘我的JFrame / JPanel

让我们从显而易见的…开始。

这是有问题的…

@Overridepublic void paintComponent(Graphics g) {    g.setColor(Color.GREEN);    g.fillOval(x, y, 15, 15);}@Overridepublic void paint(Graphics g) {    dbImage = createImage(getWidth(), getHeight());    dbg = dbImage.getGraphics();    paintComponent(dbg);    g.drawImage(dbImage, 0, 0, this);}

现在已经不需要在Swing组件中实现双缓冲了。另外,通过不将paint方法称为super方法,您正在破坏绘画合同

整个事情应该是…

@Overrideprotected void paintComponent(Graphics g) {    super.paintComponent(g);    g.setColor(Color.GREEN);    g.fillOval(x, y, 15, 15);}

有关更多详细信息,请参见AWT中的绘画和摇摆和执行自定义绘画。

KeyListener
因存在问题而众所周知。仅当注册到的组件可操作并且具有键盘焦点时,它才会引发键事件。
JPanel
默认情况下,A
不可聚焦。在尝试并使其具有针对性(让您非常失望)之前,您应该改用Key Bindings
API,该API旨在克服以下限制:
KeyListener

作为一个基本的例子…

import java.awt.Color;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.Graphics;import java.awt.event.ActionEvent;import java.awt.event.KeyEvent;import javax.swing.AbstractAction;import javax.swing.Action;import javax.swing.ActionMap;import javax.swing.InputMap;import javax.swing.Jframe;import javax.swing.JPanel;import javax.swing.KeyStroke;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;public class Main {    public static void main(String[] args) {        new Main();    }    public Main() {        EventQueue.invokeLater(new Runnable() { @Override public void run() {     try {         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {         ex.printStackTrace();     }     Jframe frame = new Jframe("Testing");     frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);     frame.add(new Game());     frame.pack();     frame.setLocationRelativeTo(null);     frame.setVisible(true); }        });    }    public class Game extends JPanel {        int x, y, xCoord, yCoord;        public Game() { x = 250; y = 250; addKeyBinding(KeyEvent.VK_LEFT, "move.left", new MoveAction(this, -1, 0)); addKeyBinding(KeyEvent.VK_RIGHT, "move.right", new MoveAction(this, 1, 0)); addKeyBinding(KeyEvent.VK_UP, "move.up", new MoveAction(this, 0, -1)); addKeyBinding(KeyEvent.VK_DOWN, "move.down", new MoveAction(this, 0, 1));        }        protected void addKeyBinding(int keyCode, String name, Action action) { addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);        }        protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) { InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap actionMap = getActionMap(); inputMap.put(keyStroke, name); actionMap.put(name, action);        }        public void changeCoord() { x += xCoord; y += yCoord; if (x <= 20) {     x = 20; } if (x >= 480) {     x = 480; } if (y <= 40) {     y = 40; } if (y >= 480) {     y = 480; } repaint();        }        public void setXCoord(int xcoord) { xCoord = xcoord; changeCoord();        }        public void setYCoord(int ycoord) { yCoord = ycoord; changeCoord();        }        @Override        public Dimension getPreferredSize() { return new Dimension(480, 480);        }        @Override        protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.GREEN); g.fillOval(x, y, 15, 15);        }    }    public class MoveAction extends AbstractAction {        private int xDelta;        private int yDelta;        // I'd prefer an interface with just the "move" methods, but        // that's more time I don't have        private Game game;        public MoveAction(Game game, int xDelta, int yDelta) { this.xDelta = xDelta; this.yDelta = yDelta; this.game = game;        }        @Override        public void actionPerformed(ActionEvent e) { game.setXCoord(xDelta); game.setYCoord(yDelta);        }    }}

但是,等等,那不完全是您想要的(相信我,我是互联网上的糊涂人;)),一个更好的例子可能是…

import java.awt.Color;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 java.util.HashSet;import java.util.Set;import javax.swing.AbstractAction;import javax.swing.Action;import javax.swing.ActionMap;import javax.swing.InputMap;import javax.swing.Jframe;import javax.swing.JPanel;import javax.swing.KeyStroke;import javax.swing.Timer;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;public class Main {    public static void main(String[] args) {        new Main();    }    public Main() {        EventQueue.invokeLater(new Runnable() { @Override public void run() {     try {         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {         ex.printStackTrace();     }     Jframe frame = new Jframe("Testing");     frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);     frame.add(new Game());     frame.pack();     frame.setLocationRelativeTo(null);     frame.setVisible(true); }        });    }    public enum Direction {        UP,        LEFT,        DOWN,        RIGHT;    }    public class Game extends JPanel {        int x, y, xCoord, yCoord;        private Set<Direction> movement;        public Game() { x = 250; y = 250; movement = new HashSet<>(4); addKeyPressedBinding(KeyEvent.VK_LEFT, "left.pressed", new MoveAction(movement, Direction.LEFT, true)); addKeyReleasedBinding(KeyEvent.VK_LEFT, "left.released", new MoveAction(movement, Direction.LEFT, false)); addKeyPressedBinding(KeyEvent.VK_RIGHT, "right.pressed", new MoveAction(movement, Direction.RIGHT, true)); addKeyReleasedBinding(KeyEvent.VK_RIGHT, "right.released", new MoveAction(movement, Direction.RIGHT, false)); addKeyPressedBinding(KeyEvent.VK_UP, "up.pressed", new MoveAction(movement, Direction.UP, true)); addKeyReleasedBinding(KeyEvent.VK_UP, "up.released", new MoveAction(movement, Direction.UP, false)); addKeyPressedBinding(KeyEvent.VK_DOWN, "down.pressed", new MoveAction(movement, Direction.DOWN, true)); addKeyReleasedBinding(KeyEvent.VK_DOWN, "down.released", new MoveAction(movement, Direction.DOWN, false)); Timer timer = new Timer(40, new ActionListener() {     @Override     public void actionPerformed(ActionEvent e) {         changeCoord();     } }); timer.start();        }        protected void addKeyBinding(int keyCode, String name, Action action) { addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);        }        protected void addKeyPressedBinding(int keyCode, String name, Action action) { addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);        }        protected void addKeyReleasedBinding(int keyCode, String name, Action action) { addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);        }        protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) { InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap actionMap = getActionMap(); inputMap.put(keyStroke, name); actionMap.put(name, action);        }        public void changeCoord() { if (movement.contains(Direction.UP)) {     y--; } else if (movement.contains(Direction.DOWN)) {     y++; } if (movement.contains(Direction.LEFT)) {     x--; } else if (movement.contains(Direction.RIGHT)) {     x++; } x += xCoord; y += yCoord; if (x <= 20) {     x = 20; } if (x >= 480) {     x = 480; } if (y <= 40) {     y = 40; } if (y >= 480) {     y = 480; } repaint();        }        public void setXCoord(int xcoord) { xCoord = xcoord; changeCoord();        }        public void setYCoord(int ycoord) { yCoord = ycoord; changeCoord();        }        @Override        public Dimension getPreferredSize() { return new Dimension(480, 480);        }        @Override        protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.GREEN); g.fillOval(x, y, 15, 15);        }    }    public class MoveAction extends AbstractAction {        private Set<Direction> movement;        private Direction direction;        private boolean pressed;        public MoveAction(Set<Direction> movement, Direction direction, boolean pressed) { this.movement = movement; this.direction = direction; this.pressed = pressed;        }        @Override        public void actionPerformed(ActionEvent e) { if (pressed) {     movement.add(direction); } else {     movement.remove(direction); }        }    }}

这样做只是在按下某个键时激活一个标志(并在释放它时将其禁用),然后在Swing中

Timer
,我们检查哪些键是“活动的”并更新球的位置。

这样做是消除了第一次按下并按住某个键时由操作系统引起的键“口吃”。在第一个键和重复的键事件之间插入一个延迟。相反,我们只是根据需要打开和关闭该标志。

它还允许您同时在两个方向(水平和垂直)上移动

了解Swing中的并发性以及如何使用Swing计时器以了解更多详细信息



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/508037.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号