Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不同层次结构层上的多个JScrollPane(Java):水平滚动条问题_Java_Swing_User Interface_Jscrollpane_Jtextpane - Fatal编程技术网

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

不同层次结构层上的多个JScrollPane(Java):水平滚动条问题,java,swing,user-interface,jscrollpane,jtextpane,Java,Swing,User Interface,Jscrollpane,Jtextpane,我正在努力解决以下问题: 我在布局的不同位置有多个JScrollPane。当只使用一个JScrollPane时,一切都正常。不幸的是,第二个问题让我陷入了深深的麻烦之中 此外,还有以下要求: -必须使用JTextPane(需要richt文本格式) -没有第三方库(这会让生活更轻松,但目前还不是这样) (此处允许) -JTextPane仍应保持其当前的行为(说明:有两个JTextPane由一个JSplitter分隔。由于JScrollPane的计数不同,它们的行为不同。目标是所有情况下的行为相同(

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

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

此外,还有以下要求:

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

-没有第三方库(这会让生活更轻松,但目前还不是这样) (此处允许)

-JTextPane仍应保持其当前的行为(说明:有两个JTextPane由一个JSplitter分隔。由于JScrollPane的计数不同,它们的行为不同。目标是所有情况下的行为相同(第一个))

以下是我编写的代码:

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的jscrollpane上获得相同的行为吗

编辑#1:

@rdonuk想出了一个有效的解决方案。我仍然更喜欢不依赖于使用任何
集合(首选|最大值|最小值)
方法的解决方案。此外,我还提出了一个解决方案,该方案适用于我的具体情况,但可能不适用于其他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提供的两种解决方案都能正常工作,可能比我的解决方案要好,但由于最终用户界面相当复杂,而且这两种解决方案要么需要大量工作,要么在特定环境下无法工作,我将坚持使用我的解决方案(解决方案2)。

请尝试下面的代码。简而言之我刚刚修复了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();
        }
    }
}

制作一个
JPanel
,它实现了
Scrollable
,并为
getPreferredScrollableViewportSize


见我最初的帖子。示例代码中有3种解决方案。

您的GUI应该是什么样子的?请查看可滚动的
界面,该界面可用于向
JScrollPane
提供有关其“首选”视口大小的提示be@GilbertLeBlanc:上面的示例是为了简单而进行的抽象。最后,用户界面将有许多组件,这些组件不适合屏幕(限于屏幕宽度,在最外层的JScrollPane上不会有水平滚动条)。因此,添加了外部JScrollPane(JSplitter的底部)。内容将是动态的,取决于用户交互。但是JTextPane(包括JScrollPane)的行为应该与JSplitPane的上半部分相同。@GilbertLeBlanc:part#2:JTextPane的内容也是动态的。所有的可能都很合适,也可能是一团糟。因此,它应该包含滚动条,因为组件的高度稍后会受到限制(宽度应该适合屏幕,这是当前的问题)。@MadProgrammer:我已经查看了Scrollable,并覆盖了
getScrollableTracksViewPortWidth()
以返回
false
,如其他问题所述。这根本不起作用(破坏了组件的大小调整)。由于它是组件的一部分,而且JTextPane的内容也是动态的,所以我不知道如何提供“首选”视口大小。有什么建议吗?@rdonuk:这个解决方案似乎有效,但正如@MadProgrammer提到的,如果可能的话,我更喜欢不依赖
set(首选的|最大|最小)大小的解决方案。我会投票支持你的答案,但不幸的是,由于我的信誉点(新帐户),这是不可能的。如果没有
设置(首选|最大|最小)大小,我无法找到解决方案
我会将此标记为解决问题的答案。好的。如果您找到其他解决方案,请在此处发布。@rdonuk:将您的方法添加到可能的解决方案中。此外,我还添加了另一个适用于我的案例的解决方案。但我还远远没有满意。@CodeMonkey请检查我的第二个解决方案。它有效,而且肯定是一个解决方案。尽管如此,我还是觉得有点“不对”。说明:(TextWrap)JTextPane是自定义组件的一部分。该自定义组件不应该考虑它的布局(JTextPane是其中的一部分)而不是必须在使用自定义组件的任何地方添加的受限窗格吗?在解决方案#2中,我重写了getPreferredSize方法(我的(子)自定义组件的),这导致了相同的结果。作为swing新手,如果您能解释一下为什么您的解决方案是可行的,我将不胜感激。您之前发布的链接涉及
setXSize
方法,其中一些注释建议自定义组件可能会覆盖getXSi
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);
        }
    }
}