如何从 JFrame 中的用户输入绘制字符串 Java
How do I draw string from user input in a JFrame Java
无法通过搜索功能找到我要找的内容,我可能只是标题表述不当。
无论如何,现在我可以单击我的 JFrame,它会绘制用户在 控制台 中键入的任何内容,当您按下 Enter 时,它会停止句子。
但我想要的是让用户直接在 JFrame 中键入内容,然后在您按下回车键时结束输入。
这是我现在拥有的:
public void drawString(MouseEvent e) throws IOException {
if(textClick==true) {
int xLoc = e.getX();
int yLoc = e.getY();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String accStr;
System.out.println("Enter your Account number: ");
accStr = br.readLine();
g2.drawString(accStr, xLoc, yLoc);
textClick=false;
}
}
因此您单击了 JFrame 上的某处。然后它将显示用户在该位置键入的任何内容,而无需进入控制台并在那里键入。
不要将控制台输入与 Swing GUI 混合使用,因为这会导致线程噩梦。而是通过其他方式获取输入。我自己会使用 JOptionPane.showInputDialog(...)
来获取用户的输入字符串。另外,不要像在 paint 或 paintComponent 方法之外使用 Graphics,因为这是导致 NullPointerException 或其他一些 GUI 失败的原因。而是在 JLabel 或文本组件(如 JTextArea 或 JTextField)中显示文本。
类似于:
public void drawString(MouseEvent e) throws IOException {
if(textClick) { // none of this == true stuff please
int xLoc = e.getX();
int yLoc = e.getY();
String prompt = "Enter your Account Number:";
String input = JOptionPane.showInputDialog(someComponent, prompt);
// !!! no
// g2.drawString(accStr, xLoc, yLoc); // no don't do this
myJLabel.setText(input);
textClick=false;
}
}
如果您绝对必须使用 Graphics 绘制字符串,那么在上面的方法中,设置对象的一个字段,可能类似于 private String textToDraw
,在您的 GUI 上调用 repaint()
,并在您的JPanel 的 protected void paintComponent(Graphics g)
方法绘制文本。
这里有一段代码,将 JTextField 放在鼠标按下的位置,然后在按下回车键或失去焦点时将 JTextField 转换为 JLabel:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class AddingText extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
public AddingText() {
addMouseListener(new MyMouse());
setLayout(null); // one of the few times this may be ok
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private void convertToLabel(final JTextField textField) {
JLabel label = new JLabel(textField.getText());
label.setSize(label.getPreferredSize());
label.setLocation(textField.getLocation());
remove(textField);
add(label);
repaint();
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
final JTextField textField = new JTextField(20);
textField.setSize(textField.getPreferredSize());
textField.setLocation(e.getPoint());
add(textField);
revalidate();
repaint();
textField.requestFocusInWindow();
textField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
convertToLabel((JTextField) e.getComponent());
}
});
textField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
convertToLabel((JTextField) e.getSource());
}
});
}
}
private static void createAndShowGui() {
AddingText mainPanel = new AddingText();
JFrame frame = new JFrame("AddingText");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
尝试二:我通过覆盖 paintComponent 并使用 JOptionPane 直接在 JPanel 中绘制。文本被放置到 Map<Point, String>
中,然后通过遍历此地图在 paintComponent 中绘制此文本。这样我们就避免了可怕的 null
布局。
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.*;
public class AddingText2 extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private Map<Point, String> pointTextMap = new LinkedHashMap<>();
public AddingText2() {
addMouseListener(new MyMouse());
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(getFont().deriveFont(Font.BOLD));
for (Point p : pointTextMap.keySet()) {
String text = pointTextMap.get(p);
g.drawString(text, p.x, p.y);
}
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
String prompt = "Please add text to display";
String input = JOptionPane.showInputDialog(AddingText2.this, prompt);
pointTextMap.put(e.getPoint(), input);
repaint();
}
}
private static void createAndShowGui() {
AddingText2 mainPanel = new AddingText2();
JFrame frame = new JFrame("AddingText2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
如果我理解你的问题,你基本上想要 KeyListener
:
public class MyWindow extends JFrame {
private int x, y;
private String text;
private boolean shouldGetText = false;
private KeyListener keyboard = new KeyAdapter() {
public void keyTyped(KeyEvent evt) {
if(!shouldGetText)
return;
text = text + evt.getChar(); // or evt.getKeyChar()... not sure about the name of this method
}
public void keyPressed(KeyEvent evt) {
if (shouldGetText && evt.getKeyCode() == KeyEvent.VK_ENTER)
shouldGetText = false;
}
}
private MouseListener mouse = new MouseAdapter() {
public void mouseMoved(MouseEvent evt) {
if (shouldGetText)
return;
x = evt.getX();
y = evt.getY();
}
public void mousePressed(MouseEvent evt) {
shouldGetText = true;
text = "";
}
}
public MyWindow() {
addKeyListener(keyboard);
addMouseListener(mouse);
addMouseMotionListene(mouse);
// Do other stuff
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawString(text, x, y);
}
}
无法通过搜索功能找到我要找的内容,我可能只是标题表述不当。
无论如何,现在我可以单击我的 JFrame,它会绘制用户在 控制台 中键入的任何内容,当您按下 Enter 时,它会停止句子。
但我想要的是让用户直接在 JFrame 中键入内容,然后在您按下回车键时结束输入。
这是我现在拥有的:
public void drawString(MouseEvent e) throws IOException {
if(textClick==true) {
int xLoc = e.getX();
int yLoc = e.getY();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String accStr;
System.out.println("Enter your Account number: ");
accStr = br.readLine();
g2.drawString(accStr, xLoc, yLoc);
textClick=false;
}
}
因此您单击了 JFrame 上的某处。然后它将显示用户在该位置键入的任何内容,而无需进入控制台并在那里键入。
不要将控制台输入与 Swing GUI 混合使用,因为这会导致线程噩梦。而是通过其他方式获取输入。我自己会使用 JOptionPane.showInputDialog(...)
来获取用户的输入字符串。另外,不要像在 paint 或 paintComponent 方法之外使用 Graphics,因为这是导致 NullPointerException 或其他一些 GUI 失败的原因。而是在 JLabel 或文本组件(如 JTextArea 或 JTextField)中显示文本。
类似于:
public void drawString(MouseEvent e) throws IOException {
if(textClick) { // none of this == true stuff please
int xLoc = e.getX();
int yLoc = e.getY();
String prompt = "Enter your Account Number:";
String input = JOptionPane.showInputDialog(someComponent, prompt);
// !!! no
// g2.drawString(accStr, xLoc, yLoc); // no don't do this
myJLabel.setText(input);
textClick=false;
}
}
如果您绝对必须使用 Graphics 绘制字符串,那么在上面的方法中,设置对象的一个字段,可能类似于 private String textToDraw
,在您的 GUI 上调用 repaint()
,并在您的JPanel 的 protected void paintComponent(Graphics g)
方法绘制文本。
这里有一段代码,将 JTextField 放在鼠标按下的位置,然后在按下回车键或失去焦点时将 JTextField 转换为 JLabel:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class AddingText extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
public AddingText() {
addMouseListener(new MyMouse());
setLayout(null); // one of the few times this may be ok
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private void convertToLabel(final JTextField textField) {
JLabel label = new JLabel(textField.getText());
label.setSize(label.getPreferredSize());
label.setLocation(textField.getLocation());
remove(textField);
add(label);
repaint();
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
final JTextField textField = new JTextField(20);
textField.setSize(textField.getPreferredSize());
textField.setLocation(e.getPoint());
add(textField);
revalidate();
repaint();
textField.requestFocusInWindow();
textField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
convertToLabel((JTextField) e.getComponent());
}
});
textField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
convertToLabel((JTextField) e.getSource());
}
});
}
}
private static void createAndShowGui() {
AddingText mainPanel = new AddingText();
JFrame frame = new JFrame("AddingText");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
尝试二:我通过覆盖 paintComponent 并使用 JOptionPane 直接在 JPanel 中绘制。文本被放置到 Map<Point, String>
中,然后通过遍历此地图在 paintComponent 中绘制此文本。这样我们就避免了可怕的 null
布局。
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.*;
public class AddingText2 extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private Map<Point, String> pointTextMap = new LinkedHashMap<>();
public AddingText2() {
addMouseListener(new MyMouse());
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(getFont().deriveFont(Font.BOLD));
for (Point p : pointTextMap.keySet()) {
String text = pointTextMap.get(p);
g.drawString(text, p.x, p.y);
}
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
String prompt = "Please add text to display";
String input = JOptionPane.showInputDialog(AddingText2.this, prompt);
pointTextMap.put(e.getPoint(), input);
repaint();
}
}
private static void createAndShowGui() {
AddingText2 mainPanel = new AddingText2();
JFrame frame = new JFrame("AddingText2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
如果我理解你的问题,你基本上想要 KeyListener
:
public class MyWindow extends JFrame {
private int x, y;
private String text;
private boolean shouldGetText = false;
private KeyListener keyboard = new KeyAdapter() {
public void keyTyped(KeyEvent evt) {
if(!shouldGetText)
return;
text = text + evt.getChar(); // or evt.getKeyChar()... not sure about the name of this method
}
public void keyPressed(KeyEvent evt) {
if (shouldGetText && evt.getKeyCode() == KeyEvent.VK_ENTER)
shouldGetText = false;
}
}
private MouseListener mouse = new MouseAdapter() {
public void mouseMoved(MouseEvent evt) {
if (shouldGetText)
return;
x = evt.getX();
y = evt.getY();
}
public void mousePressed(MouseEvent evt) {
shouldGetText = true;
text = "";
}
}
public MyWindow() {
addKeyListener(keyboard);
addMouseListener(mouse);
addMouseMotionListene(mouse);
// Do other stuff
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawString(text, x, y);
}
}