简体   繁体   中英

How do I draw string from user input in a JFrame Java

Couldn't find what I was looking for from the search function, I might have just been formulating the title badly.

Anyways, right now I can click on my JFrame and it will draw whatever the user types into the console and when you hit Enter it will stop the sentence.

But what I want is for the user to just type directly into the JFrame and then when you hit enter you end the input.

This is what I have now:

 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;
    }
}

So you click somewhere on the JFrame. It will then display whatever the user is typing at that location, without having to go into the console and type there.

Don't mix console input with a Swing GUI as this can lead to a threading nightmare. Instead get the input by some other means. Myself, I'd use a JOptionPane.showInputDialog(...) to get a user's input String. Also, don't use Graphics like you're doing outside of a paint or paintComponent method as that's a recipe for a NullPointerException or some other GUI failure. Instead display the text in a JLabel or a text component such as a JTextArea or JTextField.

Something like:

 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;
    }
}

If you absolutely must draw the String using Graphics, then in the method above, set a field of the object, perhaps something like private String textToDraw , call repaint() on your GUI, and in your JPanel's protected void paintComponent(Graphics g) method draw the text.

Here's a kludge code that puts a JTextField at the mousepressed location, and then converts the JTextField into a JLabel either on enter press or on focus lost:

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();
         }
      });
   }
}

Attempt two: where I draw directly in the JPanel by overridding paintComponent and by using a JOptionPane. The text is placed into a Map<Point, String> and then this text is drawn within paintComponent by iterating through this map. This way we avoid the dreaded null layout.

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();
         }
      });
   }
}

If i understood your problem right, you basicly want a 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);
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM