Апплет Java отображает JLabel (и другие компоненты) с дополнительными случайными буквами - PullRequest
3 голосов
/ 27 мая 2011

Когда я запускаю апплет, код которого указан ниже, текст JLabel отображается неправильно.Над текстом надписи наложены дополнительные символы мусора.

Если я опускаю вызов setFont(), я не вижу проблем с рендерингом.

Апплет нормально работает в средстве просмотра апплетов, но имеет такие артефакты рендеринга в Chrome, Firefox и IE 8. Я использую последнюю версию Java 6 (версия 25) для Windows XP.Похоже, что проблема всегда возникает в Chrome и периодически возникает в Firefox.

Есть ли у вас какие-либо идеи о том, что может быть причиной этого?Я предполагаю, что я делаю что-то глупое.

Я разместил скомпилированный апплет здесь: 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);
    }

}

Вот скриншот того, как это выглядит для меня:

enter image description here

Ответы [ 2 ]

2 голосов
/ 27 мая 2011

Убедитесь, что компоненты графического интерфейса Swing созданы и обновлены в EDT.

например. 1 (не проверено)

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

например. 2 (не проверено во всем, кроме программы просмотра апплетов)

На основе (разорванного) примера camickr, но с вызовом setFont(), заключенным в Timer, который срабатывает каждые полсекунды, и последующим вызовом 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);
        }
    }
}

И так как я здесь.

<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. codebase="classes" выглядит подозрительно. Если бы это был сервер на базе Java, каталог /classes/lib) был бы предназначен исключительно для использования сервером и не был бы доступен для апплета.
  2. Атрибут кода должен быть полностью определенным именем cass, поэтому com.evanmallory.TellTime.class должно быть com.evanmallory.TellTime.
  3. <param name="host" value="http://localhost:8080"/> Я готов сделать WAG, что это значение либо не нужно, либо неправильно во время развертывания. Лучше определить во время выполнения, используя Applet.getDocumentBase() или Applet.getCodeBase().

Кстати - апплет работал нормально в моей недавней FF, работающей на недавней Oracle Java. Но проблемы EDT не являются детерминированными (случайными), так что это не значит много.

1 голос
/ 27 мая 2011

В руководстве Swing всегда создаются компоненты графического интерфейса в методе init ():

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

}

См .: Как сделать апплеты

...