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

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);
        }
    });
    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;

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

@Override
public Color getForeground() {
    if (m_enabled) {
        System.err.println("foreground color: " + super.getForeground());
        return super.getForeground();
    } else {
        System.err.println("foreground color: " + getDisabledTextColor());
        return getDisabledTextColor();
    }
}

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


现在的问题是前景色不变。文本窗格始终处于禁用状态。但是,“ getForeground”中的调试信息如下

setting textpane enabled to true
foreground color: javax.swing.plaf.ColorUIResource[r=0,g=0,b=0]
setting textpane enabled to false
foreground color: javax.swing.plaf.ColorUIResource[r=109,g=109,b=109]


这对我来说没问题,但文本窗格始终看起来可用

你有什么想法?

最佳答案

super.getForeground()在下一次调用中返回禁用的颜色,因为一旦将其设置为禁用的颜色,它还将传播到超类,如下所示:

这是直接来自JComponent的代码

public void setForeground(Color fg) {
    Color oldFg = getForeground();
super.setForeground(fg);
if ((oldFg != null) ? !oldFg.equals(fg) : ((fg != null) && !fg.equals(oldFg))) {
    // foreground already bound in AWT1.2
    repaint();
}
}





无需重写getForeground()方法,只需从setEnabled()方法中调用setForeground()方法即可。


在更新之前将默认前景色存储在某个地方,并在以后的调用中使用它。

你能试试这个吗

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;
    }
}

08-26 07:02