如何将JTextPane / JPanel正确打包到JPanel到JScrollPane?

时间:2013-11-25 00:30:15

标签: java swing user-interface jscrollpane jtextpane

下面是我原来问题的具体答案,但是如果你想要达到一般类似的结构,那么按照下面的camickr方法可能会更实用。要按我原来想要的方式执行此操作,您必须覆盖JPanel并为外部容器实现Scrollable。 (归功于用户Kylar - JTextArea on JPanel inside JScrollPane does not resize properly

import javax.swing.*;
import java.awt.*;
import javax.swing.text.*;

public class MyEditor extends JTextPane {
    JFrame window;
    JScrollPane editScroll;
    NumberLines numPane;
    HoldMe please;

public static void main(String args[]) {
    new MyEditor();
}

MyEditor() {

    setOpaque(false);
    setEditorKit(new TextWrapKit());

    numPane = new NumberLines();
    numPane.setPreferredSize(new Dimension(50,100));
    please = new HoldMe();

    please.setLayout(new BorderLayout());
    please.add(this,BorderLayout.CENTER);
    please.add(numPane,BorderLayout.WEST);

    editScroll = new JScrollPane(please);
    editScroll.setPreferredSize(new Dimension(500,500));
    editScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    editScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 

    window = new JFrame();
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.getContentPane().add(editScroll);
    window.pack();
    window.setVisible(true);
}

private class HoldMe extends JPanel implements Scrollable{
    public Dimension getPreferredScrollableViewportSize() {
    return super.getPreferredSize(); //tell the JScrollPane that we want to be our 'preferredSize' - but later, we'll say that vertically, it should scroll.
    }

     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
    return 16;//set to 16 because that's what you had in your code.
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
    return 16;//set to 16 because that's what you had set in your code.
    }

    public boolean getScrollableTracksViewportWidth() {
    return true;//track the width, and re-size as needed.
    }

    public boolean getScrollableTracksViewportHeight() {
    return false; //we don't want to track the height, because we want to scroll vertically.
 }   
}


private class NumberLines extends JPanel {
NumberLines() {
        setBackground(new Color(120,120,120));
        setOpaque(false);
        repaint();
    } 
@Override
protected void paintComponent(Graphics g) {
    g.fillRect(0,0,this.getWidth(),this.getHeight());

}

}

private class TextWrapKit extends StyledEditorKit {
    ViewFactory defaultFactory=new TextWrapFactory();
    public ViewFactory getViewFactory() {
        return defaultFactory;
    }
}

private class TextWrapFactory implements ViewFactory {
    public View create(Element elem) {
        String kind = elem.getName();
        if (kind != null) {
            if (kind.equals(AbstractDocument.ContentElementName)) {
                return new TextWrapView(elem);
            } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
                return new ParagraphView(elem);
            } else if (kind.equals(AbstractDocument.SectionElementName)) {
                return new BoxView(elem, View.Y_AXIS);
            } else if (kind.equals(StyleConstants.ComponentElementName)) {
                return new ComponentView(elem);
            } else if (kind.equals(StyleConstants.IconElementName)) {
                return new IconView(elem);
            }
        }

        // default to text display
        return new LabelView(elem);
    }
}

private class TextWrapView extends LabelView {
    public TextWrapView(Element elem) {
        super(elem);
    }

    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);
        }
    }

}

}   

编辑:代码替换为SCCE,对不起麻烦

好的,所以它的结构是这样......

•顶级 - 扩展JTextPane

•将此JTextPane放入设置为BorderLayout CENTER的JPanel

•将另一个JPanel放入设置为WEST

的同一JPanel中

•将持有两者的JPanel放入JScrollPane

•准备部署(禁止)

基本上,我无法找到一种方法来做到这一点,而不会失去一些关键的东西。我可以把它们放在一起,但我会丢失滚动。或者我会向后滚动,但随后会丢失文本包装。有一次我得到了包装,从技术上说它滚动但不是应该有的,换句话说,滚动窗格没有检测到文本的大小。我需要嵌套的JPanel(第一个)来滚动JTextPane

问题区域在下面的构造函数中,对不起它是如此混乱,但我在这里尝试不同的东西失去它...可能没有帮助。如果有人能帮助我解决这个问题,我将非常感激。

感谢您的阅读。

import javax.swing.*;
import java.awt.*;
import javax.swing.text.*;
import java.awt.BorderLayout;

public class MyEditor extends JTextPane {
JFrame window;
JScrollPane editScroll;


public static void main(String args[]) {
    new MyEditor();
}

MyEditor() {
    setOpaque(false);
    setEditorKit(new TextWrapKit());

    JPanel numPane = new JPanel();
    JPanel packEdit = new JPanel();

    packEdit.setLayout(new BorderLayout());
    packEdit.add(this,BorderLayout.CENTER);
    packEdit.add(numPane,BorderLayout.WEST);

    editScroll = new JScrollPane(packEdit);
    editScroll.setPreferredSize(new Dimension(500,500));        
    editScroll.setViewportView(packEdit);
    editScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    editScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 

    window = new JFrame();
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.add(editScroll);
    window.pack();
    window.setVisible(true);
}

private class TextWrapKit extends StyledEditorKit {
    ViewFactory defaultFactory=new TextWrapFactory();
    public ViewFactory getViewFactory() {
        return defaultFactory;
    }
}

private class TextWrapFactory implements ViewFactory {
    public View create(Element elem) {
        String kind = elem.getName();
        if (kind != null) {
            if (kind.equals(AbstractDocument.ContentElementName)) {
                return new TextWrapView(elem);
            } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
                return new ParagraphView(elem);
            } else if (kind.equals(AbstractDocument.SectionElementName)) {
                return new BoxView(elem, View.Y_AXIS);
            } else if (kind.equals(StyleConstants.ComponentElementName)) {
                return new ComponentView(elem);
            } else if (kind.equals(StyleConstants.IconElementName)) {
                return new IconView(elem);
            }
        }

        // default to text display
        return new LabelView(elem);
    }
}

private class TextWrapView extends LabelView {
    public TextWrapView(Element elem) {
        super(elem);
    }

    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);
        }
    }

}

}

1 个答案:

答案 0 :(得分:1)

  

扩展了JTextPane

为什么?

  

setEditorKit(new TextWrapKit());

为什么呢?

使滚动窗格使用默认组件。然后,如果由于某种原因您仍需要自定义,您可以一次更改一个,以确保它仍然有效。如果它不再起作用,那么你就知道问题所在。

  

packEdit.add(numPane,BorderLayout.WEST);

在我看来,您正在尝试添加行号。执行此操作的标准方法是将组件添加到滚动窗格的行标题,而不是将其添加到视口中的面板的一部分。有关此方法的示例,请参阅Text Component Line Number

将来,每个问题都应张贴SSCCE。如果没有SSCCE,您将获得一个免费(尝试)答案。