如何在禁用突出显示的其他组件中安排透明的 JTextPane

Posted

技术标签:

【中文标题】如何在禁用突出显示的其他组件中安排透明的 JTextPane【英文标题】:How to arrange a transparent JTextPane in other components with disabled highlighting 【发布时间】:2021-03-07 14:54:21 【问题描述】:

有人可以给我一个提示,告诉我如何显示一个透明的JTextPane,它是其他组件的孩子,例如JScrollPaneJPanel,拜托。我使用了AlphaContainer,它可以通过here 获得以提高透明度。

这是有效的:

chatTextPane = new JTextPane();
chatTextPane.setEditable(false);
chatTextPane.setHighlighter(null);
chatTextPane.setBackground(new Color(255,255,255,100));
AlphaContainer ac = new AlphaContainer(chatTextPane);   

JPanel chatPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
chatPanel.setOpaque(false);
chatPanel.add(ac);

看起来像这样:

但是,如果我将它包装成一个不透明的JScrollPane,它就不再透明了。如果我将JScrollPane 放在AlphaContainer 中,则会再次启用突出显示(并且有问题):

chatTextPane = new JTextPane();
chatTextPane.setEditable(false);
chatTextPane.setHighlighter(null);
chatTextPane.setBackground(new Color(255,255,255,100));
JScrollPane scrollPane = new JScrollPane(chatTextPane);
scrollPane.setOpaque(false);
AlphaContainer ac = new AlphaContainer(scrollPane);

JPanel chatPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
chatPanel.setOpaque(false);
chatPanel.add(ac);

它看起来像这样:

最后,我最初想将它添加到另一个面板中,JTextField 也包含在 BoxLayout 中。如果我尝试这样做,JTextField 会显示两次:一次正确显示在底部,但也显示在顶部(不可编辑)。

我已经尝试解决这个问题几个小时了,我很感激任何事情。

这是第二个示例的可运行代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MyClass 
    public static void main(String args[]) 
        new MyClass();
    

    public MyClass() 
        EventQueue.invokeLater(new Runnable() 

            @Override
            public void run() 
                try 
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                 catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                        | UnsupportedLookAndFeelException ex) 
                    ex.printStackTrace();
                

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().setBackground(new Color(100, 0, 0, 255));

                //
                JTextPane chatTextPane = new JTextPane();
                chatTextPane.setEditable(false);
                chatTextPane.setHighlighter(null);
                chatTextPane.setPreferredSize(new Dimension(300, 300));
                chatTextPane.setBackground(new Color(255,255,255,100));
                chatTextPane.setText("testtesttesttesttesttest");
                JScrollPane scrollPane = new JScrollPane(chatTextPane);
                scrollPane.setOpaque(false);
                AlphaContainer ac = new AlphaContainer(scrollPane);

                JPanel chatPanel = new JPanel();
                chatPanel.setOpaque(false);
                chatPanel.add(ac);              
                //
                
                frame.add(chatPanel);
                frame.pack();
                frame.setVisible(true);
            

        );
    

    private class AlphaContainer extends JComponent 
        private JComponent component;

        public AlphaContainer(JComponent component) 
            this.component = component;
            setLayout(new BorderLayout());
            setOpaque(false);
            component.setOpaque(false);
            add(component);
        

        /**
         * Paint the background using the background Color of the contained component
         */
        @Override
        public void paintComponent(Graphics g) 
            g.setColor(component.getBackground());
            g.fillRect(0, 0, getWidth(), getHeight());
        
    

【问题讨论】:

但是,如果我将它包装成一个不透明的 JScrollPane,它就不再透明了。 - 文本窗格是透明的,但滚动窗格不是透明的,并且滚动窗格的视口不透明。发布您的 minimal reproducible example 来证明问题。 我上传了无效示例的可运行代码here 代码应该在这里发布在论坛中,这样我们就可以看到代码,而无需点击另一个网站的链接。 我已将代码添加到问题中 (1+) 不错minimal reproducible example.. 【参考方案1】:

Swing 组件具有父/子关系。在您的情况下,它看起来像:

JFrame 内容窗格(带有自定义背景颜色) 聊天面板 JScrollPane JViewport JTextPane

Swing 在子组件之前绘制父组件。因此,您希望首先绘制内容窗格(不透明),然后绘制“ChatPanel”(将是半透明的),然后再绘制所有其他子组件不透明。

所以有几个变化:

    AlphaContainer 需要用于添加到内容窗格的组件。

您可以使用:

//frame.add(chatPanel);
frame.add( new AlphaContainer(chatPanel) );

注意:AlphaContainer 将使添加到其中的组件不透明,因此您无需显式使用 setOpaque( false );

    您需要使 JTextPane 不透明(因为没有单独添加到 AlphaContainer)。

    您还需要使JViewport 不透明。

这是通过使用:

scrollPane.getViewport().setOpaque( false );

也不要使用:

chatTextPane.setPreferredSize(new Dimension(300, 300));

只有当组件的首选大小大于滚动窗格的大小时,才会出现滚动条。如果您硬编码首选大小,则滚动条不会出现,因为首选大小不会随着您向文本区域添加文本而改变。

在滚动窗格上设置首选大小。

【讨论】:

以上是关于如何在禁用突出显示的其他组件中安排透明的 JTextPane的主要内容,如果未能解决你的问题,请参考以下文章

如何完全禁用 JTextPane 的文本突出显示?

如何在 Flutter 中禁用 FlatButton 的飞溅突出显示?

使视图变暗,就像禁用一样

如何在不禁用突出显示的情况下禁用合适的触摸行

如何禁用 html 或 JS 中的突出显示?

如何在 iOS 的标签栏中禁用蓝色突出显示?