【问题标题】:JTextPane and foreground colorJTextPane 和前景色
【发布时间】:2014-05-12 00:37:51
【问题描述】:

希望有一个 JTextPane,其内容始终可以由用户选择。因此,我创建了自己的 JTextPane 子类,并始终在方法“isEnabled()”中返回 true。另外我介绍了一个新成员 m_enabled,它负责返回正确的前景色(启用/禁用)。

它按预期工作,但如果我设置默认前景色(例如 Color.RED)并在启用和禁用之间切换,前景色将不再是红色。

你能帮我解决这个问题吗?

public class StylesExample1 {
public static final String text = "Lorem ipsum dolor...";
public static boolean m_enabled = true;

public static void main(String[] args) throws BadLocationException {
    try {
        UIManager
                .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {
    }

    JFrame f = new JFrame("Frame");
    final JTextPane pane = new MyPane();
    pane.setText(text);

    pane.setPreferredSize(new Dimension(200, 200));
    f.getContentPane().add(pane);
    JButton b = new JButton("Toggle Enabled state");
    b.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            m_enabled = !m_enabled;
            System.err.println("setting textpane enabled to " + m_enabled);
            pane.setEnabled(m_enabled);
        }
    });

    pane.setForeground(Color.red);

    f.getContentPane().add(b);
    f.getContentPane().setLayout(new FlowLayout());
    f.setSize(400, 300);
    f.setVisible(true);
}
}

class MyPane extends JTextPane {

private static final long serialVersionUID = 1L;
private boolean m_enabled = true;
private Color defaultForegroundColor, disabledTextColor;

public MyPane() {
    defaultForegroundColor = getForeground();
    disabledTextColor = getDisabledTextColor();
}

public void setEnabled(boolean enabled) {
    m_enabled = enabled;

    if (m_enabled) {
        setForeground(defaultForegroundColor);
    } else {
        setForeground(disabledTextColor);
    }
}

@Override
public boolean isEnabled() {
    return true;
}
}

【问题讨论】:

    标签: java swing colors jtextpane foreground


    【解决方案1】:
    • 您的类 MyPane extends JTextPane 不会覆盖 WindowsLookAndFeel 所需的细节和正确方法,

    • DeafultHightLigter/Painter/Caret/Selection 可能还有其他问题

    • (我建议)在 UIManager 中为 Windows(Classic)LookAndFeel 使用和覆盖键

    • 编辑来自UIManager by @camickr的键列表

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JTextPane;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.text.BadLocationException;
    
    public class StylesExample1 {
    
        private final String text = "Lorem ipsum dolor...";
        private boolean m_enabled = true;
    
        public StylesExample1() {
            final JTextPane pane = new MyPane();
            pane.setText(text);
            pane.setPreferredSize(new Dimension(200, 200));
            JButton b = new JButton("Toggle Enabled state");
            b.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    m_enabled = !m_enabled;
                    System.err.println("setting textpane enabled to " + m_enabled);
                    pane.setEnabled(m_enabled);
                }
            });
            pane.setDisabledTextColor(Color.red);
            pane.setForeground(Color.red);
            JFrame f = new JFrame("Frame");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(pane);
            f.add(b);
            f.getContentPane().setLayout(new FlowLayout());
            f.setSize(400, 300);
            f.setVisible(true);
        }
    
        public static void main(String[] args) throws BadLocationException {
            try {
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            } catch (Exception evt) {
            }
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new StylesExample1();
                }
            });
        }
    }
    
    class MyPane extends JTextPane {
    
        private static final long serialVersionUID = 1L;
        private boolean m_enabled = true;
        private Color defaultForegroundColor, disabledTextColor;
    
        public MyPane() {
            defaultForegroundColor = getForeground();
            disabledTextColor = getDisabledTextColor();
        }
    
        @Override
        public void setEnabled(boolean enabled) {
            m_enabled = enabled;
            if (m_enabled) {
                UIManager.put("TextPane.disabledBackground", Color.RED);
                UIManager.put("TextPane.foreground", Color.RED);
                UIManager.put("TextPane.inactiveForeground", Color.RED);
                SwingUtilities.updateComponentTreeUI(this); // don't to use this
            } else {
                UIManager.put("TextPane.disabledBackground", Color.RED);
                UIManager.put("TextPane.foreground", Color.RED);
                UIManager.put("TextPane.inactiveForeground", Color.RED);
                SwingUtilities.updateComponentTreeUI(this); // don't to use this
            }
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    

    【讨论】:

    • 在我的用例中,我需要在之后更改背景颜色。所以我不想硬编码红色。以后应该可以调整
    • 您可以传递任何(有效值)Color而不是Color.RED,您可以简单地使用defaultForegroundColor / disabledTextColor,通过构造函数或在局部变量中初始化的硬编码常量(枚举),并使用私有变量,现在您的问题是关于/仅如何从另一个类传递值(Swing 中的日常问题)
    【解决方案2】:

    在“MyPane”的构造函数中,将默认前景色设置为 JTextPane 的默认前景色,但在构造函数之后调用 setForeground(Color.red)。问题是 MyPane 中的“defaultForegroundColor”成员不知道它应该是红色的。进行以下调整:

    public MyPane(Color defaultForegroundColor)
    {
      this.defaultForegroundColor = defaultForegroundColor;
      this.disabledTextColor = getDisabledTextColor();
    }
    

    并使用以下代码创建它:

    final JTextPane pane = new MyPane(Color.red);
    

    如果要在构建后更改前景,请执行以下操作:

    public void setNewForeground(Color c)
    {
       this.defaultForegroundColor = c;
    }
    

    【讨论】:

    • 但是如果我想在构造函数被调用后改变前景色呢?
    • 我已经相应地修改了答案
    【解决方案3】:

    想要一个 JTextPane,其内容始终可以由用户选择。

    然后我会使用:

    setEditable( false );
    

    而不是

    setEnabled( false );
    

    【讨论】:

      猜你喜欢
      • 2014-05-10
      • 2014-01-06
      • 1970-01-01
      • 2012-10-28
      • 2021-02-13
      • 2010-10-03
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      相关资源
      最近更新 更多