不同层级上的多个 JScrollPane (Java):水平滚动条问题
Multiple JScrollPane (Java) on different hierarchy layer: horizontal scroll bar issue
我正在努力解决以下问题:
我在布局的不同位置有多个 JScrollPanes。仅使用一个 JScrollPane 时一切正常。不幸的是,第二个让我陷入了深深的麻烦。
此外,还有以下要求:
-必须使用 JTextPane(需要 richt 文本格式)
-没有第三方库(会让生活更轻松,但目前还没有
此处允许)
-JTextPane 的行为仍应与当前相同(说明:有 2 个 JTextPanes 由 JSplitter 分隔。由于 JScrollPanes 的数量不同,它们的行为不同。目标是在所有情况下的行为都相同(第一个))
下面是我写的代码:
public class ScrollExample extends JPanel {
public ScrollExample() {
super(new BorderLayout());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1);
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JScrollPane scrollPaneText2 = new JScrollPane(textPane2);
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new JPanel(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.CENTER);
panel.add(new JButton("Example"), BorderLayout.NORTH);
JScrollPane secondScrollPane = new JScrollPane(panel);
secondScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
secondScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, secondScrollPane);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public static void main(String[] args) {
ScrollExample example = new ScrollExample();
JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch(axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch(elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
}
解释:
-JTextPane 的正确行为需要内部 类(它将打破 "long" 单词而不是弄乱 UI)。
-JSplitPane 的上半部分显示了 JTextPane 的正确行为(需要时文本换行和添加滚动条(垂直))
-下半部分添加了一个随机按钮和JTextPane(包括JScrollPane)。该按钮仅用于说明,因为在此区域中,许多其他组件应参与 UI.
现在的问题在 JSpitPane 的下部。 JTextPane 的 JScrollPane 的行为方式与没有第二个 JScrollPane 时的行为方式不同。
有谁知道或可以给我提示如何在两个 JTextPane 的 JScrollPanes 上获得相同的行为?
编辑#1:
@rdonuk 提出了一个可行的解决方案。我仍然更喜欢不依赖任何 set(Preferred|Maximum|Minimum)
方法的解决方案。此外,我想出了一个适用于我的特定情况的解决方案,但可能不适用于其他 LayoutManager。此外,我也不喜欢这种方法,我仍在寻找更好的解决方案。
编辑#2:
调整后的澄清要求。
编辑#3:
添加了第三个解决方案(由@MadProgrammer 提供)。
解决方案 1
解决方案 2
我简单地重写了 JScrollPanes 的 getPreferredSize 方法:
public class ScrollExample extends JPanel {
public ScrollExample() {
super(new BorderLayout());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1) {
@Override
public Dimension getPreferredSize() {
return new Dimension(1,1);
}
};
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JScrollPane scrollPaneText2 = new JScrollPane(textPane2) {
@Override
public Dimension getPreferredSize() {
return new Dimension(1,1);
}
};
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new JPanel(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.CENTER);
panel.add(new JButton("Example"), BorderLayout.NORTH);
JScrollPane secondScrollPane = new JScrollPane(panel);
secondScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
secondScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, secondScrollPane);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public static void main(String[] args) {
ScrollExample example = new ScrollExample();
JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch(axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch(elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
}
解决方案 3
编辑#4:
@MadProgrammer 和@rdonuk 给出的两种解决方案都有效,并且总体上可能比我的更好,但由于最终 UI 非常复杂,两种解决方案都需要大量工作或获胜在那个特定环境中工作我会坚持我的解决方案(解决方案 #2)。
请尝试下面的代码。简而言之;我刚刚修复了 scrollPaneText2 的大小,并向您的主面板添加了一个调整大小的侦听器。因此,如果用户调整 window 的大小,则 scrollPaneText2 的大小将根据新大小再次固定。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class ScrollExample extends JPanel {
JScrollPane secondScrollPane;
JScrollPane scrollPaneText2;
JPanel panel;
public ScrollExample() {
super(new BorderLayout());
addComponentListener(new ResizeListener());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1);
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPaneText2 = new JScrollPane(textPane2);
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
panel = new JPanel(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.WEST);
panel.add(new JButton("Example"), BorderLayout.NORTH);
secondScrollPane = new JScrollPane(panel);
secondScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
secondScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, secondScrollPane);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public void adjustComponents() {
panel.remove(scrollPaneText2);
Dimension dimension = new Dimension();
int nScrollWidth = secondScrollPane.getVerticalScrollBar().getWidth();
dimension.setSize(secondScrollPane.getVisibleRect().getWidth()-nScrollWidth, scrollPaneText2.getHeight());
scrollPaneText2.setPreferredSize(dimension);
scrollPaneText2.setMaximumSize(dimension);
panel.add(scrollPaneText2);
repaint();
}
public static void main(String[] args) {
final ScrollExample example = new ScrollExample();
final JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch(axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch(elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
public class ResizeListener extends ComponentAdapter {
@Override
public void componentResized(ComponentEvent e) {
ScrollExample scrollExample = (ScrollExample) e.getSource();
scrollExample.adjustComponents();
}
}
}
制作一个实现Scrollable
的JPanel
并为getPreferredScrollableViewportSize
提供解决方案
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.Scrollable;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class ScrollExample extends JPanel {
public ScrollExample() {
super(new BorderLayout());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1);
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JScrollPane scrollPaneText2 = new JScrollPane(textPane2);
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new RestrictedPanel();
panel.setLayout(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.CENTER);
panel.add(new JButton("Example"), BorderLayout.NORTH);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, panel);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public class RestrictedPanel extends JPanel implements Scrollable {
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(600, 200);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return true;
}
}
public static void main(String[] args) {
ScrollExample example = new ScrollExample();
JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch (axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch (elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
}
查看我的首字母post。示例代码中有 3 个解决方案。
我正在努力解决以下问题:
我在布局的不同位置有多个 JScrollPanes。仅使用一个 JScrollPane 时一切正常。不幸的是,第二个让我陷入了深深的麻烦。
此外,还有以下要求:
-必须使用 JTextPane(需要 richt 文本格式)
-没有第三方库(会让生活更轻松,但目前还没有 此处允许)
-JTextPane 的行为仍应与当前相同(说明:有 2 个 JTextPanes 由 JSplitter 分隔。由于 JScrollPanes 的数量不同,它们的行为不同。目标是在所有情况下的行为都相同(第一个))
下面是我写的代码:
public class ScrollExample extends JPanel {
public ScrollExample() {
super(new BorderLayout());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1);
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JScrollPane scrollPaneText2 = new JScrollPane(textPane2);
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new JPanel(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.CENTER);
panel.add(new JButton("Example"), BorderLayout.NORTH);
JScrollPane secondScrollPane = new JScrollPane(panel);
secondScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
secondScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, secondScrollPane);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public static void main(String[] args) {
ScrollExample example = new ScrollExample();
JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch(axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch(elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
}
解释:
-JTextPane 的正确行为需要内部 类(它将打破 "long" 单词而不是弄乱 UI)。
-JSplitPane 的上半部分显示了 JTextPane 的正确行为(需要时文本换行和添加滚动条(垂直))
-下半部分添加了一个随机按钮和JTextPane(包括JScrollPane)。该按钮仅用于说明,因为在此区域中,许多其他组件应参与 UI.
现在的问题在 JSpitPane 的下部。 JTextPane 的 JScrollPane 的行为方式与没有第二个 JScrollPane 时的行为方式不同。
有谁知道或可以给我提示如何在两个 JTextPane 的 JScrollPanes 上获得相同的行为?
编辑#1:
@rdonuk 提出了一个可行的解决方案。我仍然更喜欢不依赖任何 set(Preferred|Maximum|Minimum)
方法的解决方案。此外,我想出了一个适用于我的特定情况的解决方案,但可能不适用于其他 LayoutManager。此外,我也不喜欢这种方法,我仍在寻找更好的解决方案。
编辑#2:
调整后的澄清要求。
编辑#3:
添加了第三个解决方案(由@MadProgrammer 提供)。
解决方案 1
解决方案 2
我简单地重写了 JScrollPanes 的 getPreferredSize 方法:
public class ScrollExample extends JPanel {
public ScrollExample() {
super(new BorderLayout());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1) {
@Override
public Dimension getPreferredSize() {
return new Dimension(1,1);
}
};
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JScrollPane scrollPaneText2 = new JScrollPane(textPane2) {
@Override
public Dimension getPreferredSize() {
return new Dimension(1,1);
}
};
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new JPanel(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.CENTER);
panel.add(new JButton("Example"), BorderLayout.NORTH);
JScrollPane secondScrollPane = new JScrollPane(panel);
secondScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
secondScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, secondScrollPane);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public static void main(String[] args) {
ScrollExample example = new ScrollExample();
JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch(axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch(elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
}
解决方案 3
编辑#4:
@MadProgrammer 和@rdonuk 给出的两种解决方案都有效,并且总体上可能比我的更好,但由于最终 UI 非常复杂,两种解决方案都需要大量工作或获胜在那个特定环境中工作我会坚持我的解决方案(解决方案 #2)。
请尝试下面的代码。简而言之;我刚刚修复了 scrollPaneText2 的大小,并向您的主面板添加了一个调整大小的侦听器。因此,如果用户调整 window 的大小,则 scrollPaneText2 的大小将根据新大小再次固定。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class ScrollExample extends JPanel {
JScrollPane secondScrollPane;
JScrollPane scrollPaneText2;
JPanel panel;
public ScrollExample() {
super(new BorderLayout());
addComponentListener(new ResizeListener());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1);
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPaneText2 = new JScrollPane(textPane2);
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
panel = new JPanel(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.WEST);
panel.add(new JButton("Example"), BorderLayout.NORTH);
secondScrollPane = new JScrollPane(panel);
secondScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
secondScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, secondScrollPane);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public void adjustComponents() {
panel.remove(scrollPaneText2);
Dimension dimension = new Dimension();
int nScrollWidth = secondScrollPane.getVerticalScrollBar().getWidth();
dimension.setSize(secondScrollPane.getVisibleRect().getWidth()-nScrollWidth, scrollPaneText2.getHeight());
scrollPaneText2.setPreferredSize(dimension);
scrollPaneText2.setMaximumSize(dimension);
panel.add(scrollPaneText2);
repaint();
}
public static void main(String[] args) {
final ScrollExample example = new ScrollExample();
final JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch(axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch(elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
public class ResizeListener extends ComponentAdapter {
@Override
public void componentResized(ComponentEvent e) {
ScrollExample scrollExample = (ScrollExample) e.getSource();
scrollExample.adjustComponents();
}
}
}
制作一个实现Scrollable
的JPanel
并为getPreferredScrollableViewportSize
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.Scrollable;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class ScrollExample extends JPanel {
public ScrollExample() {
super(new BorderLayout());
JTextPane textPane1 = new JTextPane();
textPane1.setEditorKit(new WrapEditorKit());
JTextPane textPane2 = new JTextPane();
textPane2.setEditorKit(new WrapEditorKit());
JScrollPane scrollPaneText1 = new JScrollPane(textPane1);
scrollPaneText1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JScrollPane scrollPaneText2 = new JScrollPane(textPane2);
scrollPaneText2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPaneText2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new RestrictedPanel();
panel.setLayout(new BorderLayout());
panel.add(scrollPaneText2, BorderLayout.CENTER);
panel.add(new JButton("Example"), BorderLayout.NORTH);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPaneText1, panel);
splitPane.setDividerLocation(100);
add(splitPane);
textPane1.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
textPane2.setText("ThisIsAVeryLongStringWhichRepeatsItselfThisIsAVeryLongStringWhichRepeatsItself ThisIsAVeryLongStringWhichRepeatsItself");
}
public class RestrictedPanel extends JPanel implements Scrollable {
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(600, 200);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return true;
}
}
public static void main(String[] args) {
ScrollExample example = new ScrollExample();
JFrame frame = new JFrame("Example");
frame.setLayout(new BorderLayout());
frame.add(example, BorderLayout.CENTER);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setBounds(100, 50, 600, 400);
frame.setVisible(true);
}
});
}
public class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch (axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
public class WrapEditorKit extends StyledEditorKit {
protected ViewFactory _factory = new WrapColumnFactory();
@Override
public ViewFactory getViewFactory() {
return _factory;
}
}
public class WrapColumnFactory implements ViewFactory {
@Override
public View create(Element elem) {
switch (elem.getName()) {
case AbstractDocument.ContentElementName:
return new WrapLabelView(elem);
case AbstractDocument.ParagraphElementName:
return new ParagraphView(elem);
case AbstractDocument.SectionElementName:
return new BoxView(elem, View.Y_AXIS);
case StyleConstants.ComponentElementName:
return new ComponentView(elem);
case StyleConstants.IconElementName:
return new IconView(elem);
}
return new LabelView(elem);
}
}
}
查看我的首字母post。示例代码中有 3 个解决方案。