通常我们改变一个SWING的外观有两种方法,一种是UIManager.put("","");就可以了.但是这里的主键必须是已经有的.如:
UIManager.put("ProgressBarUI","com.test.MyProgressBarUI");
另一种是设置ComponentUI,
如:
JProgressBar jpb;
jpb.setUI(new MyProgressBarUI());
即可
下面我们来改写一下JSplitPane的UI.当我们调用setUI时提示的类是"SplitPaneUI",这个类是个抽象类,我们查看它的子类,它有BasicSplitPaneUI, MultiSplitPaneUI ,前者是SplitPaneUI 的基本 L&F 实现,后者是用于组合 SplitPaneUI
的多路 UI.所以我们重写前者.我们查看这个类的源码.可以看到,它主要有两个JButton,和一个Divider.
所以重点重写下面三个函数.
public BasicSplitPaneDivider createDefaultDivider() {}
protected JButton createLeftOneTouchButton() {}
protected JButton createRightOneTouchButton() { }
重写成我们想要的效果就可以了.
下面是个人修改之后的效果
UI源码如下:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.lgh.mail.components;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import sun.swing.DefaultLookup;
/**
*
* @author lgh
*/
public class SearchSplitPaneUI extends BasicSplitPaneUI {
private static final Color BG_COLOR = Color.BLACK;
private static final SearchSplitPaneUI cornerButtonUI = new SearchSplitPaneUI();
public SearchSplitPaneUI() {
super();
}
public static ComponentUI createUI(JComponent c) {
return new SearchSplitPaneUI();
}
@Override
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
g.setColor(Color.BLACK);
int width = c.getWidth();
int height = c.getHeight();
g.drawRect(3, 3, width - 6, height - 6);
}
/**
* Creates the default divider.
*/
@Override
public BasicSplitPaneDivider createDefaultDivider() {
return new MyBasicSplitPaneDivider(this);
}
private class MyBasicSplitPaneDivider extends BasicSplitPaneDivider {
private int oneTouchSize, oneTouchOffset;
boolean centerOneTouchButtons;
//center空白区域
private int x1, y1;
@SuppressWarnings("unchecked")
public MyBasicSplitPaneDivider(SearchSplitPaneUI ui) {
super(ui);
// oneTouchSize = DefaultLookup.getInt(ui.getSplitPane(), ui,
// "SplitPane.oneTouchButtonSize", ONE_TOUCH_SIZE);
// oneTouchOffset = DefaultLookup.getInt(ui.getSplitPane(), ui,
// "SplitPane.oneTouchButtonOffset", ONE_TOUCH_OFFSET);
// centerOneTouchButtons = DefaultLookup.getBoolean(ui.getSplitPane(),
// ui, "SplitPane.centerOneTouchButtons", true);
oneTouchSize = ONE_TOUCH_SIZE;
oneTouchOffset = ONE_TOUCH_OFFSET;
centerOneTouchButtons = true;
setLayout(new DividerLayout());
setBasicSplitPaneUI(ui);
orientation = splitPane.getOrientation();
setCursor((orientation == JSplitPane.HORIZONTAL_SPLIT) ? Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
setBackground(UIManager.getColor("SplitPane.background"));
// super(ui);
// this.setBackground(BG_COLOR);
// this.setPreferredSize(getSize());
}
private void revalidate() {
invalidate();
if (splitPane != null) {
splitPane.revalidate();
}
}
/**
* Creates and return an instance of JButton that can be used to
* collapse the right component in the split pane.
*/
@Override
protected JButton createRightOneTouchButton() {
JButton b = new JButton() {
public void setBorder(Border border) {
}
@Override
public void paint(Graphics g) {
if (splitPane != null) {
int[] xs = new int[3];
int[] ys = new int[3];
int blockSize;
// Fill the background first ...
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(),
this.getHeight());
// ... then draw the arrow.
if (orientation == JSplitPane.VERTICAL_SPLIT) {
blockSize = Math.min(getHeight(), oneTouchSize);
xs[0] = blockSize;
xs[1] = blockSize << 1;
xs[2] = 0;
ys[0] = blockSize;
ys[1] = ys[2] = 0;
} else {
blockSize = Math.min(getWidth(), oneTouchSize);
xs[0] = xs[2] = 0;
xs[1] = blockSize;
ys[0] = 0;
ys[1] = blockSize;
ys[2] = blockSize << 1;
}
g.setColor(BG_COLOR);
g.fillPolygon(xs, ys, 3);
}
}
// Don't want the button to participate in focus traversable.
public boolean isFocusTraversable() {
return false;
}
};
b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize));
b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
b.setFocusPainted(false);
b.setBorderPainted(false);
b.setRequestFocusEnabled(false);
return b;
}
/**
* Creates and return an instance of JButton that can be used to
* collapse the left component in the split pane.
*/
protected JButton createLeftOneTouchButton() {
JButton b = new JButton() {
public void setBorder(Border b) {
}
public void paint(Graphics g) {
if (splitPane != null) {
int[] xs = new int[3];
int[] ys = new int[3];
int blockSize;
// Fill the background first ...
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(),
this.getHeight());
// ... then draw the arrow.
g.setColor(BG_COLOR);
if (orientation == JSplitPane.VERTICAL_SPLIT) {
blockSize = Math.min(getHeight(), oneTouchSize);
xs[0] = blockSize;
xs[1] = 0;
xs[2] = blockSize << 1;
ys[0] = 0;
ys[1] = ys[2] = blockSize;
g.drawPolygon(xs, ys, 3); // Little trick to make the
// arrows of equal size
} else {
blockSize = Math.min(getWidth(), oneTouchSize);
xs[0] = xs[2] = blockSize;
xs[1] = 0;
ys[0] = 0;
ys[1] = blockSize;
ys[2] = blockSize << 1;
}
g.fillPolygon(xs, ys, 3);
}
}
// Don't want the button to participate in focus traversable.
public boolean isFocusTraversable() {
return false;
}
};
b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize));
b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
b.setFocusPainted(false);
b.setBorderPainted(false);
b.setRequestFocusEnabled(false);
return b;
}
@Override
public void paint(Graphics g) {
super.paint(g);
Dimension size = getSize();
g.setColor(BG_COLOR);
g.fillRect(1, 1, size.width - 1, size.height - 1);
g.setColor(Color.GRAY);
g.drawRect(0, 0, size.width, size.height);
g.setColor(Color.WHITE);
//分为水平时跟垂直时,白色区域
if (orientation == JSplitPane.VERTICAL_SPLIT) {
g.fillRect(x1, 1, 30, size.height - 1);
} else {
g.fillRect(1, y1, size.width - 1, 30);
}
if (leftButton != null) {
leftButton.repaint();
}
if (rightButton != null) {
rightButton.repaint();
}
}
/**
* Used to layout a <code>BasicSplitPaneDivider</code>.
* Layout for the divider
* involves appropriately moving the left/right buttons around.
* <p>
*/
protected class DividerLayout implements LayoutManager {
public void layoutContainer(Container c) {
if (leftButton != null && rightButton != null) {
if (splitPane.isOneTouchExpandable()) {
Insets insets = getInsets();
if (orientation == JSplitPane.VERTICAL_SPLIT) {
int extraX = (insets != null) ? insets.left : 0;
int blockSize = getHeight();
if (insets != null) {
blockSize -= (insets.top + insets.bottom);
blockSize = Math.max(blockSize, 0);
}
blockSize = Math.min(blockSize, oneTouchSize);
int y = (c.getSize().height - blockSize) / 2;
if (!centerOneTouchButtons) {
y = (insets != null) ? insets.top : 0;
extraX = 0;
}
int width = (int) MyBasicSplitPaneDivider.this.getSize().getWidth();
x1 = width / 2 - oneTouchSize;
leftButton.setBounds(extraX - oneTouchOffset + width / 2, y,
blockSize * 2, blockSize);
rightButton.setBounds(extraX - oneTouchOffset +
oneTouchSize * 2 + width / 2, y,
blockSize * 2, blockSize);
} else {
int extraY = (insets != null) ? insets.top : 0;
int blockSize = getWidth();
if (insets != null) {
blockSize -= (insets.left + insets.right);
blockSize = Math.max(blockSize, 0);
}
blockSize = Math.min(blockSize, oneTouchSize);
int x = (c.getSize().width - blockSize) / 2;
if (!centerOneTouchButtons) {
x = (insets != null) ? insets.left : 0;
extraY = 0;
}
int height = (int) MyBasicSplitPaneDivider.this.getSize().getHeight();
y1 = height / 2 - oneTouchSize;
leftButton.setBounds(x, extraY - oneTouchOffset + height / 2,
blockSize, blockSize * 2);
rightButton.setBounds(x, extraY - oneTouchOffset +
oneTouchSize * 2 + height / 2, blockSize,
blockSize * 2);
}
} else {
leftButton.setBounds(-5, -5, 1, 1);
rightButton.setBounds(-5, -5, 1, 1);
}
}
}
public Dimension minimumLayoutSize(Container c) {
// NOTE: This isn't really used, refer to
// BasicSplitPaneDivider.getPreferredSize for the reason.
// I leave it in hopes of having this used at some point.
if (splitPane == null) {
return new Dimension(0, 0);
}
Dimension buttonMinSize = null;
if (splitPane.isOneTouchExpandable() && leftButton != null) {
buttonMinSize = leftButton.getMinimumSize();
}
Insets insets = getInsets();
int width = getDividerSize();
int height = width;
if (orientation == JSplitPane.VERTICAL_SPLIT) {
if (buttonMinSize != null) {
int size = buttonMinSize.height;
if (insets != null) {
size += insets.top + insets.bottom;
}
height = Math.max(height, size);
}
width = 1;
} else {
if (buttonMinSize != null) {
int size = buttonMinSize.width;
if (insets != null) {
size += insets.left + insets.right;
}
width = Math.max(width, size);
}
height = 1;
}
return new Dimension(width, height);
}
public Dimension preferredLayoutSize(Container c) {
return minimumLayoutSize(c);
}
public void removeLayoutComponent(Component c) {
}
public void addLayoutComponent(String string, Component c) {
}
} // End of class BasicSplitPaneDivider.DividerLayout
}
}