I've been working on a fairly simple interface that allows multiple people to use sprites and walk around in a room conected through the internet. I've been having lots of the normal trouble with flickering but I had solved it with buffering. As soon as I started trying to use a transparent gif as the sprite the flickering returned. Here I have greatly simplified my program to basicaly just show the flickering after you hit connect so there is a lot of stuff that was used in the full version but is pointless here. If you make "sprite.gif" a normal gif there is no problem, but when parts of the gif are transparent there is noticeable flickering. Does anyone know why this happens?
Code:
import javax.swing.*;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.URL;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedInputStream;
import java.io.ObjectInputStream;
public class GifDisplay extends JPanel implements ActionListener {
JTextArea topTextArea;
Color m_clrBg = new Color(0, 0, 100);
static JTextArea bottomTextArea;
JButton button1, button2;
final static String newline = "\n";
static JTextField namef, input_text; // Textfields
Button display_button; // Display button
static JLabel message, input_label, output_label; // Labels for textfields
String out_string;
static JButton button;
static Image image, image1, image2, image3, image4, image5, image6;
static JTextArea textArea, online;
static int start, start2;
static Color squareColor; // The color of the square.
int squareTop, squareLeft; // Coordinates of top-left corner of square.
boolean focussed = false; // True when this applet has input focus.
static boolean init = false;
static DisplayPanel canvas; // The drawing surface on which the applet draws,
// belonging to a nested class DisplayPanel, which
// is defined below.
Image m_imgOffScr = null; // Image for off-screen drawing -- "back buffer"
Graphics m_gOffScr = null; // Graphics drawing interface to offscr image
public GifDisplay() {
super(new GridBagLayout());
GridBagLayout gridbag = (GridBagLayout) getLayout();
GridBagConstraints c = new GridBagConstraints();
message = new JLabel("Enter Name:");
gridbag.setConstraints(message, c);
add(message);
c.weightx = 1;
c.ipadx = 250;
namef = new JTextField(15);
namef.setEditable(false);
namef.setForeground(Color.BLACK);
gridbag.setConstraints(namef, c);
add(namef, c);
c.ipadx = 0;
c.weightx = 0;
c.ipady = 60;
c.gridwidth = 2;
c.gridheight = 2;
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.BOTH;
bottomTextArea = new JTextArea();
bottomTextArea.setEditable(false);
JScrollPane bottomScrollPane = new JScrollPane(bottomTextArea);
gridbag.setConstraints(bottomScrollPane, c);
add(bottomScrollPane);
c.ipady = 80; //reset to default
c.ipadx = 60; //make this component tall
c.weighty = 1.0;
c.weightx = .8;
c.gridwidth = 0;
c.gridheight = 3;
c.weighty = 1;
// c.ipady = 40; //make this component tall
c.gridx = 3;
c.gridy = 0;
online = new JTextArea();
online.setEditable(false);
JScrollPane onlinePane = new JScrollPane(online);
// bottomScrollPane.setPreferredSize(preferredSize);
gridbag.setConstraints(onlinePane, c);
add(onlinePane);
c.weightx = 0.0;
c.gridwidth = 4;
c.gridx = 0;
c.gridy = 3;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
squareColor = Color.red;
canvas = new DisplayPanel(); // Create drawing surface and
canvas.setBackground(Color.white); // Set the background color of the canvas.
squareTop = canvas.getSize().height - canvas.getSize().height / 10 / 2;
squareLeft = canvas.getSize().width - canvas.getSize().height / 10 / 2;
gridbag.setConstraints(canvas, c);
add(canvas);
c.fill = GridBagConstraints.NONE;
c.ipady = 0; //reset to default
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 3;
c.gridx = 0; //aligned with button 2
c.gridy = 7; //third row
c.gridwidth = 1;
button1 = new JButton("Connect");
gridbag.setConstraints(button1, c);
add(button1);
start = 1;
button1.addActionListener(this);
namef.addActionListener(this);
URL url = this.getClass().getResource("sprite.gif");
image3 = getToolkit().getImage(url);
setPreferredSize(new Dimension(500, 500));
}
class DisplayPanel extends JPanel {
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
while (Abstract.paint) {}
if (refresh.buffer1 != null) {
g.drawImage(Abstract.buffer, 0, 0, this); // Just display the "back" buffer
} else {
g.setColor(m_clrBg);
g.drawRect(0, 0, getSize().width, getSize().height);
}
Abstract.paint = true;
}
} // end nested class DisplayPanel
public static void disp(String mes) {
bottomTextArea.append(mes);
bottomTextArea.setCaretPosition(bottomTextArea.getDocument().getLength());
Toolkit.getDefaultToolkit().beep();
}
public static void onup(User c[]) {
online.setText("");
for (int l = 0; l < c.length; l++) {
if (c[l].active && c[l].name != null) {
online.append(c[l].name + newline);
}
}
}
public static void sen(String h) {
try {
PrintWriter os = new PrintWriter(Abstract.soccer().
getOutputStream());
os.print(h + "\r\n");
os.flush();
init = true;
} catch (java.io.IOException c) {
}
}
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(button1)) {
if (start == 0) {
start = 1;
sen(":exit:");
System.err.println("Exit");
namef.setEditable(false);
button1.setText("Connect");
message.setText("Enter Name:");
} else {
start = 0;
new refresh().start();
start2 = 0;
}
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("GifDisplay");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new GifDisplay();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
class Abstract {
static Socket s;
static int serial;
static String c[];
static String name;
static Image buffer;
static boolean paint = false;
static JFrame fra;
public static Socket soccer() {
return s;
}
public static void soccer(Socket soc) {
s = soc;
}
public static void retu(String a[]) {
c = a;
}
public static void retun(String a) {
name = a;
}
public static void fram(JFrame a) {
fra = a;
}
public static void ser(int a) {
serial = a;
}
}
class refresh extends Thread {
static int f[][];
Color m_clrBg = new Color(0, 0, 100);
static Image buffer1;
Graphics pad;
final static String newline = "\n";
private User m[];
Image image;
public void run() {
int place = Abstract.serial;
while (true) {
if (Abstract.paint) {
painter(place);
GifDisplay.canvas.repaint();
}
}
}
public void painter(int place) {
int width = GifDisplay.canvas.getSize().width; // Width of the applet.
int height = GifDisplay.canvas.getSize().height; // Height of the applet.
buffer1 = GifDisplay.canvas.createImage(GifDisplay.canvas.getSize().width,
GifDisplay.canvas.getSize().height);
pad = buffer1.getGraphics();
pad.drawImage(GifDisplay.image3, 55, 55,
width / 25, height / 25 * 2,
GifDisplay.canvas);
Abstract.buffer = buffer1;
Abstract.paint = false;
}
}
Sorry about that. As I said I took out most of the code to make the problem a little clearer. User was a class that kept track of the various variables assosiated with the users like name, location, ect. Its not assiciated with this problem so I took it out but accidently some references to it I guess. Heres the code with some more of the working bits removed. I found the problem is the same in this gutted version as it is in the full thing. I've tested it and it should compile and run as is, you just need to try a gif one of which I included for your convinience. [edit]it seems I was mistaken about the problem only occuring with transparent gifs. I now see it only to certain gifs the one I included causes the problem but I found others don't is there some sort of specific type of gif that must be used in java? The second download works without flickering.
Code:
import javax.swing.*;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.URL;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedInputStream;
import java.io.ObjectInputStream;
public class GifDisplay extends JPanel implements ActionListener {
JTextArea topTextArea;
Color m_clrBg = new Color(0, 0, 100);
static JTextArea bottomTextArea;
JButton button1, button2;
final static String newline = "\n";
static JTextField namef, input_text; // Textfields
Button display_button; // Display button
static JLabel message, input_label, output_label; // Labels for textfields
String out_string;
static JButton button;
static Image image, image1, image2, image3, image4, image5, image6;
static JTextArea textArea, online;
static int start, start2;
static Color squareColor; // The color of the square.
int squareTop, squareLeft; // Coordinates of top-left corner of square.
boolean focussed = false; // True when this applet has input focus.
static boolean init = false;
static DisplayPanel canvas; // The drawing surface on which the applet draws,
// belonging to a nested class DisplayPanel, which
// is defined below.
Image m_imgOffScr = null; // Image for off-screen drawing -- "back buffer"
Graphics m_gOffScr = null; // Graphics drawing interface to offscr image
public GifDisplay() {
super(new GridBagLayout());
GridBagLayout gridbag = (GridBagLayout) getLayout();
GridBagConstraints c = new GridBagConstraints();
message = new JLabel("Enter Name:");
gridbag.setConstraints(message, c);
add(message);
c.weightx = 1;
c.ipadx = 250;
namef = new JTextField(15);
namef.setEditable(false);
namef.setForeground(Color.BLACK);
gridbag.setConstraints(namef, c);
add(namef, c);
c.ipadx = 0;
c.weightx = 0;
c.ipady = 60;
c.gridwidth = 2;
c.gridheight = 2;
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.BOTH;
bottomTextArea = new JTextArea();
bottomTextArea.setEditable(false);
JScrollPane bottomScrollPane = new JScrollPane(bottomTextArea);
gridbag.setConstraints(bottomScrollPane, c);
add(bottomScrollPane);
c.ipady = 80; //reset to default
c.ipadx = 60; //make this component tall
c.weighty = 1.0;
c.weightx = .8;
c.gridwidth = 0;
c.gridheight = 3;
c.weighty = 1;
// c.ipady = 40; //make this component tall
c.gridx = 3;
c.gridy = 0;
online = new JTextArea();
online.setEditable(false);
JScrollPane onlinePane = new JScrollPane(online);
// bottomScrollPane.setPreferredSize(preferredSize);
gridbag.setConstraints(onlinePane, c);
add(onlinePane);
c.weightx = 0.0;
c.gridwidth = 4;
c.gridx = 0;
c.gridy = 3;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
squareColor = Color.red;
canvas = new DisplayPanel(); // Create drawing surface and
canvas.setBackground(Color.white); // Set the background color of the canvas.
squareTop = canvas.getSize().height - canvas.getSize().height / 10 / 2;
squareLeft = canvas.getSize().width - canvas.getSize().height / 10 / 2;
gridbag.setConstraints(canvas, c);
add(canvas);
c.fill = GridBagConstraints.NONE;
c.ipady = 0; //reset to default
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 3;
c.gridx = 0; //aligned with button 2
c.gridy = 7; //third row
c.gridwidth = 1;
button1 = new JButton("Connect");
gridbag.setConstraints(button1, c);
add(button1);
start = 1;
button1.addActionListener(this);
namef.addActionListener(this);
URL url = this.getClass().getResource("sprite.gif");
image3 = getToolkit().getImage(url);
setPreferredSize(new Dimension(500, 500));
}
class DisplayPanel extends JPanel {
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
if (refresh.buffer1 != null) {
g.drawImage(Abstract.buffer, 0, 0, this); // Just display the "back" buffer
} else {
g.setColor(m_clrBg);
g.drawRect(0, 0, getSize().width, getSize().height);
}
Abstract.paint = true;
}
} // end nested class DisplayPanel
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(button1)) {
if (start == 0) {
start = 1;
System.err.println("Exit");
namef.setEditable(false);
button1.setText("Connect");
message.setText("Enter Name:");
} else {
start = 0;
new refresh().start();
start2 = 0;
}
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("GifDisplay");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new GifDisplay();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
class Abstract {
static Socket s;
static int serial;
static String c[];
static String name;
static Image buffer;
static boolean paint = false;
static JFrame fra;
}
class refresh extends Thread {
static int f[][];
Color m_clrBg = new Color(0, 0, 100);
static Image buffer1;
Graphics pad;
final static String newline = "\n";
Image image;
public void run() {
int place = Abstract.serial;
while (true) {
painter(place);
GifDisplay.canvas.repaint();
}
}
public void painter(int place) {
int width = GifDisplay.canvas.getSize().width; // Width of the applet.
int height = GifDisplay.canvas.getSize().height; // Height of the applet.
buffer1 = GifDisplay.canvas.createImage(GifDisplay.canvas.getSize().width,
GifDisplay.canvas.getSize().height);
pad = buffer1.getGraphics();
pad.drawImage(GifDisplay.image3, 55, 55,
width / 25, height / 25 * 2,
GifDisplay.canvas);
Abstract.buffer = buffer1;
}
}
Last edited by axlan; 06-22-2005 at 09:22 AM.
Reason: spelling
Bookmarks