Swing components + images based applications

I’m developing a game and I’m basically using BufferedImage. I need a text field in my game so that the user can type his nickname and such…this text field must appear over all the images on the background. How can I use JFormattedText field here?!? I tried using it with partial success because it appears and disappears(flickering) while I render. Have no idea on how to do it. Please Help!!! Thanks :wink:

It’s hard to help you without knowing how you’re putting the JFormattedText field on top of the images.

Are you using a JDialog? I’ve had similar problems when using dialogs. Some kind of dialog bug was fixed in the newer versions of Java, but I have no idea whether that would help.

If you’re not using a JDialog but are using passive rendering, it might help to use active rendering.

Does this happen with other Components, or is the JFormattedText field the only component you’re using.

Thanks for replying. The same problem occurs with any swing component. I really would like to know a correct method to do such things. I’m almost sure I’m not doing it in a ‘near to correct’ fashion. Because what I do is the following: first I draw all the game images on an offscreen image(a BufferedImage)called backBuffer, then I do jframe.getGraphics().drawImage(backBuffer, 0, 0, null) to present all the contents to the screen(all this works OK). What I need is to draw the JFormattedTextField on the backBuffer before presenting the backBuffer to the screen. What I did previously was use functions like paintAll() and paintComponents() on the backBuffer. It works but no image is rendered on the background, only the swing components. I get a full gray background. Do anyone knows a good way to do it? Thanks

I did a lot with Swing ;D However, I would need a code sample (please shorten it to the bare minimum) …

Thanks for replying. This is a test code I did to try making that thing work(hope it is understandable)



import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Main extends JFrame implements ActionListener, Runnable
{
    JFormattedTextField text;
    JButton button;
    Thread thread;
    Graphics2D g2D;
    BufferedImage backbuffer;
    BufferedImage bi;
    
    public void actionPerformed(ActionEvent e)
    {
        JOptionPane.showMessageDialog(null, text.getText());
    }
    
    public Main()
    { 
        super("test");
        
        MaskFormatter mf = null;
        
        try
        {
            mf = new MaskFormatter("**********");
            mf.setValidCharacters(" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-");
        }
        catch(Exception e)
        {
            System.out.println("Got exception! quaquaquaqua!!!: " + e.getMessage());
        }
        
        text = new JFormattedTextField(mf);
        text.setColumns(10);
        text.setSize(100, 30);
        
        button = new JButton("OK");
        button.setSize(100, 30);
        button.addActionListener(this);
        
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        panel.add(text);
        panel.add(button);
        panel.setOpaque(false);
        setLayout(new GridBagLayout());
        getContentPane().add(panel);
       
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        setBounds(200, 200, 300, 300);
        setVisible(true);
        backbuffer = new BufferedImage(290, 290, BufferedImage.TYPE_4BYTE_ABGR);
        g2D = backbuffer.createGraphics();
        
        thread = new Thread(this);
        thread.start();
        
        try 
        {
            bi = ImageIO.read(new File("Image.jpg"));
        } 
        catch(IOException ex) 
        {
            ex.printStackTrace();
        }
    }

	public void run()
	{
		while (true)
		{
			g2D.setColor(Color.WHITE);
			g2D.fillRect(0, 0, 290, 290);
			g2D.drawImage(bi, 0, 0, null);
			g2D.setColor(Color.BLACK);
			g2D.setFont(new Font("Rainbow6", Font.PLAIN, 50));
			g2D.drawString("Xiss Burg", 10 + (int)(30 * Math.cos(System.currentTimeMillis() * 0.001)), 100 + (int)(30 * Math.sin(System.currentTimeMillis() * 0.001)));
			paintComponents(g2D);
			getGraphics().drawImage(backbuffer, 0, 0, null);


			try
			{
				thread.sleep(30);
			}
			catch (InterruptedException e)
			{
				JOptionPane.showMessageDialog(null, "The thread has thrown an InterruptedException:\n"
													+ e.getMessage());
			}
		}
	}
    
    public static void main(String args[])
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                Main m = new Main();
            }
        }
        );
    }
}

This worked for me.


import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Test extends JFrame implements ActionListener, Runnable
{
    JFormattedTextField text;
    JButton button;
    Thread thread;
    Graphics2D g2D;
    BufferedImage backbuffer;
    BufferedImage bi;
    JPanel panel;
    
    public void actionPerformed(ActionEvent e)
    {
        JOptionPane.showMessageDialog(null, text.getText());
    }
    
    public Test()
    { 
        super("test");
        
        MaskFormatter mf = null;
        
        try
        {
            mf = new MaskFormatter("**********");
            mf.setValidCharacters(" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-");
        }
        catch(Exception e)
        {
            System.out.println("Got exception! quaquaquaqua!!!: " + e.getMessage());
        }
        
        text = new JFormattedTextField(mf);
        text.setColumns(10);
        
        button = new JButton("OK");
        button.setSize(100, 30);
        button.addActionListener(this);
        
        panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        panel.add(text);
        panel.add(button);
        panel.setOpaque(false);
        setContentPane(panel);    //better to set the panel as the content pane than to add it.
       
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        setBounds(200, 200, 300, 300);
        setVisible(true);
        backbuffer = new BufferedImage(290, 290, BufferedImage.TYPE_4BYTE_ABGR);
        
        thread = new Thread(this);
        thread.start();
        
        try 
        {
            bi = ImageIO.read(getClass().getResourceAsStream("/Image.jpg"));
        } 
        catch(IOException ex) 
        {
            ex.printStackTrace();
        }
    }

    public void run()
    {
        while (true)
        {
            g2D = backbuffer.createGraphics();
            Insets border = getInsets();
            g2D.setColor(Color.WHITE);
            g2D.fillRect(0, 0, 290, 290);
            g2D.drawImage(bi, 0, 0, null);
            g2D.setColor(Color.BLACK);
            g2D.setFont(new Font("Rainbow6", Font.PLAIN, 50));
            g2D.drawString("Xiss Burg", 10 + (int)(30 * Math.cos(System.currentTimeMillis() * 0.001)), 100 + (int)(30 * Math.sin(System.currentTimeMillis() * 0.001)));
            getContentPane().paintComponents(g2D);   //paint to the correct component.  the JPanel contained the button and text field.
            g2D.dispose();
            getGraphics().drawImage(backbuffer, border.left, border.top, null); //need to take into account the JFrame border.


            try
            {
                Thread.sleep(30);
            }
            catch (InterruptedException e)
            {
                JOptionPane.showMessageDialog(null, "The thread has thrown an InterruptedException:\n"
                                                    + e.getMessage());
            }
        }
    }
    
    public static void main(String args[])
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                Test m = new Test();
            }
        }
        );
    }
}

hi!
I have considered your lists for a ltille while… It is worth to make the threads interruptible at any point of your application state. Thus I often recommend to load Timers instead of Threads with internal loops, because of Java Access Security enabled for IO operations mostly.
Then try to replace the runned Thread with a simple javax.swing.Timer implementing the given ActionListener. Thereafter your application will become more flexible. Mainly :


javax.swing.Timer timer = new javax.swing.Timer(tickTime, actionListener);
timer.start();

could be stopped when required:

timer.stop();

::slight_smile:

Thank you CaptainJester, it works the way I want :smiley: Thanks for showing me ‘Insets’. I didn’t know it.

And broumbroum, thanks for the suggestion. But I didn’t understand why you are suggesting it. could you explain better or show me any article that explains it better?!

Thank yall

I suggested to use a Timer instead of a Thread instance in that case, because of the requested ImageIO process at the begining of the code seen beyond my post. To be clearier, the loop while(true) has better to be replaced with a Timer sending succeeding ActionEvents. Plus you can restart the Timer at any time with its restart() method without losing your Timer instance. And finally it would be great to instance FileChannelImageInput for an image file or ImageInputStream, because of their flexibility regarding Thread-safety…

.
For instance, try to interrupt the thread while it is running Image operation like loading and/or drawing simultaneously. You should notice the lock on the runnin Thread.
Further simply imagine loading multiple images for drawing them next in the same Thread. How could you stop the operation if wanted so?
http://builder.com.com/5100-6370-5144546.html , a web page talkin about it.

I already developed a game using a very similar algorithm, using a thread with a while(true)(I learned it from a Java game programming tutorial), and it works fine. I never had any problems with that, and I do operations like load images(when loading the game for example) inside this thread with no problems. The Timer also seems very good to do such things. I’ll try it out on my next applications. Thanks again.