Java bubble image adapt to text size

2019-07-29 04:28发布

I am trying to build some sort of messenger service but I am having issues with the rendering of a text bubble. I started by splitting a bubble into 9 images, The four corner would be static. Where I have an issue is the NORTH, SOUTH, EAST and WEST images.

I would like them to repeat themselves similar to the CSS option repeat. Basically, adapting the bubble to the content.

I looked around but a lot are Android or IOS solutions. Is there a repeat functionality in Java and can do this without re-sizing the image inside the paintComponent which causes the image to be distorted.

Here is what I got for the moment when I try to generate a bubble:

bubble 1 bubble 2

Any ideas are welcome!

3条回答
疯言疯语
2楼-- · 2019-07-29 04:58

One can scale the images with Graphics.drawImage(x, y, w, h, null). For north and south scale the width of a an image of 1 pixel width, and similar for east and west.

查看更多
Viruses.
3楼-- · 2019-07-29 05:00

To add on to @Joop Eggen's answer, you basically need to scale your north and south images to be the necessary width and your east and west images to be the necessary height.

It would look something like below. You would have 8 or 9 images, depending on whether you had a center image. You would scale the north and south to width of innerWidth = outerWidth - 2 * borderWidth; your east and west would be scaled vertically to a height of innerHeight = outerHeight - 2 * borderHeight.

enter image description here

查看更多
Evening l夕情丶
4楼-- · 2019-07-29 05:19

You have (at least) two options available to you. You can tile the image elements as required or you can scale them to fit.

While I have no doubt scaling will work, how good it looks will depend on how good the source image is and may produce undesirable artifacts as the image is scaled.

Alternatively, you could tile the images to fill the available space. Based on the size and complexity of the image and the area being tilted, this may take some time to renderer.

Obviously the time to tile/scale and image can mitigated by buffering the result and only re-generating the output when it changes.

The final solution will come down to exactly what it is you hope to achieve.

The following is a tiled exampled

BubbleTextBubbleTtext

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BubbleTextTest {

    public static void main(String[] args) {
        new BubbleTextTest();
    }

    public BubbleTextTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel label;

        public TestPane() {

            String text = "<html>I am the very model of a modern Major-General,<br>";
            text += "I've information vegetable, animal, and mineral,<br>";
            text += "I know the kings of England, and I quote the fights historical<br>";
            text += "From Marathon to Waterloo, in order categorical;a<br>";
            text += "I'm very well acquainted, too, with matters mathematical,<br>";
            text += "I understand equations, both the simple and quadratical,<br>";
            text += "About binomial theorem I'm teeming with a lot o' news, (bothered for a rhyme)<br>";
            text += "With many cheerful facts about the square of the hypotenuse.<br>";

            label = new JLabel(text);

            setBackground(new Color(209, 209, 209));

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            try {
                add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/TopLeft.png")))), gbc);
                gbc.gridx = 2;
                add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/TopRight.png")))), gbc);

                gbc.gridy = 2;
                gbc.gridx = 0;
                add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/BottomLeft.png")))), gbc);
                gbc.gridx = 2;
                add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/BottomRight.png")))), gbc);

                gbc.gridx = 1;
                gbc.gridy = 0;
                gbc.weightx = 1;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                add(new FillerPane(ImageIO.read(getClass().getResource("/Top.png")), FillDirection.HORIZONTAL), gbc);
                gbc.gridy = 2;
                add(new FillerPane(ImageIO.read(getClass().getResource("/Bottom.png")), FillDirection.HORIZONTAL), gbc);

                gbc.gridx = 0;
                gbc.gridy = 1;
                gbc.weighty = 1;
                gbc.weightx = 0;
                gbc.fill = GridBagConstraints.VERTICAL;
                add(new FillerPane(ImageIO.read(getClass().getResource("/Left.png")), FillDirection.VERTICAL), gbc);
                gbc.gridx = 2;
                add(new FillerPane(ImageIO.read(getClass().getResource("/Right.png")), FillDirection.VERTICAL), gbc);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            gbc.gridx = 1;
            gbc.gridy = 1;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;
            add(label, gbc);
        }

    }

    public enum FillDirection {
        HORIZONTAL,
        VERTICAL
    }

    public class FillerPane extends JPanel {

        private BufferedImage img;
        private FillDirection fillDirection;

        public FillerPane(BufferedImage img, FillDirection fillDirection) {
            this.img = img;
            this.fillDirection = fillDirection;
        }

        @Override
        public Dimension getPreferredSize() {
            return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
        }

        @Override
        public Dimension getMinimumSize() {
            return getPreferredSize();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = 0;
                int y = 0;
                int xDelta = 0;
                int yDelta = 0;
                switch (fillDirection) {
                    case HORIZONTAL:
                        xDelta = img.getWidth();
                        break;
                    case VERTICAL:
                        yDelta = img.getHeight();
                        break;
                }
                while (x < getWidth() && y < getHeight()) {
                    g2d.drawImage(img, x, y, this);
                    x += xDelta;
                    y += yDelta;
                }
                g2d.dispose();
            }
        }

    }

}
查看更多
登录 后发表回答