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

标签 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 放入设置为 WES​​T 的同一个 JPanel

• 将容纳两者的 JPanel 放入 JScrollPane

• 准备部署(不)

基本上,我无法找到一种方法来做到这一点而不丢失一些关键的东西。我可以把它们全部放在一起,但我会失去滚动。或者我会向后滚动,但随后会丢失文本换行。有一次我换行,从技术上讲它滚动了,但没有达到应有的效果,换句话说,滚动 Pane 没有检测到文本的大小。我需要嵌套的 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);
        }
    }

}

}

最佳答案

extends JTextPane

为什么?

setEditorKit(new TextWrapKit());

为什么?

使滚动 Pane 与默认组件一起使用。然后,如果由于某种原因您仍然需要自定义,请一次进行一项更改以确保它仍然有效。如果它不再起作用,那么您就知道问题出在哪里。

packEdit.add(numPane,BorderLayout.WEST);

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

将来,每个问题都应该发布一个 SSCCE。您无需 SSCCE 即可获得一个免费(尝试)答案。

关于java - 如何正确地将 JTextPane/JPanel 打包到 JPanel 中到 JScrollPane 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20182978/

相关文章:

java - Http 连接读取超时

android - 如何对齐屏幕底部的 View ?

open-source - 推荐开源项目,UI开发

ios - trigger.io 自定义原生按钮工具栏和标签栏

java - 在 Java servlet 中使用 x509 证书公钥

java - 将 Spring 字段注入(inject)转换为构造函数注入(inject)(IntelliJ IDEA)?

java - 我需要创建 XML-PRC 兼容的 Web 服务

java - 为两个不同的 JButton 设置不同的禁用颜色? (UIManager.getDefaults 更改两个按钮)

java - 同步一系列异步调用

java - 将 JPanel 添加到 JList