我想實現JSplitPane(水平分割),其中右側分量具有恆定的寬度,即當分隔符被拖動時,它將跳回正確的大小,除非分頻器被拖動得足夠遠,在這種情況下,最右邊的分量將具有零寬度。檢測何時正在拖動JSplitPane分隔符,而不是正在調整大小的組件
要重新顯示右分量則用戶可以拖動分隔得足夠遠到左邊。
我有這個主要工作,但當我調整窗口的大小取決於多少和多快我改變窗口大小分頻器跳轉顯示或隱藏正確的組件,在那裏我想要的是它不應該改變「國家」,即如果有合適的成分是不可見的,那麼它應該是不可見的,反之亦然。
我已經嘗試了很多東西,但主要障礙是似乎沒有辦法知道天氣分隔線是由用戶通過鼠標拖動或者如果代碼(我的分隔線邏輯和/或JSplitPane內部邏輯)改變了分隔位置。
這裏是一個自包含的測試用例,運行它,並嘗試拖動水平分隔來隱藏和顯示在右側面板和那些隱藏/顯示嘗試調整窗口。
如預期在Mac OS X的Java 1.6(蘋果)或Java 7(甲骨文)不起作用。對於Oracle來說,渲染速度要慢得多,問題更嚴重。調整窗口大小緩慢工作,但窗口大小快速變化會導致問題。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import net.miginfocom.swing.MigLayout;
public class SplitTest {
public static class MySplitPane extends JSplitPane {
boolean m_RightCollapsed;
public MySplitPane(int orientation, JComponent left, JComponent right) {
super(orientation, left, right);
addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
}
});
addComponentListener(new ComponentListener() {
@Override
public void componentShown(ComponentEvent e) {
reposDivider();
}
@Override
public void componentResized(ComponentEvent e) {
reposDivider();
}
@Override
public void componentMoved(ComponentEvent e) {
reposDivider();
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
}
public void reposDivider() {
setDividerLocation(getDividerLocation());
}
public void setDividerLocation(int location) {
int newLocation;
m_RightCollapsed = location > getSize().width - getRightComponent().getPreferredSize().width/2;
if (m_RightCollapsed)
newLocation = getSize().width;
else
newLocation = getSize().width - getInsets().right - getDividerSize() - getRightComponent().getPreferredSize().width;
super.setDividerLocation(newLocation);
}
}
static class MyScrollable extends JPanel implements Scrollable {
int m_Height;
public MyScrollable(int height) {
m_Height = height;
}
@Override
public void paint(java.awt.Graphics g) {
super.paint(g);
g.setColor(Color.CYAN);
g.fillOval(0, 0, getWidth(), 500);
}
@Override
public Dimension getPreferredScrollableViewportSize() {
//return super.getPreferredSize();
return new Dimension(100, m_Height);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
// TODO Auto-generated method stub
return 10;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 20;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
public static class ShrinkGrow extends JPanel {
public ShrinkGrow(final JComponent component, final JSplitPane split) {
JButton grow = new JButton("+++");
JButton shrink = new JButton("---");
add(grow);
add(shrink);
grow.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Dimension oldSize = component.getPreferredSize();
Dimension newSize = new Dimension(oldSize.width, oldSize.height + 10);
component.setPreferredSize(newSize);
component.setSize(newSize);
}
});
shrink.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Dimension oldSize = component.getPreferredSize();
Dimension newSize = new Dimension(oldSize.width, oldSize.height - 10);
component.setPreferredSize(newSize);
component.setSize(newSize);
}
});
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
JPanel mainView = new JPanel();
JPanel top = new JPanel();
top.setLayout(new BoxLayout(top, BoxLayout.Y_AXIS));
JPanel bottom = new JPanel();
bottom.setLayout(new BoxLayout(bottom, BoxLayout.Y_AXIS));
final JSplitPane rightSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
JPanel topContent = new MyScrollable(200);
JPanel topFixed = new ShrinkGrow(topContent, rightSplit);
topFixed.setLayout(new BoxLayout(topFixed, BoxLayout.X_AXIS));
JScrollPane topFlexible = new JScrollPane(topContent);
topFlexible.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
topFlexible.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JPanel bottomContent = new MyScrollable(300);
JPanel bottomFixed = new ShrinkGrow(bottomContent, rightSplit);
bottomFixed.setLayout(new BoxLayout(bottomFixed, BoxLayout.X_AXIS));
JScrollPane bottomFlexible = new JScrollPane(bottomContent);
bottomFlexible.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
bottomFlexible.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
mainView.setBackground(Color.red);
topFixed.setBackground(Color.green);
topContent.setBackground(Color.green.darker());
bottomFixed.setBackground(Color.blue);
bottomContent.setBackground(Color.blue.darker());
mainView.setMinimumSize(new Dimension(100, 100));
mainView.setPreferredSize(new Dimension(400, 300));
mainView.setMaximumSize(new Dimension(10000, 10000));
topFixed.setMinimumSize(new Dimension(topFixed.getMinimumSize().width, 30));
topFixed.setPreferredSize(new Dimension(topFixed.getPreferredSize().width, 30));
topFixed.setMaximumSize(new Dimension(topFixed.getMaximumSize().width, 30));
bottomFixed.setMinimumSize(new Dimension(bottomFixed.getMinimumSize().width, 40));
bottomFixed.setPreferredSize(new Dimension(bottomFixed.getPreferredSize().width, 40));
bottomFixed.setMaximumSize(new Dimension(bottomFixed.getMaximumSize().width, 40));
topContent.setPreferredSize(new Dimension(100, 500));
bottomContent.setPreferredSize(new Dimension(100, 400));
top.add(topFixed);
top.add(topFlexible);
bottom.add(bottomFixed);
bottom.add(bottomFlexible);
rightSplit.setLeftComponent(top);
rightSplit.setRightComponent(bottom);
rightSplit.setMinimumSize(new Dimension(0, 0));
final JSplitPane mainSplit = new MySplitPane(JSplitPane.HORIZONTAL_SPLIT, mainView, rightSplit);
window.add(mainSplit);
window.pack();
window.setVisible(true);
}
}
謝謝,我已經嘗試過這一點。但問題在於,不可能知道屬性是否因拖動分隔符而發生更改,或者由於JSlitPane組件大小發生了更改。如果前一種情況下,我想尊重用戶的選擇,並將其位置放在兩個有效位置中的一個或另一個位置上,並且在後一種情況下,我想將其恢復到更改前的位置。問題是,當窗口大小發生變化時,這些屬性更改有1-4個。 – nyholku