Why does JSplitPane add a border to my components, and how do I stop it?
-
06-07-2021 - |
Frage
JSplitPane
seems to add a border to any Component
added to it.
This is most visible with nested JSplitPanes - e.g.:
public class JSplitPaneToy {
public static void main(String[] args) {
JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
makePanel(), makePanel());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
JFrame frame = new JFrame("JSplitPane Toy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(sp);
frame.pack();
frame.setVisible(true);
}
private static JScrollPane makePanel() {
JScrollPane pane = new JScrollPane(new JTable(
new Object[][]{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}, new Object[]{1, 2, 3}));
pane.setPreferredSize(new Dimension(200, 100));
return pane;
}
}
i.e. each subsequent nested component appears to be set further back - i.e. there is some form of shadow border being added.
- Why is this border being added? (Is this actually a border being added...?)
- How can I prevent this 'border' from being added?
Lösung
If you want to drop those borders on all JSplitPane, you can change the defaults of the UI like this. However, I usually try not to mess with UI-defaults.
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class JSplitPaneToy {
public static void main(String[] args) {
UIManager.getDefaults().put("SplitPane.border", BorderFactory.createEmptyBorder());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JSplitPaneToy().initUI();
}
});
}
public void initUI() {
JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), makePanel());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
JFrame frame = new JFrame("JSplitPane Toy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(sp);
frame.pack();
frame.setVisible(true);
}
private JScrollPane makePanel() {
JScrollPane pane = new JScrollPane(new JTable(new Object[][] { { 0, 1, 2 }, { 1, 2, 3 }, { 2, 3, 4 } }, new Object[] { 1, 2, 3 }));
pane.setPreferredSize(new Dimension(200, 100));
return pane;
}
}
You may want to have a look at the JXMultiSplitPane of the SwingX project, instead of nesting so many splitpanes.
Andere Tipps
We use this method to "flatten" a JSplitPane. Perhaps this is what you are looking for:
/**
* Makes a split pane invisible. Only contained components are shown.
*
* @param splitPane
*/
public static void flattenJSplitPane(JSplitPane splitPane) {
splitPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
BasicSplitPaneUI flatDividerSplitPaneUI = new BasicSplitPaneUI() {
@Override
public BasicSplitPaneDivider createDefaultDivider() {
return new BasicSplitPaneDivider(this) {
@Override
public void setBorder(Border b) {
}
};
}
};
splitPane.setUI(flatDividerSplitPaneUI);
splitPane.setBorder(null);
}
As for why the borders get added, would not know. Apparently its some sort of a feature. We found it to be an unwanted one and the above method works around it. There's probably a simpler way of dealing with this problem, but hey, when you find somethig that works, you stop looking for alternatives.
I used this, to reset the border form the Divider.
SplitPaneUI ui = sp.getUI();
if( ui instanceof BasicSplitPaneUI ) {
((BasicSplitPaneUI)ui).getDivider().setBorder( null );
}
NOTE: your Example doesnt work splitPane
is unknown, it should be sp
.
public class JSplitPaneToy {
public static void main(String[] args) {
JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), makePanel());
SplitPaneUI ui = sp.getUI();
if( ui instanceof BasicSplitPaneUI ) {
((BasicSplitPaneUI)ui).getDivider().setBorder( null );
}
sp.setBorder( BorderFactory.createEmptyBorder() );
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if( ui instanceof BasicSplitPaneUI ) {
((BasicSplitPaneUI)ui).getDivider().setBorder( null );
}
sp.setBorder( BorderFactory.createEmptyBorder() );
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if( ui instanceof BasicSplitPaneUI ) {
((BasicSplitPaneUI)ui).getDivider().setBorder( null );
}
sp.setBorder( BorderFactory.createEmptyBorder() );
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
ui = sp.getUI();
if( ui instanceof BasicSplitPaneUI ) {
((BasicSplitPaneUI)ui).getDivider().setBorder( null );
}
sp.setBorder( BorderFactory.createEmptyBorder() );
JFrame frame = new JFrame("JSplitPane Toy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(sp);
frame.pack();
frame.setVisible(true);
}
private static JScrollPane makePanel() {
JScrollPane pane = new JScrollPane(new JTable(
new Object[][]{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}, new Object[]{1, 2, 3}){
});
pane.setPreferredSize(new Dimension(200, 100));
return pane;
}
}
An alternative answer is to set each Component
on the JSplitPane
to have an empty border - e.g.
JComponent a = ...;
JComponent b = ...;
a.setBorder(BorderFactory.createEmptyBorder());
b.setBorder(BorderFactory.createEmptyBorder());
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, a, b);
Just override setBroder by JScrollPane like that
public class MyScrollPane extends JScrollPane {
...
@Override
public void setBorder(Border b) {}
}