0

I'm using a jtextfield but it doesn't show up. From messing around with the code I think it's being drawn over. Another problem I've been having with the textfield is that when I revalidate it changes its size from what I need to the entire screen. I dealt with this by setting the size in a loop. I'd like it if there was a better way to do that but my priority is getting it visible first. Here is the code. Thanks ahead of time.

 /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package clientgui;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JTextField;

/**
 *
 * @author Zzzz
 */
public class ClientGUI extends JFrame{

    /**
     * @param args the command line arguments
     */

    Socket s ;
    PrintWriter out;
    String username;
    BufferedReader in; 
    ListeningThread lt;
    Image dbi;
    Graphics dbg;
    JTextField textField;
    BufferedImage background;

    public ClientGUI() throws IOException, InterruptedException
    {   
        background = ImageIO.read(new File("Background.png"));
        s = new Socket("127.0.0.1", 4382);
        out = new PrintWriter(s.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        lt = new ListeningThread(s);
        lt.start();

        setTitle("Simple Chat");
        setSize(500,500);
        setDefaultCloseOperation(3);
        setVisible(true);
        textField = new JTextField();

        textField.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent ae) {
                out.println(textField.getText());
            }

        });
        add(textField);


        while(true)
        {
            textField.setBounds(100, 420, 325, 25);
            textField.repaint();
            Thread.sleep(20);
        }
    }

    @Override
    public void paint(Graphics g)
    {

        dbi = createImage(getWidth(), getHeight());
        dbg = dbi.getGraphics();
        paintComponent(dbg);
        g.drawImage(dbi, 0, 0, rootPane);
    }

    public void paintComponent(Graphics g)
    {
        g.setColor(Color.white);
        g.drawImage(background, 0, 0, rootPane);
        g.drawString((String) ListeningThread.messages.get(0), 50, 65);
        repaint();
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        new ClientGUI();
    }

}
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Zzzz
  • 1
  • It's not being drawn at all. You override `paint`, which would normally call `paintChildren` at some point, so you would have to do it yourself. Put all your `paint` code into `paintComponent` instead. Also, don't call `repaint()` in `paintComponent()`. `repaint` is just a request to call `paintComponent` later down the line. – Mad Physicist May 22 '17 at 21:39
  • 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson May 23 '17 at 02:22

1 Answers1

2

There's a great article on how Swing and AWT do their painting on the Oracle site. I highly recommend you read it. In the section on the painting methods of Swing, it explains the errors you are facing.

1. You override paint() (big mistake)

Basically, paint() is the method that repaints everything, while paintComponent() is the place to put your custom code. paint() actually calls these functions (in order):

  1. protected void paintComponent(Graphics g)
  2. protected void paintBorder(Graphics g)
  3. protected void paintChildren(Graphics g)

When you overrode paint, you prevented your text box from ever being drawn at all by paintChildren(). To quote the article:

Swing programs should override paintComponent() instead of overriding paint()

2. You call repaint() (little mistake)

The same article also has a section on how repainting normally works. A very simplified way to look at it is that calling repaint() schedules a call to paint() in the near future, when the AWT Event Processing Thread gets to it. You do not need to call repaint() inside paintComponent().

TL;DR

  1. You should put everything you have in paint() into paintComponent().
  2. Don't call repaint() at the end of paintComponent().
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • 1
    `while-loop` and `Thread.sleep` likely in the EDT :P - Also calling `repaint` in a paint method is a big mistake, as it can cause the EDT to become flooded with paint events, causing the thread to starve other threads and consume all the CPU cycles, so, yeah, unpleasant - The OP should also be calling `super.paintXxx`, otherwise they will break the paint chain and cause lots of weirdness to occur – MadProgrammer May 22 '17 at 22:02
  • super.paintComponent() is not necessary in this case, and I would recommend against it. All it does is paint the background, so is unnecessary if OP is displaying a background image. – Mad Physicist May 23 '17 at 00:34
  • 1
    That assumes a few things, yes it "only" paints the background, but the panel is sized larger than the image, then you end up with paint glitches - and yes I've seen it done. It also assumes that the nature of the parent method, which is never a good thing, calling `super.paintXxx` solves 90% of common issues and questions presented by users and is commonly good practice. Also in this, it would have generated a compiler error. The fact they are not calling `super.paint` in there code cold also cause untold issues - again, a common source of questions – MadProgrammer May 23 '17 at 00:38
  • The default paint manager is pretty smart, so multiple calls to repaint() will just get aggregated into one if they fall within some reasonable time interval, probably related to your device's refresh rate. It's more of a nuisance than anything else, and certainly not something to make a habit of. – Mad Physicist May 23 '17 at 00:49
  • I've watched this type of code (calling `repaint` in a paint method) bring more than one system to it's knees - as clever as it is, there seems to be enough of delay to cause issues :P – MadProgrammer May 23 '17 at 00:52
  • Good point about the image size. Could also be remedied by making the component not opaque, but in a way I'm pretty sure OP won't like. – Mad Physicist May 23 '17 at 00:52
  • Can't cover for all the wonderful things that people "might" do ;) – MadProgrammer May 23 '17 at 00:52
  • Sure, that's why my answer only covers the basics that I think will build the best initial habits. Once you understand the system, you can freely do whatever you want. – Mad Physicist May 23 '17 at 00:54