简体   繁体   English

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

[英]How do I properly pack JTextPane/JPanel into JPanel into JScrollPane?

Below is the answer specific to my original question, but if you're trying to achieve a similar structure in general, it'd probably be more practical follow camickr's method below. 以下是针对我的原始问题的解答,但是,如果您总体上想要实现类似的结构,则遵循下面的camickr方法可能更实用。 To do it the way I originally wanted, you have to override JPanel and implement Scrollable for the outer container. 要按照我最初想要的方式进行操作,您必须重写JPanel并为外部容器实现Scrollable。 (credit to user Kylar - JTextArea on JPanel inside JScrollPane does not resize properly ) (授予用户Kylar- JScrollPane内JPanel上的JTextArea的大小无法正确调整

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

}

}   

EDIT: code replaced with SCCE, sorry for the trouble 编辑:用SCCE替换代码,对不起您的麻烦

Okay, so it's structured like this... 好的,它的结构如下:

• Top class - extends JTextPane •顶级-扩展JTextPane

• Place this JTextPane into a JPanel set to BorderLayout CENTER •将此JTextPane放入设置为BorderLayout CENTER的JPanel中

• Place another JPanel into the same JPanel set to WEST •将另一个JPanel放入设置为WEST的同一JPanel中

• Place the JPanel holding the two into a JScrollPane •将持有两者的JPanel放入JScrollPane

• Ready for deployment (nope) •准备部署(没有)

Basically, I can't figure out a way to do this without losing out on something critical. 基本上,我无法找到一种方法来做到这一点而又不会失去一些关键的东西。 I can get them all together, but I'll lose scrolling. 我可以把它们放在一起,但我会失去滚动感。 Or I'll get scrolling back, but then lose text wrapping. 否则,我将向后滚动,但是会丢失文本换行。 One time I got wrapping, and technically it scrolled but not as it should have, in otherwords, the scrollpane didn't detect the size of the text. 有一次,我换行了,从技术上讲,它滚动了,但是没有滚动,换句话说,滚动窗格没有检测到文本的大小。 I need the nested JPanel (1st one) to scroll with the JTextPane 我需要嵌套的JPanel(第一个)与JTextPane一起滚动

The problem area is in the constructor below, sorry it's such a mess but I'm losing it over here trying different things... Probably isn't helping. 问题区域在下面的构造函数中,很抱歉,这是一团糟,但是我在这里尝试不同的东西时会迷失它……可能没有帮助。 I'd be so grateful if somebody could help me figure this out. 如果有人可以帮助我解决这个问题,我将非常感激。

Thank you for reading. 感谢您的阅读。

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

}

} }

extends JTextPane 扩展JTextPane

Why? 为什么?

setEditorKit(new TextWrapKit()); setEditorKit(new TextWrapKit());

Why? 为什么?

Get the scroll pane working with the default components. 获取使用默认组件的滚动窗格。 Then if for some reason you still need to customize you make the changes one at a time to make sure it still works. 然后,如果由于某种原因仍需要自定义,则一次进行一次更改以确保其仍然有效。 If it doesn't work any more then you know what the problem is. 如果它不再起作用,那么您就知道问题出在哪里。

packEdit.add(numPane,BorderLayout.WEST); packEdit.add(numPane,BorderLayout.WEST);

Looks to me like you are trying to add line number. 在我看来,您正在尝试添加行号。 The standard way to do this is to add your component to the row header of the scrollpane, instead of making it part of the panel added to the viewport. 执行此操作的标准方法是将组件添加到滚动窗格的行标题,而不是使其成为添加到视口的面板的一部分。 See Text Component Line Number for an example of this approach. 有关此方法的示例,请参见文本组件行号

In the future a SSCCE should be posted with every question. 将来,每个问题都应发布SSCCE You get one free (attempted) answer without a SSCCE . 如果没有SSCCE您将获得一个免费(尝试)的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM