Java 自定义JScrollPane。在滚动条行上添加组件

Java 自定义JScrollPane。在滚动条行上添加组件,java,swing,jscrollpane,jlabel,jscrollbar,Java,Swing,Jscrollpane,Jlabel,Jscrollbar,这就是我想要实现的目标: 如您所见,水平滚动已更改,应在同一行中添加JLabel(“文本”)。目前,我找到了更改水平滚动的方法(如在图像上),但我找不到任何方法在图像上放置JLabel(“文本”)的地方添加JLabel(“文本”) 有什么建议吗?提前谢谢 import java.awt.Component; import java.awt.Container; import java.awt.Point; import javax.swing.JFrame; import javax.swi

这就是我想要实现的目标:

如您所见,水平滚动已更改,应在同一行中添加JLabel(“文本”)。目前,我找到了更改水平滚动的方法(如在图像上),但我找不到任何方法在图像上放置JLabel(“文本”)的地方添加JLabel(“文本”)

有什么建议吗?提前谢谢

import java.awt.Component;
import java.awt.Container;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneLayout;
import javax.swing.WindowConstants;

public class Test {

    public static void main(String[] args) {
        JFrame jFrame = new JFrame();
        jFrame.setSize(300, 300);

        JPanel myPanel = new JPanel();
        myPanel.add(new JLabel("Check Check Check Check Check Check Check Check"));
        MyScrollPane scrollPane = new MyScrollPane(myPanel);

        jFrame.add(scrollPane);
        jFrame.setVisible(true);
        jFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    }

}

class MyScrollPane extends JScrollPane {

    JLabel label = new JLabel("text");

    public MyScrollPane(Component view) {
        super(view, VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_ALWAYS);
        this.setLayout(new MyLayout(label));
        add(label);
    }
}

class MyLayout extends ScrollPaneLayout {

    JLabel label;

    public MyLayout(JLabel aLabel) {
        super();
        label = aLabel;
    }

    public void layoutContainer(Container parent) {
        super.layoutContainer(parent);

        hsb.setSize(hsb.getWidth() - 100, hsb.getHeight()); // drift
        Point location = hsb.getLocation();
        label.setLocation(location.x + 12, location.y - 12);
    }
}

您可能想考虑自己实现JScRelpANE。这听起来可能很吓人,但实际上一个JScrollPane只有2个JScrollBars和一些调用g.translate()的图形逻辑。如果你使用g.translate,你会发现滚动你自己的东西非常容易


制作自己的组件的优点是,您可以完全控制布局、显示和事件。如果我处在你的位置,这是我的路线。

你可能想考虑自己的JSCROLBONE实现。这听起来可能很吓人,但实际上一个JScrollPane只有2个JScrollBars和一些调用g.translate()的图形逻辑。如果你使用g.translate,你会发现滚动你自己的东西非常容易

制作自己的组件的优点是,您可以完全控制布局、显示和事件。如果我处在你的位置,我会走这条路。

以下是我的尝试:

import java.awt.*;
import java.awt.font.*;
import javax.swing.*;
import javax.swing.border.*;

public class Test2 {
  public JComponent makeUI() {
    JPanel myPanel = new JPanel();
    myPanel.add(new JLabel("Check Check Check Check Check Check Check Check"));
    JScrollPane scrollPane = new JScrollPane(myPanel,
        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
        JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    JScrollBar hsb = scrollPane.getHorizontalScrollBar();
    hsb.setBorder(new StringBorder(hsb, "Test"));
    JPanel p = new JPanel(new BorderLayout());
    p.add(scrollPane);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new Test2().makeUI());
    f.setSize(300, 300);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
class StringBorder implements Border {
  private final JComponent parent;
  private final Insets insets;
  private final Rectangle rect;
  private final String str;
  public StringBorder(JComponent parent, String str) {
    this.parent = parent;
    this.str = str;
    FontRenderContext frc = new FontRenderContext(null, true, true);
    rect = parent.getFont().getStringBounds(str, frc).getBounds();
    rect.width = Math.max(rect.width, 100);
    insets = new Insets(0,5,0,rect.width);
  }
  @Override public Insets getBorderInsets(Component c) {
    return insets;
  }
  @Override public boolean isBorderOpaque() {
    return false;
  }
  @Override public void paintBorder(
      Component c, Graphics g, int x, int y, int width, int height) {
    Graphics2D g2 = (Graphics2D)g;
    float tx = x + width - insets.right + insets.left;
    float ty = y - rect.y + (height - rect.height)/2;
    g2.setPaint(Color.BLACK);
    g2.drawString(str, tx, ty);
  }
}
以下是我的尝试:

import java.awt.*;
import java.awt.font.*;
import javax.swing.*;
import javax.swing.border.*;

public class Test2 {
  public JComponent makeUI() {
    JPanel myPanel = new JPanel();
    myPanel.add(new JLabel("Check Check Check Check Check Check Check Check"));
    JScrollPane scrollPane = new JScrollPane(myPanel,
        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
        JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    JScrollBar hsb = scrollPane.getHorizontalScrollBar();
    hsb.setBorder(new StringBorder(hsb, "Test"));
    JPanel p = new JPanel(new BorderLayout());
    p.add(scrollPane);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new Test2().makeUI());
    f.setSize(300, 300);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
class StringBorder implements Border {
  private final JComponent parent;
  private final Insets insets;
  private final Rectangle rect;
  private final String str;
  public StringBorder(JComponent parent, String str) {
    this.parent = parent;
    this.str = str;
    FontRenderContext frc = new FontRenderContext(null, true, true);
    rect = parent.getFont().getStringBounds(str, frc).getBounds();
    rect.width = Math.max(rect.width, 100);
    insets = new Insets(0,5,0,rect.width);
  }
  @Override public Insets getBorderInsets(Component c) {
    return insets;
  }
  @Override public boolean isBorderOpaque() {
    return false;
  }
  @Override public void paintBorder(
      Component c, Graphics g, int x, int y, int width, int height) {
    Graphics2D g2 = (Graphics2D)g;
    float tx = x + width - insets.right + insets.left;
    float ty = y - rect.y + (height - rect.height)/2;
    g2.setPaint(Color.BLACK);
    g2.drawString(str, tx, ty);
  }
}

可能实现这种效果的最好方法是使用自己的布局和
JScrollPane
。下面是一个允许任何组件作为左下角组件的示例:

public class CustomScrollPaneLayout extends ScrollPaneLayout {
    @Override
    public void layoutContainer(Container parent) {
        super.layoutContainer(parent);

        JScrollBar scrollBar = getHorizontalScrollBar();
        if (lowerLeft == null || !lowerLeft.isVisible() || scrollBar == null)
            return;

        Dimension size = lowerLeft.getPreferredSize();
        Rectangle bounds = lowerLeft.isVisible()
                ? lowerLeft.getBounds() : scrollBar.getBounds();
        if (size.width > bounds.getWidth()) {
            int right = scrollBar.getX()+scrollBar.getWidth();
            if (size.width + scrollBar.getMinimumSize().width > right)
                size.width = right - scrollBar.getMinimumSize().width;
            if (bounds.x + size.width < scrollBar.getX())
                size.width = scrollBar.getX() - bounds.x;

            lowerLeft.setBounds(bounds.x, bounds.y, size.width, bounds.height);
            int x = bounds.x + size.width;
            scrollBar.setBounds(x, bounds.y, right - x, bounds.height);
        }
        lowerLeft.setVisible(true);
    }
}
公共类CustomScrollPaneLayout扩展了ScrollPaneLayout{
@凌驾
公共无效布局容器(容器父级){
super.layoutContainer(父级);
JScrollBar scrollBar=getHorizontalScrollBar();
如果(lowerLeft==null | |!lowerLeft.isVisible()| |滚动条==null)
返回;
维度大小=lowerLeft.getPreferredSize();
矩形边界=lowerLeft.isVisible()
?lowerLeft.getBounds():滚动条.getBounds();
如果(size.width>bounds.getWidth()){
int right=scrollBar.getX()+scrollBar.getWidth();
if(size.width+scrollBar.getMinimumSize().width>right)
size.width=右-滚动条.getMinimumSize().width;
if(bounds.x+size.width

请注意,您需要使用水平滚动条策略
ScrollPaneConstants。如果您希望控件始终可见,则水平滚动条策略始终为

实现这种效果的最佳方法可能是使用自己的布局和
JScrollPane
。下面是一个允许任何组件作为左下角组件的示例:

public class CustomScrollPaneLayout extends ScrollPaneLayout {
    @Override
    public void layoutContainer(Container parent) {
        super.layoutContainer(parent);

        JScrollBar scrollBar = getHorizontalScrollBar();
        if (lowerLeft == null || !lowerLeft.isVisible() || scrollBar == null)
            return;

        Dimension size = lowerLeft.getPreferredSize();
        Rectangle bounds = lowerLeft.isVisible()
                ? lowerLeft.getBounds() : scrollBar.getBounds();
        if (size.width > bounds.getWidth()) {
            int right = scrollBar.getX()+scrollBar.getWidth();
            if (size.width + scrollBar.getMinimumSize().width > right)
                size.width = right - scrollBar.getMinimumSize().width;
            if (bounds.x + size.width < scrollBar.getX())
                size.width = scrollBar.getX() - bounds.x;

            lowerLeft.setBounds(bounds.x, bounds.y, size.width, bounds.height);
            int x = bounds.x + size.width;
            scrollBar.setBounds(x, bounds.y, right - x, bounds.height);
        }
        lowerLeft.setVisible(true);
    }
}
公共类CustomScrollPaneLayout扩展了ScrollPaneLayout{
@凌驾
公共无效布局容器(容器父级){
super.layoutContainer(父级);
JScrollBar scrollBar=getHorizontalScrollBar();
如果(lowerLeft==null | |!lowerLeft.isVisible()| |滚动条==null)
返回;
维度大小=lowerLeft.getPreferredSize();
矩形边界=lowerLeft.isVisible()
?lowerLeft.getBounds():滚动条.getBounds();
如果(size.width>bounds.getWidth()){
int right=scrollBar.getX()+scrollBar.getWidth();
if(size.width+scrollBar.getMinimumSize().width>right)
size.width=右-滚动条.getMinimumSize().width;
if(bounds.x+size.width

请注意,如果希望控件始终可见,则需要使用水平滚动条策略
ScrollPaneConstants。水平滚动条总是

我想指出,标签的放置并未考虑“hsb”的宽度。你需要加上12号的宽度。是的,你是对的,但事实并非如此,位置不是问题。看起来根本没有添加标签,或者标签放在其他组件后面,所以我们看不到它。我想指出的是,标签的放置并未考虑“hsb”的宽度。你需要加上12号的宽度。是的,你是对的,但事实并非如此,位置不是问题。看起来标签根本没有添加,或者它放在其他组件后面,所以我们看不到它。非常感谢,这真的很酷!我没有想过用这种方法来解决这个问题。是否可以在滚动条附近添加一个JComponent(JLabel(“Text”)只是一些抽象JComponent的一个示例)?实际上,我想添加一个带有放大/缩小功能的JPanelbuttons@Stas试试这个链接:非常感谢,这真的很酷!我没有想过用这种方法来解决这个问题。是否可以在滚动条附近添加一个JComponent(JLabel(“Text”)只是一些抽象JComponent的一个示例)?实际上,我想添加一个带有放大/缩小功能的JPanelbuttons@Stas请尝试以下链接: