如何解决按下新键后如何在JFrame上保留KeyListener图像
我对Java完全陌生,我的项目是用键盘制作明信片生成器。 我现在的问题是,当按下新的键时,我不知道如何使图像停留在帧中。我确定我需要一个ArrayList,但是我不知道它在代码中的位置。 我将不胜感激:)
public class Funktionier extends Canvas implements KeyListener {
private static final long serialVersionUID = 2576012469492443014L;
public JFrame frame;
private Image []pngs;
private int currentimage;
private Random random;
private int x;
private int y;
public Funktionier(int width,int height)
{
pngs = new Image[26];
for (int i=0; i<26; i++) {
try {
pngs[i] = ImageIO.read(new File("./res/JAVA-"+(char) ('A'+i)+".png"));
} catch (IOException e) {
e.printstacktrace();
}
}
frame = new JFrame ();
JTextField field = new JTextField (30);
field.setBounds(219,10,437,20);
frame.add(field);
frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Deine Karte");
frame.setResizable(false);
frame.setSize(width,height);
field.addKeyListener(this);
frame.add(this);
this.addKeyListener(this);
this.requestFocus();
frame.setVisible(true);
//currentimage = 0;
random = new Random ();
randomXY ();
}
public static void main (String[] args) {
new Funktionier (874,620);
}
public void randomXY () {
x= random.nextInt(getWidth()-130);
y= random.nextInt(getHeight()-110);
}
public void paint (Graphics g)
{
g.drawImage(pngs[currentimage],x,y,pngs[currentimage].getWidth(null),pngs[currentimage].getHeight(null),null);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keypressed(KeyEvent e) {
}
@Override
public void keyreleased(KeyEvent e) {
if(e.getKeyChar() < 'a' || e.getKeyChar() > 'z') return;
currentimage= e.getKeyChar()-'a' ;
randomXY ();
repaint ();
}
}
解决方法
您应该使用JPanel
而不是Canvas
,因此使类Funktionier
扩展JPanel
而不是Canvas
。
您应该覆盖方法paintComponent()
,而不是方法paint()
。在覆盖的paintComponent()
方法中,您需要做的第一件事就是调用super.paintComponent()
。
每次调用paintComponent()
时,您都需要绘制所有内容,因为每次调用paintComponent()
时,您都会以空白JPanel
开始。因此,不要只绘制“当前”图像。还将绘制的所有图像绘制到当前图像。
同时参考Painting in AWT and Swing和Performing Custom Painting
编辑
代码后的解释。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
public class Funktionier extends JPanel implements DocumentListener,Runnable {
private static final long serialVersionUID = 4909941254467865823L;
private static final Image[] PNGS;
private JFrame frame;
private List<ImagLocn> imagesToDraw;
private Random rand;
static {
PNGS = new Image[26];
for (int i = 0; i < 26; i++) {
try {
PNGS[i] = ImageIO.read(new File("JAVA-" + (char) ('A' + i) + ".png"));
}
catch (IOException xIo) {
throw new RuntimeException(xIo);
}
}
}
public Funktionier(int width,int height) {
imagesToDraw = new ArrayList<>();
rand = new Random();
setPreferredSize(new Dimension(width,height));
}
@Override // javax.swing.event.DocumentListener
public void insertUpdate(DocumentEvent docEvent) {
if (docEvent.getLength() > 0) {
Document doc = docEvent.getDocument();
int length = doc.getLength();
try {
String text = doc.getText(0,length);
text = text.strip();
length = text.length();
String lastLetter = text.substring(length - 1,length);
int index = lastLetter.charAt(0) - 'A';
if (index >= 0 && index < PNGS.length) {
imagesToDraw.add(new ImagLocn(PNGS[index],rand.nextInt(getWidth()),rand.nextInt(getHeight())));
repaint();
}
}
catch (BadLocationException xBadLocation) {
throw new RuntimeException(xBadLocation);
}
}
}
@Override // javax.swing.event.DocumentListener
public void removeUpdate(DocumentEvent docEvent) {
// Do nothing.
}
@Override // javax.swing.event.DocumentListener
public void changedUpdate(DocumentEvent docEvent) {
// Do nothing.
}
@Override // java.lang.Runnable
public void run() {
showGui();
}
@Override // javax.swing.JComponent
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (ImagLocn il : imagesToDraw) {
g.drawImage(il.getImage(),il.getX(),il.getY(),null);
}
}
private JPanel createTextFieldPanel() {
JPanel textFieldPanel = new JPanel();
JTextField field = new JTextField(30);
Document doc = field.getDocument();
doc.addDocumentListener(this);
if (doc instanceof AbstractDocument) {
AbstractDocument absDoc = (AbstractDocument) doc;
absDoc.setDocumentFilter(new DocuFltr());
}
textFieldPanel.add(field);
return textFieldPanel;
}
private void showGui() {
frame = new JFrame("Deine Karte");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createTextFieldPanel(),BorderLayout.PAGE_START);
frame.add(this,BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Funktionier(500,500));
}
}
class DocuFltr extends DocumentFilter {
@Override
public void insertString(FilterBypass fb,int offset,String string,AttributeSet attr) throws BadLocationException {
if (string.matches("^[A-Za-z]+$")) {
fb.insertString(offset,string.toUpperCase(),attr);
}
}
@Override
public void replace(FilterBypass fb,int length,String text,AttributeSet attrs) throws BadLocationException {
if (text.matches("^[A-Za-z]+$")) {
fb.replace(offset,length,text.toUpperCase(),attrs);
}
}
}
class ImagLocn {
private Image image;
private int x;
private int y;
public ImagLocn(Image img,int anX,int aY) {
image = img;
x = anX;
y = aY;
}
public Image getImage() {
return image;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
这是运行上述代码时的外观。
- 请参阅Laying Out Components Within a Container。请勿使用
setBounds()
将组件放置在屏幕上。使用布局管理器。JFrame
的内容窗格的默认布局管理器是BorderLayout
。 - 我使用document filter来确保只能将字母输入
JTextField
中。文档过滤器还将小写字母转换为大写字母。 - 我实现了document listener而不是
KeyListener
。在文档监听器中,每次在JTextField
中输入另一个字母时,我都会在需要绘制的图像列表中添加另一个图像。 - 就像我在原始答案中所写的那样,我重写了方法
paintComponent()
,并始终绘制图像的整个列表。 - 我将所有PNG图片放置在工作目录中,即
System.getProperty("user.dir")
返回的值。我这样做只是为了让自己更轻松。您可以将它们放在您喜欢的任何位置。只需确保在代码中使用正确的文件路径即可。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。