Java 自定义JScrollPane。在滚动条行上添加组件
这就是我想要实现的目标: 如您所见,水平滚动已更改,应在同一行中添加JLabel(“文本”)。目前,我找到了更改水平滚动的方法(如在图像上),但我找不到任何方法在图像上放置JLabel(“文本”)的地方添加JLabel(“文本”) 有什么建议吗?提前谢谢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
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请尝试以下链接: