2 JSplitPane 内的同步 JScrollPanes 无法正常工作
2 Synchronized JScrollPanes inside JSplitPane not working properly
我对 Swing 有疑问。我将两个 JScrollPane 水平放置在一个 JSplitPane 中,并同步了 JScrollPanes。在每个 JScrollPane 中,我都放置了一个 JPanel。两个 JScrollPane 之间的同步,即(滚动一个 JScrollPane 也会滚动另一个 JScrollPane)正常工作。但是当我将 JSplitPane 分隔线拖向 left/right 直到 JPanel 的某些部分被隐藏时,水平滚动条会显示但处于禁用状态。我无法滚动查看 JPanel 的隐藏部分。
代码如下:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
public class SplitPaneTest extends JFrame {
public SplitPaneTest() {
setTitle( "Splits" );
setDefaultCloseOperation( EXIT_ON_CLOSE );
setSize( 400, 400 );
JPanel panel1 = new JPanel();
panel1.setLayout(new BorderLayout());
panel1.add( new JLabel( "Left panel!" ) );
JScrollPane scrollPane1 = new JScrollPane(panel1);
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
panel2.add( new JLabel( "Right Panel" ) );
JScrollPane scrollPane2 = new JScrollPane(panel2);
scrollPane2.getVerticalScrollBar().setModel(scrollPane1.getVerticalScrollBar().getModel());
scrollPane2.getHorizontalScrollBar().setModel(scrollPane1.getHorizontalScrollBar().getModel());
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane1,
scrollPane2);
splitPane.setResizeWeight(0.5);
add(splitPane);
setVisible( true );
}
public static void main( String[] args ) {
new SplitPaneTest();
}
}
也许重点是 移动 JSplitPane 的分隔线不会调整 JScrollPane 的大小。尽管如此,JScrollPane 上的 VIEW 已更改,因此滚动条由 JScrollPane 显示(当组件的首选大小大于 JScrollPane 中 JPanel 上的视口大小时,滚动条会自动出现)
但是滚动条是灰色的,因为从 JScrollPane 的角度来看不需要滚动(它包含的 JPanel 没有调整大小,因此不会超过 JScrollPane 的大小...)
UPDATE 这对我有用,解决方案是在 JPanel 中放置滚动条出现的尽可能多的内容(快速滚动时字体有点碎)
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
public class SplitPaneTest extends JFrame {
public SplitPaneTest() {
setTitle( "Splits" );
setDefaultCloseOperation( EXIT_ON_CLOSE );
setSize( 200, 200 );
JPanel panel1 = new JPanel();
panel1.setLayout(new BorderLayout());
panel1.setBackground(Color.YELLOW);
panel1.setLayout(new BorderLayout());
//panel1.setMinimumSize(new Dimension(100,200));
//panel1.setPreferredSize(new Dimension(100,200));
//panel1.revalidate();
panel1.add( new JLabel( "Left panel! fhajsdfasbkfbbsdkjafbkajhbshabshjdfbajsbskjaSK" ) );
JScrollPane scrollPane1 = new JScrollPane(panel1, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
//scrollPane1.setMinimumSize(new Dimension(100,200));
//scrollPane1.setPreferredSize(new Dimension(100,200));
//scrollPane1.revalidate();
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
//panel2.setMinimumSize(new Dimension(100,200));
//panel2.setPreferredSize(new Dimension(100,200));
//panel2.revalidate();
panel2.add( new JLabel( "Right Panel dfgasdgsdghsgs<dg<sdgs<dgdsgdfsafasfasfasfsafa" ) );
JScrollPane scrollPane2 = new JScrollPane(panel2, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
//scrollPane2.setMinimumSize(new Dimension(100,200));
//scrollPane2.setPreferredSize(new Dimension(100,200));
//scrollPane2.revalidate();
scrollPane2.getVerticalScrollBar().setModel(scrollPane1.getVerticalScrollBar().getModel());
scrollPane2.getHorizontalScrollBar().setModel(scrollPane1.getHorizontalScrollBar().getModel());
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane1,
scrollPane2);
splitPane.setResizeWeight(0.5);
//splitPane.setContinuousLayout(true);
this.add(splitPane);
this.setVisible( true );
}
public static void main( String[] args ) {
new SplitPaneTest();
}
}
当组件的首选大小大于滚动窗格的大小时,将自动显示滚动条。
您无法共享模型,因为每个滚动条的状态会有所不同,具体取决于分配给每个滚动窗格的 space 数量。它们唯一同步的时间是拆分窗格的分隔线位于中间时。
因此您需要监听每个滚动窗格的滚动条的变化,而不是尝试从另一个滚动窗格调整滚动条。
类似于:
import java.awt.BorderLayout;
import javax.swing.*;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import java.awt.event.*;
public class SplitPaneTest2 extends JFrame {
public SplitPaneTest2() {
setTitle( "Splits" );
setDefaultCloseOperation( EXIT_ON_CLOSE );
setSize( 400, 400 );
JPanel panel1 = new JPanel();
panel1.setLayout(new BorderLayout());
panel1.add( new JLabel( "Left panel!11111111111111111111" ) );
JScrollPane scrollPane1 = new JScrollPane(panel1);
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
panel2.add( new JLabel( "Right Panel11111111111111111111" ) );
JScrollPane scrollPane2 = new JScrollPane(panel2);
// scrollPane2.getVerticalScrollBar().setModel(scrollPane1.getVerticalScrollBar().getModel());
// scrollPane2.getHorizontalScrollBar().setModel(scrollPane1.getHorizontalScrollBar().getModel());
new ScrollBarSynchronizer(scrollPane1.getHorizontalScrollBar(), scrollPane2.getHorizontalScrollBar());
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane1,
scrollPane2);
splitPane.setResizeWeight(0.5);
add(splitPane);
setVisible( true );
}
public static void main( String[] args ) {
new SplitPaneTest2();
}
static class ScrollBarSynchronizer implements AdjustmentListener
{
JScrollBar[] scrollBars;
public ScrollBarSynchronizer(JScrollBar... scrollBars)
{
this.scrollBars = scrollBars;
for (JScrollBar scrollBar: scrollBars)
scrollBar.addAdjustmentListener( this );
}
@Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
JScrollBar source = (JScrollBar)e.getSource();
int value = e.getValue();
for (JScrollBar scrollBar: scrollBars)
{
if (scrollBar != source)
{
scrollBar.removeAdjustmentListener( this );
scrollBar.setValue( value );
scrollBar.addAdjustmentListener( this );
}
}
}
}
}
您还可以为垂直滚动条创建一个单独的同步器。
我对 Swing 有疑问。我将两个 JScrollPane 水平放置在一个 JSplitPane 中,并同步了 JScrollPanes。在每个 JScrollPane 中,我都放置了一个 JPanel。两个 JScrollPane 之间的同步,即(滚动一个 JScrollPane 也会滚动另一个 JScrollPane)正常工作。但是当我将 JSplitPane 分隔线拖向 left/right 直到 JPanel 的某些部分被隐藏时,水平滚动条会显示但处于禁用状态。我无法滚动查看 JPanel 的隐藏部分。
代码如下:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
public class SplitPaneTest extends JFrame {
public SplitPaneTest() {
setTitle( "Splits" );
setDefaultCloseOperation( EXIT_ON_CLOSE );
setSize( 400, 400 );
JPanel panel1 = new JPanel();
panel1.setLayout(new BorderLayout());
panel1.add( new JLabel( "Left panel!" ) );
JScrollPane scrollPane1 = new JScrollPane(panel1);
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
panel2.add( new JLabel( "Right Panel" ) );
JScrollPane scrollPane2 = new JScrollPane(panel2);
scrollPane2.getVerticalScrollBar().setModel(scrollPane1.getVerticalScrollBar().getModel());
scrollPane2.getHorizontalScrollBar().setModel(scrollPane1.getHorizontalScrollBar().getModel());
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane1,
scrollPane2);
splitPane.setResizeWeight(0.5);
add(splitPane);
setVisible( true );
}
public static void main( String[] args ) {
new SplitPaneTest();
}
}
也许重点是 移动 JSplitPane 的分隔线不会调整 JScrollPane 的大小。尽管如此,JScrollPane 上的 VIEW 已更改,因此滚动条由 JScrollPane 显示(当组件的首选大小大于 JScrollPane 中 JPanel 上的视口大小时,滚动条会自动出现) 但是滚动条是灰色的,因为从 JScrollPane 的角度来看不需要滚动(它包含的 JPanel 没有调整大小,因此不会超过 JScrollPane 的大小...)
UPDATE 这对我有用,解决方案是在 JPanel 中放置滚动条出现的尽可能多的内容(快速滚动时字体有点碎)
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
public class SplitPaneTest extends JFrame {
public SplitPaneTest() {
setTitle( "Splits" );
setDefaultCloseOperation( EXIT_ON_CLOSE );
setSize( 200, 200 );
JPanel panel1 = new JPanel();
panel1.setLayout(new BorderLayout());
panel1.setBackground(Color.YELLOW);
panel1.setLayout(new BorderLayout());
//panel1.setMinimumSize(new Dimension(100,200));
//panel1.setPreferredSize(new Dimension(100,200));
//panel1.revalidate();
panel1.add( new JLabel( "Left panel! fhajsdfasbkfbbsdkjafbkajhbshabshjdfbajsbskjaSK" ) );
JScrollPane scrollPane1 = new JScrollPane(panel1, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
//scrollPane1.setMinimumSize(new Dimension(100,200));
//scrollPane1.setPreferredSize(new Dimension(100,200));
//scrollPane1.revalidate();
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
//panel2.setMinimumSize(new Dimension(100,200));
//panel2.setPreferredSize(new Dimension(100,200));
//panel2.revalidate();
panel2.add( new JLabel( "Right Panel dfgasdgsdghsgs<dg<sdgs<dgdsgdfsafasfasfasfsafa" ) );
JScrollPane scrollPane2 = new JScrollPane(panel2, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
//scrollPane2.setMinimumSize(new Dimension(100,200));
//scrollPane2.setPreferredSize(new Dimension(100,200));
//scrollPane2.revalidate();
scrollPane2.getVerticalScrollBar().setModel(scrollPane1.getVerticalScrollBar().getModel());
scrollPane2.getHorizontalScrollBar().setModel(scrollPane1.getHorizontalScrollBar().getModel());
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane1,
scrollPane2);
splitPane.setResizeWeight(0.5);
//splitPane.setContinuousLayout(true);
this.add(splitPane);
this.setVisible( true );
}
public static void main( String[] args ) {
new SplitPaneTest();
}
}
当组件的首选大小大于滚动窗格的大小时,将自动显示滚动条。
您无法共享模型,因为每个滚动条的状态会有所不同,具体取决于分配给每个滚动窗格的 space 数量。它们唯一同步的时间是拆分窗格的分隔线位于中间时。
因此您需要监听每个滚动窗格的滚动条的变化,而不是尝试从另一个滚动窗格调整滚动条。
类似于:
import java.awt.BorderLayout;
import javax.swing.*;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import java.awt.event.*;
public class SplitPaneTest2 extends JFrame {
public SplitPaneTest2() {
setTitle( "Splits" );
setDefaultCloseOperation( EXIT_ON_CLOSE );
setSize( 400, 400 );
JPanel panel1 = new JPanel();
panel1.setLayout(new BorderLayout());
panel1.add( new JLabel( "Left panel!11111111111111111111" ) );
JScrollPane scrollPane1 = new JScrollPane(panel1);
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
panel2.add( new JLabel( "Right Panel11111111111111111111" ) );
JScrollPane scrollPane2 = new JScrollPane(panel2);
// scrollPane2.getVerticalScrollBar().setModel(scrollPane1.getVerticalScrollBar().getModel());
// scrollPane2.getHorizontalScrollBar().setModel(scrollPane1.getHorizontalScrollBar().getModel());
new ScrollBarSynchronizer(scrollPane1.getHorizontalScrollBar(), scrollPane2.getHorizontalScrollBar());
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane1,
scrollPane2);
splitPane.setResizeWeight(0.5);
add(splitPane);
setVisible( true );
}
public static void main( String[] args ) {
new SplitPaneTest2();
}
static class ScrollBarSynchronizer implements AdjustmentListener
{
JScrollBar[] scrollBars;
public ScrollBarSynchronizer(JScrollBar... scrollBars)
{
this.scrollBars = scrollBars;
for (JScrollBar scrollBar: scrollBars)
scrollBar.addAdjustmentListener( this );
}
@Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
JScrollBar source = (JScrollBar)e.getSource();
int value = e.getValue();
for (JScrollBar scrollBar: scrollBars)
{
if (scrollBar != source)
{
scrollBar.removeAdjustmentListener( this );
scrollBar.setValue( value );
scrollBar.addAdjustmentListener( this );
}
}
}
}
}
您还可以为垂直滚动条创建一个单独的同步器。