4

JPanel に JTextArea を配置しました。この JPanel には背景に画像があり、JTextArea は背景が透けて見えるように半透明 (半透明の赤) になっています。ユーザーがテキストを編集または選択できるようにしたくないので、JLabelとして機能させたいです(ただし、複数の行があり、ワードラップが簡単で、画面のサイズ変更に合わせて調整できます)。

これらすべてのオプションを試しました:

text.setEditable(false);
text.setFocusable(false);
text.setEnabled(false);
text.setHighlighter(null);

それでも、ユーザーがマウスを JTextArea の上にドラッグすると、色がいくらか変化します。誰が何が起こっているのか知っていますか?

4

1 に答える 1

3

コンポーネントの背景色を単純に「透明」に設定して、Swing がそれを処理することを期待することはできません。コンポーネントに透明 ( ) のフラグを付ける必要がありますsetOpaque(false)。そうして初めて、Swing の再描画マネージャーは、その下のコンポーネントを更新する必要があることを認識します。

これにより、背景をどのようにペイントするかという問題が生じます (Swing には完全に不透明または完全に透明という概念しかないため)。

これを行うには、独自のペイント ルーチン (オーバーライドpaintComponent、背景の塗りつぶし、コンポーネントの更新) を提供する必要があります...これは基本的にRob Camick のソリューションが行っていることであり、適切なラッパー コンポーネントを提供するだけです...

JLabel以下は、 HTML でラップされたテキストと を使用する例ですJTextArea。どちらも「半透明」をサポートするように更新されています...

を使ってJLabel

ここに画像の説明を入力

を使ってJTextArea

ここに画像の説明を入力

さて、Rob のラッパー クラスを使用する方がはるかに簡単ですが、これにより、何が問題であり、それを修正するために何をする必要があるかがわかります。

public class MultiLineLabel {

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

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

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

    public class TransclucentLabel extends JLabel {

        public TransclucentLabel(String text) {
            super(text);
            setVerticalAlignment(TOP);
        }

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            Insets insets = getInsets();
            int x = insets.left;
            int y = insets.top;
            int width = getWidth() - (insets.left + insets.right);
            int height = getHeight() - (insets.top + insets.bottom);
            g2d.setColor(new Color(255, 0, 0, 128));
            g2d.fillRect(x, y, width, height);
            super.paintComponent(g);
        }
    }

    public class TransclucentTextArea extends JTextArea {

        public TransclucentTextArea(String text) {
            super(text);
            setOpaque(false);
            setLineWrap(true);
            setWrapStyleWord(true);
        }

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            Insets insets = getInsets();
            int x = insets.left;
            int y = insets.top;
            int width = getWidth() - (insets.left + insets.right);
            int height = getHeight() - (insets.top + insets.bottom);
            g2d.setColor(new Color(255, 0, 0, 128));
            g2d.fillRect(x, y, width, height);
            super.paintComponent(g);
        }
    }

    public class BackgroundPane extends JPanel {

        private BufferedImage background;

        public BackgroundPane() {
            setLayout(new BorderLayout());
//            addLabel();
            addTextArea();
            setBorder(new EmptyBorder(24, 24, 24, 24));

            try {
                background = ImageIO.read(new File("/path/to/your/image"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        protected void addTextArea() {
            StringBuilder sb = new StringBuilder(128);
            sb.append("I put a JTextArea in a JPanel. This JPanel has a picture on the background, and the JTextArea is translucent (translucid red) to show the background through. I don't want the user to be able to edit or select the text, I want it to act just as a JLabel (but with multiple lines and easy to word wrap and adjust to screen resize).\n\n");
            sb.append("I tried all these options:\n\n");
            sb.append("text.setEditable(false);\n");
            sb.append("text.setFocusable(false);\n");
            sb.append("text.setEnabled(false);\n");
            sb.append("text.setHighlighter(null);\n\n");
            sb.append("but still some change of color happens as the user drags the mouse over the JTextArea. Anyone knows what is going on?\n");
            add(new TransclucentTextArea(sb.toString()));
        }

        protected void addLabel() {
            StringBuilder sb = new StringBuilder(128);
            sb.append("<html>");
            sb.append("<p>I put a JTextArea in a JPanel. This JPanel has a picture on the background, and the JTextArea is translucent (translucid red) to show the background through. I don't want the user to be able to edit or select the text, I want it to act just as a JLabel (but with multiple lines and easy to word wrap and adjust to screen resize).</p><br>");
            sb.append("<p>I tried all these options:</p><br>");
            sb.append("<p>text.setEditable(false);<br>");
            sb.append("text.setFocusable(false);<br>");
            sb.append("text.setEnabled(false);<br>");
            sb.append("text.setHighlighter(null);</p><br>");
            sb.append("<p>but still some change of color happens as the user drags the mouse over the JTextArea. Anyone knows what is going on?</p>");
            add(new TransclucentLabel(sb.toString()));

        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g.drawImage(background, x, y, this);
            }
        }
    }
}
于 2013-01-15T00:59:44.113 に答える