I am having trouble getting a JSplitPane to maintain the same relative position when its container is resized. If the split pane is assumed to have a fixed position everything works fine. I can get the divider location to stay close to the same relative position using the code shown below but the divider shifts to the left when the JFrame is resized. The shift is larger if the JFrame is resized slowly. The shift is to the left if the JFrame is made smaller or larger.
How do I get the divider to stay in the exact same proportional location?
This is what the GUI initially looks like.
This is what it looks like after several resizings.
And this is what the code looks like. This attempt is based on the information provided here:
JSplitPane splitting 50% precisely
JSplitPane SetDividerLocation Problem
https://docs.oracle.com/javase/tutorial/uiswing/components/splitpane.html
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
public class Example {
public static void main(String[] args) {
new Example().showGui();
}
private void showGui() {
// create the jframe
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setSize(400, 200);
// create the left and right panels
JPanel left = new JPanel();
left.setBackground(Color.yellow);
JPanel right = new JPanel();
right.setBackground(Color.orange);
ResizableSplitPane split = new ResizableSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right, jFrame);
jFrame.getContentPane().add(split);
// show the gui
jFrame.setVisible(true);
}
public class ResizableSplitPane extends JSplitPane {
//
// instance variables
//
private boolean painted;
private double defaultDividerLocation;
private ResizableSplitPane resizableSplitPane = this;
private double currentDividerLocation;
private Component first;
private Component second;
private boolean dividerPositionCaptured = false;
//
// constructors
//
public ResizableSplitPane(int splitType, Component first, Component second, Component parent) {
this(splitType, first, second, parent, 0.5);
}
public ResizableSplitPane(int splitType, Component first, Component second, Component parent, double defaultDividerLocation) {
super(splitType, first, second);
this.defaultDividerLocation = defaultDividerLocation;
this.currentDividerLocation = defaultDividerLocation;
this.setResizeWeight(defaultDividerLocation);
this.first = first;
this.second = second;
parent.addComponentListener(new DividerLocator());
first.addComponentListener(new DividerMovedByUserComponentAdapter());
}
//
// trivial getters and setters
//
public double getDefaultDividerLocation() {
return defaultDividerLocation;
}
public void setDefaultDividerLocation(double defaultDividerLocation) {
this.defaultDividerLocation = defaultDividerLocation;
}
//
// implementation
//
@Override
public void paint(Graphics g) {
super.paint(g);
if (!painted) {
painted = true;
this.setDividerLocation(currentDividerLocation);
}
dividerPositionCaptured = false;
}
private class DividerLocator extends ComponentAdapter {
@Override
public void componentResized(ComponentEvent e) {
setDividerLocation(currentDividerLocation);
}
}
private class DividerMovedByUserComponentAdapter extends ComponentAdapter {
@Override
public void componentResized(ComponentEvent e) {
if (dividerPositionCaptured == false) {
dividerPositionCaptured = true;
currentDividerLocation = (double) first.getWidth() / (double) (first.getWidth() + second.getWidth());
System.out.println(currentDividerLocation);
}
}
}
}
}