我想在Swing图形用户界面的JScrollPane中添加一个非滚动元素,始终可见的元素("钉住的"元素).以此示例代码为例:

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JEditorPane editorPane = new JEditorPane();
        editorPane.setText("""
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                d
                """);
        JScrollPane scroll = new JScrollPane(editorPane);
        editorPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
        editorPane.add(new JLabel("this shouldn't scroll!"));

        frame.getContentPane().add(scroll);
        frame.setSize(600, 400);
        frame.setVisible(true);
    }
}

Which produces this GUI:
the swing panel created by the code

我需要一种方法来:

  1. 确保"这不应该滚动!"滚动窗格滚动时,JLabel不会移动.
  2. 别针"这不应该滚动!"面板右侧的JLabel(目前,它随着面板大小的调整而隐藏.我希望当面板的右侧被推小时,它会向左移动,以确保它始终显示在屏幕上).

我已经能够使用Swing的玻璃面板来实现这个糟糕的功能,但这对我来说意味着更多的手动更新,而且位置总是相同的,无论Swing面板的大小如何调整.

谢谢你的帮助!

推荐答案

作为个人偏好,我可能会使用复合布局,类似于this example,因为它让你更好地控制组件的呈现(即更容易处理活动组件,如按钮)和它的位置.

例如,您"可以"使用JLayerAPI...

enter image description here

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.plaf.LayerUI;

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

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() throws IOException {
            FixedTextLayerUI layerUI = new FixedTextLayerUI();
            layerUI.setText("this shouldn't scroll!");

            JTextArea ta = new JTextArea(20, 40);
            StringBuilder sb = new StringBuilder(1024);
            // Bring your own content ;)
            try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/resources/StarWarsNewHope.txt")))) {
                String text = null;
                while ((text = br.readLine()) != null) {
                    sb.append(text);
                    sb.append(System.lineSeparator());
                }
                ta.setText(sb.toString());
            }
            JLayer<JComponent> layer = new JLayer<JComponent>(new JScrollPane(ta), layerUI);
            setLayout(new BorderLayout());
            add(layer);
        }

    }

    public class FixedTextLayerUI extends LayerUI<JComponent> {

        private String text;

        public void setText(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        @Override
        public void paint(Graphics g, JComponent c) {
            super.paint(g, c);

            Graphics2D g2 = (Graphics2D) g.create();

            FontMetrics fm = g2.getFontMetrics();
            int stringWidth = fm.stringWidth(getText());
            int x = c.getWidth() - stringWidth - 8;
            int y = fm.getHeight() + fm.getAscent() + 8;

            if (c instanceof JLayer) {
                JLayer layer = (JLayer) c;
                if (layer.getView() instanceof JScrollPane) {
                    JScrollPane scrollPane = (JScrollPane) layer.getView();
                    JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
                    if (scrollBar.isVisible()) {
                        x -= scrollBar.getWidth();
                    }
                }
            }

            g2.drawString(text, x, y);

            g2.dispose();
        }

    }
}

有关更多详细信息,请参见How to Decorate Components with the JLayer Class.

Java相关问答推荐

将状态栏和导航栏设置为白色,带有深色文本

int Array Stream System. out. print方法在打印Java8时在末尾添加% sign

Jooq外键关系

使用@MappdSuperClass扩展ParentClass&Won t继承ParentClass属性

如何修复IndexOutOfBoundsException在ClerView适配器的onRowMoved函数?

内存中的H2修剪尾随空格

在Java中将int[]矩阵添加到ArrayList中,但出现错误

如果List是一个抽象接口,那么Collectors.toList()如何处理流呢?

将stringBuilder + forloop转换为stream + map

在不使用instanceof或强制转换的情况下从父类变量调用子类方法

如何在Java中使用正则表达式拆分字符串

在权限列表中找不到我的应用程序

如何使用jOOQ在PostgreSQL中从枚举类型生成Java枚举

让标签占用JavaFX中HBox的所有可用空间

为什么Spring要更改Java版本配置以及如何正确设置?

Java中的一个错误';s stdlib SocksSocketImpl?

JOOQ:批处理CRUD操作使用动态表定义,如何?

@此处不能应用可为null的批注

对于 Hangman 游戏,索引 0 超出长度 0 的范围

元音变音字符:如何在 Java 中将Á<0x9c>转换为Ü?