Tuomas Tikka
Tuomas Tikka

Reputation: 203

JTree background color on Linux with system look and feel

I am trying to customize a JTree to have a dark background and light foreground. My problem can be seen in the screenshot below:

JTree with partially customized background

What I end up with, is a partially customized background (the white is intended to be also black). The problem seems to occur on Ubuntu Linux 12.04 with OpenJDK 7. On Windows or Mac it looks ok. Also, if I switch to cross platform look and feel, it is ok. Below is the sample code:

package com.tt.examples;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.tree.DefaultTreeCellRenderer;

@SuppressWarnings("serial")
public class TreeExample extends JFrame {

    private TreeExample() {
        setTitle("TreeExample");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(320, 240);
        setLayout(new GridLayout(1, 1));
        JTree tree = new JTree();
        tree.setBackground(Color.BLACK);
        tree.setCellRenderer(new CustomTreeCellRenderer());
        JScrollPane scrollPane = new JScrollPane(tree);
        scrollPane.setBackground(Color.BLACK);
        add(scrollPane);
        setVisible(true);
    }

    private class CustomTreeCellRenderer extends DefaultTreeCellRenderer {

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
            setBackground(Color.BLACK);
            setBackgroundNonSelectionColor(Color.BLACK);
            setBackgroundSelectionColor(Color.GRAY);
            setBorderSelectionColor(Color.GRAY);
            setForeground(Color.WHITE);
            return (this);
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    // UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e) {
                    e.printStackTrace(System.err);
                }
                new TreeExample();
            }
        });
    }

}

Update: Tested on latest Linux Mint with Oracle JDK 7 and 8, and seems to show ok (as intended) there.

Update: Tested also on Ubuntu 12.04 with Oracle JDK 8 (update 25), but still no luck, so it seems it's not the JDK.

Upvotes: 2

Views: 680

Answers (1)

aterai
aterai

Reputation: 9818

Using a SynthStyle seems to work OK for me on Ubuntu 14.04 with OpenJDK 64-Bit(1.7.0_65):

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.plaf.synth.*;

public class TreeExample2 extends JFrame {
  private TreeExample2() {
    setTitle("TreeExample2");
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    JTree tree = new JTree();
    //tree.setBackground(Color.BLACK);
    tree.setOpaque(false);
    tree.setCellRenderer(new CustomTreeCellRenderer());
    JScrollPane scrollPane = new JScrollPane(tree);
    scrollPane.getViewport().setBackground(Color.BLACK);
    add(scrollPane);
    setSize(320, 240);
    setVisible(true);
  }
  private class CustomTreeCellRenderer extends DefaultTreeCellRenderer {
    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
      super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
      setBackground(Color.BLACK);
      setBackgroundNonSelectionColor(Color.BLACK);
      setBackgroundSelectionColor(Color.GRAY);
      setBorderSelectionColor(Color.GRAY);
      setForeground(Color.WHITE);
      return (this);
    }
  }
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        try {
          // UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
          SynthLookAndFeel.setStyleFactory(new MySynthStyleFactory(
              SynthLookAndFeel.getStyleFactory()));
        } catch (Exception e) {
          e.printStackTrace(System.err);
        }
        new TreeExample2();
      }
    });
  }
}

class MySynthStyleFactory extends SynthStyleFactory {
  private final SynthStyleFactory wrappedFactory;
  public MySynthStyleFactory(SynthStyleFactory factory) {
    super();
    this.wrappedFactory = factory;
  }
  @Override public SynthStyle getStyle(JComponent c, Region id) {
    SynthStyle s = wrappedFactory.getStyle(c, id);
    if (id == Region.TREE_CELL) {
      s = new TranslucentSynthSytle(s);
    }
    return s;
  }
}

class TranslucentSynthSytle extends SynthStyle {
  private final SynthStyle style;
  public TranslucentSynthSytle(SynthStyle style) {
    super();
    this.style = style;
  }
  @Override public Object get(SynthContext context, Object key) {
    return style.get(context, key);
  }
  @Override public boolean getBoolean(SynthContext context, Object key, boolean defaultValue) {
    return style.getBoolean(context, key, defaultValue);
  }
  @Override public Color getColor(SynthContext context, ColorType type) {
    return style.getColor(context, type);
  }
  @Override public Font getFont(SynthContext context) {
    return style.getFont(context);
  }
  @Override public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
    return style.getGraphicsUtils(context);
  }
  @Override public Icon getIcon(SynthContext context, Object key) {
    return style.getIcon(context, key);
  }
  @Override public Insets getInsets(SynthContext context, Insets insets) {
    return style.getInsets(context, insets);
  }
  @Override public int getInt(SynthContext context, Object key, int defaultValue) {
    return style.getInt(context, key, defaultValue);
  }
  @Override public SynthPainter getPainter(SynthContext context) {
    //return style.getPainter(context);
    return new SynthPainter() { /* do nothing */ };
  }
  @Override public String getString(SynthContext context,
                        Object key, String defaultValue) {
    return style.getString(context, key, defaultValue);
  }
  @Override public void installDefaults(SynthContext context) {
    style.installDefaults(context);
  }
  @Override public void uninstallDefaults(SynthContext context) {
    style.uninstallDefaults(context);
  }
  @Override public boolean isOpaque(SynthContext context) {
    return style.isOpaque(context);
  }
  @Override public Color getColorForState(SynthContext context, ColorType type) {
    return null;
  }
  @Override public Font getFontForState(SynthContext context) {
    return null;
  }
}

Upvotes: 1

Related Questions