不同层次结构层上的多个JScrollPane(Java):水平滚动条问题

时间:2016-03-22 18:10:06

标签: java swing user-interface jscrollpane jtextpane

我正在努力解决以下问题:

我在布局中的不同位置有多个JScrollPanes。只使用一个JScrollPane时,一切正常。不幸的是,第二个让我陷入了深深的麻烦。

此外,还有以下要求:

-A JTextPane必须使用(需要格式化文本格式化)

- 没有第三方图书馆(会让生活更轻松,但目前还不是 允许在这里)

-JTextPane应该仍然像现在一样运行(解释:JSplitter有2个JTextPanes。由于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的正确行为需要内部类(它将打破"长"单词而不是弄乱UI)。

- JSplitPane的上半部分显示JTextPane的行为方式(文本环绕并在需要时添加滚动条(垂直))

- 下半部分添加一个随机按钮和JTextPane(包括JScrollPane)。该按钮仅用于说明,因为在该区域中许多其他组件应该参与UI。

现在问题出在JSpitPane的下半部分。 JTextPane的JScrollPane的行为与没有第二个JScrollPane时的行为方式相同。

有没有人知道或者可以给我一个如何在JTextPane的JScrollPanes上获得相同行为的提示?

编辑#1:

@rdonuk提出了一个有效的解决方案。我仍然更喜欢不使用任何set(Preferred|Maximum|Minimum)方法的解决方案。此外,我提出了一个适用于我的特定情况的解决方案,但可能无法与其他LayoutManager一起使用。此外,我也不喜欢这种方法,而且我还在寻找更好的解决方案。

编辑#2:

调整后的澄清要求。

编辑#3:

添加了第三个解决方案(由@MadProgrammer提供)。

解决方案1 ​​

See below for @rdonuk's solution

解决方案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

See below for @MadProgrammer's solution

编辑#4:

@MadProgrammer和@rdonuk提供的两种解决方案都可以比我的更好,但是因为最终用户界面非常复杂,所以这两种解决方案都需要大量的工作或者不能在那个特定的环境我会坚持我的解决方案(解决方案#2)。

3 个答案:

答案 0 :(得分:2)

制作一个实施JPanel的{​​{1}}并为Scrollable提供解决方案

RestrcitedPane

getPreferredScrollableViewportSize

答案 1 :(得分:1)

请尝试下面的代码。简而言之;我刚刚修复了scrollPaneText2大小,并在主面板上添加了一个调整大小的侦听器。因此,如果用户调整窗口大小,则会根据新大小再次修复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();
        }
    }
}

答案 2 :(得分:0)

查看我的帖子。有3个解决方案可以在示例代码中使用。