Frequently Asked Questions during Java applet development

    How to call JavaScript functions in the applet?

    How to call the applet methods in JavaScript?

    How to use the applet run parameters?

    How to take a screenshot of Swing/AWT component?

    How to use two applets in a browser at the same time, if they contain static fields?

    How in Swing I can make the input field of minimum size that dynamically expands when it overflows?

    How to implement Drag&Drop in the Swing?

    How to sign an applet by certificate?

    How to play MP3 and WAV files in Java?

    How to use HTML formatting in Swing components?

    The components aren’t displayed when using the cycle, what to do?

    How can I make a smooth transition between frames in the Swing?

    How to run an applet?

    How can the Swing components with random coordinates be placed on the container?

    How to automate the applet build using Maven?

    How to call JavaScript functions in the applet?

    This can be done by using the following code:

    applet.getAppletContext().
        showDocument(new URL("javascript:" + js));

    Where applet is an object of JApplet class, js is a JavaScript function name, for example: show().

    With that the applet should be launched from JavaScript.

    How to call the applet methods in JavaScript?

    To do this the applet should be launched from JavaScript, e.g.

    <script src="https://www.java.com/js/deployJava.js"></script>
        <script>
            var attributes = { id: 'mainApplet', code:  
    'org.jazzteam.Example', archive: 'example.jar', width: 812, height:  
    635};                 
            var parameters = {};         
            deployJava.runApplet(attributes, parameters, '1.7');                 
            function actionInApplet(url) {                         
                mainApplet.appletMethod(url);                 
            }
    </script>

    In this case the applet is launched from JavaScript with id= ‘mainApplet’. In the applet there is appletMethod() method, which we want to call. To do this you need to call the method related to JavaScript object with id name. You can also pass parameters to the called methods, as demonstrated in this example.

    Also it is necessary to know that the applet method called from JavaScript should be privileged. To do this you need to wrap the method code in the following “wrapper”:

    AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            //method code
            return new Object();
        }
    });

    How to use the applet run parameters?

    In the above example in “var parameters = {};” construction you need to add the necessary parameters, for example:

    var parameters = {firstParameter:true, secondParameter:false};

    In the applet the parameters are read as follows:

    String parameter=applet.getParameter(“firstParameter”);

    Where applet is an object of JApplet class (or Applet class).

    This method also works when you run the applet using <object> and <applet> tag.

    How to take a screenshot of Swimg/AWT component?

    This can be done in 2 ways. In both cases the component must be visible.

    Without the robot use:

    BufferedImage image = new BufferedImage(component.getWidth(), 
    component.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        component.paint(g);

    With the robot use:

    In this case the screenshot of area in which this component is situated will be made. That is, if the component overlaps another application window then the screenshot will contain an area of this another window.

    Point point = new Point(0, 0);
        SwingUtilities.convertPointToScreen(point, component);
        Rectangle region = component.getBounds();
        region.x = point.x;
        region.y = point.y;
        BufferedImage image= new Robot().createScreenCapture(region);

    How to use two applets in a browser at the same time, if they contain static fields?

    To do this run the applets in different JVM. To run applets in different JVM you need to run them with separate_jvm=true parameter.

    How in Swing I can make the input field of minimum size that dynamically expands when it overflows?

    Below there is an example of such JTextField:

    public class TextField extends JTextField {
        public static final int TEXT_FIELD_PADDING = 4;
    
        public TextField() {
            addAutoResize();
            init();
        }
    
        public void init() {
            setStyleByParentStyle();
            this.setPreferredSize(new Dimension(Constant.
    TEXT_FIELD_MINIMAL_WIDTH, this.getPreferredSize().height));
        }
    
        private void addAutoResize() {
            this.getDocument().addDocumentListener
    (new DocumentListener() {
                @Override
                public void insertUpdate(DocumentEvent e) {
                checkResize();
                }
    
                @Override
                public void removeUpdate(DocumentEvent e) {
                checkResize();
                }
    
                @Override
                public void changedUpdate(DocumentEvent e) {
                checkResize();
                }
            });
        }
    
        private void checkResize() {
            FontMetrics fontMetrics = this.getFontMetrics(this.
    getFont());
    
            if (fontMetrics.stringWidth(this.getText()) + 
    TEXT_FIELD_PADDING * 2 < Constant.TEXT_FIELD_MINIMAL_WIDTH) {
                this.setPreferredSize(new 
    Dimension(Constant.TEXT_FIELD_MINIMAL_WIDTH, this.getHeight()));
                this.getParent().revalidate();
            } else {
                //NOTE 2 - border width*2
                this.setPreferredSize(new 
    Dimension(fontMetrics.stringWidth(this.getText()) + 2 + 
    Constant.CARRET_WIDTH + TEXT_FIELD_PADDING * 2, this.getHeight()));
                this.getParent().revalidate();
            }
        }
    }

    How to implement Drag&Drop in the Swing?

    The quite convenient mechanism for the implementation of Drag&Drop has appeared in Java 6, but it does have its disadvantages. For example, you should explicitly specify a Drop Target, what is not very useful when you need to lay down the object near the Drop Target. Also in the standard implementation there is no guarantee of execution order of listeners’ methods. I’ll tell you the concept of implementing a more extensible Drag&Drop.

    Initially the mouse listeners (Mouse Listener and MouseMotionListener) should be assigned to all Drag Sources. It’s need to implement 3 methods: a method of mouse click on the object, a method of moving the mouse while holding the mouse button on the object (mouseDragged in MouseMotionListener) and the mouse up method.

    The listeners assignment looks as follows:

    component.addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            //block click right mouse button
            if (MouseEvent.BUTTON1 == e.getButton()) {
                startDrag(e);
            }
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
            //block click right mouse button
            if (MouseEvent.BUTTON1 == e.getButton()) {
                endDrag(e);
            }
        }
    });
    
    component.addMouseMotionListener(new MouseMotionAdapter() {
        @Override
        public void mouseDragged(MouseEvent e) {
            drag(e);
       }
    });

    Accordingly when you click on the object Drag&Drop starts, when you move the mouse the object should be moved, when you release the mouse the object should change its position and be moved to a new container. If the object will be moved in the frame of one container, then it is possible to implement only mouseDragged () method, in which the coordinates of the dragged object will be changed:

    @Override
    public void mouseDragged(MouseEvent e) {
        Point mouseLocation = e.getLocationOnScreen();
        Component draggedComponent = (Component) e.getSource();
        SwingUtilities.convertPointFromScreen(mouseLocation, 
    draggedComponent.getParent());
        draggedComponent.setLocation(mouseLocation);
    }

    But dragged object coordinates can be set relative to the container in which it is located. Accordingly, when the mouse is moved to another container it is necessary to add a component to a new container and to calculate the new coordinates, etc. This method is not very beautiful and extensible, so I suggest using GlassPane to display the dragged object.

    The algorithm looks as follows:

    • Click on the object.
    • Get a screenshot of the object (see above how to make a screenshot).
    • Hide the original object.
    • Draw on glassPane a screenshot of the object, based on the coordinates of the mouse.
    • When you move the mouse you need to redraw a screenshot according to the new coordinates.
    • When you release the mouse you need to place the object on the container under which the cursor is located.
    • Display the original object.

    With this approach, we have no any dependences on the container on which the cursor should be placed to make Drop and correspondingly the object can be “Dropped” anywhere.


    GlassPane with transparency effect:

    public class GhostGlassPane extends JPanel {
        private final AlphaComposite composite;
        private BufferedImage ghostImage = null;
        private Point location = new Point(0, 0);
    
        public GhostGlassPane() {
            setOpaque(false);
            composite = AlphaComposite.getInstance(AlphaComposite.
    SRC_OVER, 0.7f);
    }
    public void paintComponent(Graphics g) {
    
        if (ghostImage == null)
            return;
    
        Graphics2D g2 = (Graphics2D) g;
        g2.setComposite(composite);
        g2.drawImage(ghostImage, (int) (location.getX()),
    (int) (location.getY()), null);
    
        }
    }

    In this response only concept of implementation is given.

    How to sign an applet by certificate?

    Read our “Java applet signing” article.

    How to play MP3 and WAV files in Java?

    Read our “Support of MP3 and WAV format files playback in Java” article.

    How to use HTML formatting in Swing components?

    The following swing components support HTML formatting: buttons, menu items, labels, tool tips and tabbed panes. To use the formatting it is necessary at the beginning of the text to put <html> tag (closing it at the end is optional.) For example:

    <html><b><u>T</u>wo</b>

    The following text will be displayed on the component: Two

    The components aren’t displayed when using the cycle, what to do?

    Most probably the cycle is used in the flow of drawing Swing. In order to perform any action on the UI and not to block the flow of drawing, you can use Swing Timer.
    An example usage is:

    Timer timer= new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            //actions
        }
     });
     timer.setRepeats(true);
     timer.start();

    This code will perform some actions once per second without blocking the flow of drawing.
    You can also set the property of repeats = false, to perform an action only 1 time.
    To stop the timer, perform timer.stop()

    How can I make a smooth transition between frames in the Swing?

    I can offer the following effect:

    White background appears smoothly on the one frame (you can insert a picture or a screenshot of the frame), then the white background disappears gradually and the next frame appears under it.

    The algorithm looks like:

    • Make GlassPane frame white coloured and able to change its transparency (an example of such implementation can be found above).
    • Gradually reduce glassPane transparency from 100% to 0%, so that it will be completely white and opaque.
    • Display the new frame under glassPane.
    • Increase transparency of glassPane to 100% (and then it can be deleted).

    How to run an applet?

    You can run applet on HTML page in 3 different ways: using <applet> tag, using <object> tag or using JavaScript.

    <Applet> tag is considered obsolete, but still most of the applets are run in this way:

    <applet code="HelloWorldApplet.class" width="320" height="120">
    </applet>

    The example of the applet run  <object> tag:

    <object type="application/x-java-applet" name="previewersGraph" 
    width="360" height="320"> 
        <param name="codebase" value="/applets" /> 
        <param name="code" value="my.full.class.Name" />
        <param name="archive" value="applets.jar" /> 
    </object>

    Example of JavaScript run of applet can be found above.

    How can the Swing components with random coordinates be placed on the container?

    I can offer the following algorithm:

    • From the list of components, select the largest one.
    • Further split the container into cells, equal to the largest component. For example, if the container size is 100×60 pixels and the size of the largest component is 25×20 pixels, then the component should be split into 12 cells, 4 columns and 3 rows.
    • Further we need to remove the excess cells in order to find the minimum number of cells in which the components can be located. You can initially remove excess columns or excess rows. I implemented the initial removing excess columns. Let’s consider the above example: we have 12 cells, let’s assume we have 7 components. Remove 1 column and verify that the components fit into the cells. It turned 9 cells (3×3), respectively, in which 7 components can be placed. Furthermore, we see that we can not remove the extra row\column, as in this case we will get 6 cells, what is less than 7 components.
    • Further stretch the resulting cells over the entire width of the container. We will get 9 cells of 33×20 pixels size.
    • Then place the components inside the resulting cells using random coordinates.

    Implementation of the algorithm:

    /**
     * Class for adding components to container with random 
     * coordinates
     */
    public class ComponentRandomizer {
    
        /**
         * Add all components to container with random 
         * coordinates
         */
        public static void addComponentsToContainer(Container 
    container, List<JComponent> components) {
            List<Rectangle> cells = getContainerCells(container, 
    components);
            for (JComponent component : components) {
                Rectangle randomCell = cells.get(new Random().
    nextInt(cells.size()));
                cells.remove(randomCell);
                addComponentToContainer(container, component, 
    randomCell);
            }
        }
    
        /**
         * Add one component to container by it cell
         */
        private static void addComponentToContainer(Container 
    container, JComponent component, Rectangle cell) {
            container.add(component);
            int xCoordinate = getRandomInt(cell.getX(), 
    cell.getWidth() - component.getWidth());
            int yCoordinate = getRandomInt(cell.getY(), 
    cell.getHeight() - component.getHeight());
            component.setLocation(xCoordinate, yCoordinate);
        }
    
        /**
         * Get random integer
         */
        private static int getRandomInt(double minimal, 
    double interval) {
            if (interval > 0) {
                return (int) (minimal + 
    new Random().nextInt((int) interval));
            } else {
                return (int) minimal;
            }
        }
    
        /**
         * Create a cells that serves to adding component into it
         */
        private static List<Rectangle> getContainerCells(Container 
    container, List<JComponent> components) {
    
            Pair<Integer, Integer> optimalCellsNumber = 
    getOptimalNumberOfContainerCells(container, components);
            Dimension cellSize = getCellSize(container, 
    optimalCellsNumber);
    
            List<Rectangle> cells = new LinkedList<Rectangle>();
            for (int stringIndex = 0; stringIndex < 
    optimalCellsNumber.getKey(); stringIndex++) {
                for (int columnIndex = 0; columnIndex < 
    optimalCellsNumber.getValue(); columnIndex++) {
                    cells.add(createCell(cellSize, stringIndex, 
    columnIndex));
                }
            }
    
            return cells;
        }
    
        /**
         * Create a cell that serves to adding component into it
         */
        private static Rectangle createCell(Dimension cellSize, 
    int stringIndex, int columnIndex) {
            int xCellCoordinate = (int) (columnIndex * 
    cellSize.getWidth());
            int yCellCoordinate = (int) (stringIndex * 
    cellSize.getHeight());
            return new Rectangle(xCellCoordinate, yCellCoordinate, 
    (int) cellSize.getWidth(), (int) cellSize.getHeight());
        }
    
        /**
         * Create cell size
         */
        private static Dimension getCellSize(Container container, 
    Pair<Integer, Integer> optimalCellsNumber) {
            double cellWidth = container.getWidth() / 
    optimalCellsNumber.getValue();
            double cellHeight = container.getHeight() / 
    optimalCellsNumber.getKey();
            return new Dimension((int) Math.floor(cellWidth), 
    (int) Math.floor(cellHeight));
        }
    
        /**
         * Get the optimal amount of cells that can fit all of the 
         * components
         *
         * @return count strings and columns
         */
        private static Pair<Integer, Integer> 
    getOptimalNumberOfContainerCells(Container container, 
    List<JComponent> components) {
    
            //<Strings count, Columns count>
            Pair<Integer, Integer> numberOfContainerCells = 
    getNumberOfContainerCells(container, components);
    
            //remove extra columns
            while (Math.ceil((double) components.size() / 
    numberOfContainerCells.getKey()) < 
    numberOfContainerCells.getValue()) {
                numberOfContainerCells = new Pair<Integer, 
    Integer>(numberOfContainerCells.getKey(), 
    numberOfContainerCells.getValue() - 1);
            }
            //remove extra strings
            while (Math.ceil((double) components.size() / 
    numberOfContainerCells.getValue()) < 
    numberOfContainerCells.getKey()) {
                numberOfContainerCells = new Pair<Integer, 
    Integer>(numberOfContainerCells.getKey() - 1, 
    numberOfContainerCells.getValue());
            }
    
    
            return numberOfContainerCells;
        }
    
        /**
         * Split container on the cells by largest component and get 
         * the number of cells of the container
         *
         * @return count strings and columns
         */
        private static Pair<Integer, Integer> 
    getNumberOfContainerCells(Container container, 
    List<JComponent> components) {
            JComponent largestComponent = getLargestComponent(components);
            int stringsCount = (int) Math.floor(container.getHeight() / 
    largestComponent.getHeight());
            int columnsCount = (int) Math.floor(container.getWidth() / 
    largestComponent.getWidth());
            if (stringsCount * columnsCount < components.size()) {
                throw new IllegalArgumentException(Constant.
    MESSAGE_THE_COMPONENTS_CANNOT_BE_ACCOMMODATED_IN_THE_CONTAINER);
            }
            return new Pair<Integer, Integer>(stringsCount, columnsCount);
        }
    
        /**
         * Get component with largest square
         */
        private static JComponent getLargestComponent(List<JComponent> 
    components) {
            JComponent largestComponent = components.get(0);
            for (JComponent checkedComponent : components) {
                if (getComponentSquare(
    checkedComponent.getPreferredSize()) > 
    getComponentSquare(largestComponent.getPreferredSize())) {
                    largestComponent = checkedComponent;
                }
            }
            return largestComponent;
        }
    
        /**
         * Create component square
         */
        private static double getComponentSquare(Dimension 
    checkedComponentSize) {
            return checkedComponentSize.getHeight() * 
    checkedComponentSize.getWidth();
        }
    
        /**
         * Class for saving pair values
         */
        public static class Pair<K, V> {
            private K key;
            private V value;
    
            public K getKey() {
                return key;
            }
    
            public V getValue() {
                return value;
            }
            public Pair(K k, V v) {
                key = k;
                value = v;
            }
        }
    }
    
    

    How to automate the applet build using Maven?

    To do this you need to have 2 projects: the applet project that will be built as a JAR file and the web application project that need to be deployed (as a result you will get WAR file).

    Correspondingly you should create a multi-module project which as modules will contain 2 of the above projects:

    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.jazzteam</groupId>
        <artifactId>applet-project</artifactId>
        <packaging>pom</packaging>
        <modules>
            <module>applet</module>
            <module>applet-web</module>
        </modules>
        <version>1.0-SNAPSHOT</version>
    </project>

    After the applet module building, you should copy the resulting JAR file in the web application.

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>site</phase>
                        <configuration>
                            <tasks>
                                <copy file="target\applet-eugliajar" 
    tofile="..\euglia-applet\src\main\webapp\applet-euglia.jar"/>
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    In this case the general project should be built with “clean package site“command, because in the “site” phase the files copying begin.

    In this approach the web application should contains HTML page that runs the applet.