3

When I run the applet whose code is listed below, the text of the JLabel does not draw properly. There are extra garbage characters superimposed on top of the label text.

If I omit the call to setFont(), I don't see any rendering problems.

The applet runs fine in the appletviewer, but has these rendering artifacts in Chrome, Firefox, and IE 8. I'm running the latest version of Java 6 (rev. 25) on Windows XP. The problem seems to always occur in Chrome, and be intermittent in Firefox.

Do you have any ideas about what could be causing this? I suppose I'm doing something stupid.

I've posted the compiled applet here: http://evanmallory.com/bug-demo/.

package com.evanmallory;

import java.awt.*;
import javax.swing.*;

public class TellTime extends JApplet {

    private JLabel mMessage;

    public TellTime() {
        mMessage = new JLabel("Set the clock to the given time.",
            SwingConstants.CENTER);
        mMessage.setFont(new Font("Serif", Font.PLAIN, 36));
        getContentPane().add(mMessage);
    }

}

Here's a screenshot of what it looks like for me:

enter image description here

4

2 回答 2

2

Make sure Swing GUI components are created & updated on the EDT.

E.G. 1 (untested)

package com.evanmallory;

import java.awt.*;
import javax.swing.*;

public class TellTime extends JApplet {

    private JLabel mMessage;

    public TellTime() {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() {
                mMessage = new JLabel("Set the clock to the given time.",
                    SwingConstants.CENTER);
                mMessage.setFont(new Font("Serif", Font.PLAIN, 36));
                getContentPane().add(mMessage);
            }
        });
    }
}

E.G. 2 (untested in anything but applet viewer)

Based on (ripped from) camickr's example, but with a call to setFont() wrapped in a Timer that fires every half second, and a subsequent call to repaint().

// <applet code="AppletBasic" width="300" height="100"></applet>
// The above line makes it easy to test the applet from the command line by using:
// appletviewer AppletBasic.java

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class AppletBasic extends JApplet
{
    Timer timer;

    /**
     * Create the GUI. For thread safety, this method should
     * be invoked from the event-dispatching thread.
     */
    private void createGUI()
    {
        final JLabel appletLabel = new JLabel( "I'm a Swing Applet" );
        appletLabel.setHorizontalAlignment( JLabel.CENTER );

        ActionListener listener = new ActionListener() {
            Random random = new Random();
            public void actionPerformed(ActionEvent ae) {
                // determine a size between 12 & 36.
                int size = random.nextInt(24)+12;
                appletLabel.setFont(new Font("Serif", Font.PLAIN, size));
                // tell the applet to repaint
                repaint();
            }
        };
        timer = new Timer(500, listener);
        timer.start();

        add( appletLabel );
    }

    public void init()
    {
        try
        {
            SwingUtilities.invokeAndWait(new Runnable()
            {
                public void run()
                {
                    createGUI();
                }
            });
        }
        catch (Exception e)
        {
            System.err.println("createGUI didn't successfully complete: " + e);
        }
    }
}

And since I'm here.

<html>
<body>
<applet codebase="classes" code="com.evanmallory.TellTime.class"
  width=800 height=500>
    <param name="level" value="1"/>
    <param name="topic" value="TellTime"/>
    <param name="host" value="http://localhost:8080"/>
  </applet>
  </body>
</html>
  1. The codebase="classes" looks suspicious. If this were on a Java based server, the /classes (and /lib) directory would be for the exclusive use of the server, and would not be accessible to an applet.
  2. The code attribute should be the fully qualified name of the cass, so com.evanmallory.TellTime.class should be com.evanmallory.TellTime.
  3. <param name="host" value="http://localhost:8080"/> I am prepared to make a WAG that that value is either unnecessary or wrong for time of deployment. It is better to determine at run-time using Applet.getDocumentBase() or Applet.getCodeBase().

BTW - The applet worked fine in my recent FF running a recent Oracle Java. But EDT problems are non determinate (random), so that does not mean much.

于 2011-05-27T01:53:12.157 回答
1

Swing 教程总是在 init() 方法中创建 GUI 组件:

// <applet code="AppletBasic.class" width="400" height="400"></applet>
// The above line makes it easy to test the applet from the command line by using:
// appletviewer AppletBasic.java

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;

public class AppletBasic extends JApplet
{
    /**
     * Create the GUI. For thread safety, this method should
     * be invoked from the event-dispatching thread.
     */
    private void createGUI()
    {
        JLabel appletLabel = new JLabel( "I'm a Swing Applet" );
        appletLabel.setHorizontalAlignment( JLabel.CENTER );
        add( appletLabel );
    }

    public void init()
    {
        try
        {
            SwingUtilities.invokeAndWait(new Runnable()
            {
                public void run()
                {
                    createGUI();
                }
            });
        }
        catch (Exception e)
        {
            System.err.println("createGUI didn't successfully complete: " + e);
        }
    }

}

请参阅:如何制作小程序

于 2011-05-27T02:38:22.043 回答