我正在尝试在另一个JScrollPane
中添加JScrollPane
。
内部JScrollPane
仅滚动HORIZONTAL,外部仅滚动VERTICAL。
在此图片中,您可以看到水平滚动条在添加mainPanel
时有效(但此处尚未添加水平滚动条)
以下是将outerVerticalScroller
添加到JFrame时的外观(水平条消失了):
知道如何做到这一点?
如果我跳过mainPanel
而是输入:
JScrollPane outerVerticalScroller = new JScrollPane(panelScroller, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
然后两个滚动条看起来都很完美:
但我需要额外的“mainPanel”。有什么想法吗?
public class ScrollersTest extends JFrame {
public ScrollersTest() {
super("A JScrollPane inside a JScrollPane");
setDefaultCloseOperation(EXIT_ON_CLOSE);
init();
setVisible(true);
pack();
}
public void init() {
ScrollablePanel panelScroller = new ScrollablePanel(new GridBagLayout());
panelScroller.setScrollableWidth(ScrollablePanel.ScrollableSizeHint.FIT);
GridBagConstraints c = new GridBagConstraints();
// INNER SCROLLPANE: ONLY SCROLL HORIZONTAL
JTextArea innerText = new JTextArea("This text is inside a JScrollPane of its own. But no scroller is shown when the frames size is decreased. Wrong viewPort?....................................");
JScrollPane innerHorizantalScroller = new JScrollPane(innerText, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
panelScroller.add(innerHorizantalScroller, c);
// SET SIZE OF SCROLLER HEIGHT
Dimension d = innerHorizantalScroller.getPreferredSize();
innerHorizantalScroller.setPreferredSize(new Dimension(d.width, d.height * 2));
innerHorizantalScroller.setMinimumSize(new Dimension(0, d.height * 2));
// EXTRA PANEL NEEDED (BUT MAKES HORIZANTAL SCROLLING DISAPEAR)
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(panelScroller, BorderLayout.CENTER);
// THE FRAME SCROLLPANE: ONLY SCROLL VERTICAL
JScrollPane outerVerticalScroller = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// WORKS BUT NO MAINPANEL
// JScrollPane outerVerticalScroller = new JScrollPane(panelScroller, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(outerVerticalScroller, BorderLayout.CENTER);
// getContentPane().add(mainPanel, BorderLayout.CENTER); // WORKS_BUT_NO_VERTICAL_SCROLL
}
public static void main(String args[]) {
new ScrollersTest();
}
static class ScrollablePanel extends JPanel implements Scrollable, SwingConstants {
public enum ScrollableSizeHint {
NONE, FIT, STRETCH;
}
public enum IncrementType {
PERCENT, PIXELS;
}
private ScrollableSizeHint scrollableHeight = ScrollableSizeHint.NONE;
private ScrollableSizeHint scrollableWidth = ScrollableSizeHint.NONE;
private IncrementInfo horizontalBlock;
private IncrementInfo horizontalUnit;
private IncrementInfo verticalBlock;
private IncrementInfo verticalUnit;
/**
* Default constructor that uses a FlowLayout
*/
public ScrollablePanel() {
this(new FlowLayout());
}
/**
* Constuctor for specifying the LayoutManager of the panel.
*
* @param layout
* the LayountManger for the panel
*/
public ScrollablePanel(LayoutManager layout) {
super(layout);
IncrementInfo block = new IncrementInfo(IncrementType.PERCENT, 100);
IncrementInfo unit = new IncrementInfo(IncrementType.PERCENT, 10);
setScrollableBlockIncrement(HORIZONTAL, block);
setScrollableBlockIncrement(VERTICAL, block);
setScrollableUnitIncrement(HORIZONTAL, unit);
setScrollableUnitIncrement(VERTICAL, unit);
}
/**
* Get the height ScrollableSizeHint enum
*
* @return the ScrollableSizeHint enum for the height
*/
public ScrollableSizeHint getScrollableHeight() {
return scrollableHeight;
}
/**
* Set the ScrollableSizeHint enum for the height. The enum is used to
* determine the boolean value that is returned by the
* getScrollableTracksViewportHeight() method. The valid values are:
*
* ScrollableSizeHint.NONE - return "false", which causes the height of
* the panel to be used when laying out the children
* ScrollableSizeHint.FIT - return "true", which causes the height of
* the viewport to be used when laying out the children
* ScrollableSizeHint.STRETCH - return "true" when the viewport height
* is greater than the height of the panel, "false" otherwise.
*
* @param scrollableHeight
* as represented by the ScrollableSizeHint enum.
*/
public void setScrollableHeight(ScrollableSizeHint scrollableHeight) {
this.scrollableHeight = scrollableHeight;
revalidate();
}
/**
* Get the width ScrollableSizeHint enum
*
* @return the ScrollableSizeHint enum for the width
*/
public ScrollableSizeHint getScrollableWidth() {
return scrollableWidth;
}
/**
* Set the ScrollableSizeHint enum for the width. The enum is used to
* determine the boolean value that is returned by the
* getScrollableTracksViewportWidth() method. The valid values are:
*
* ScrollableSizeHint.NONE - return "false", which causes the width of
* the panel to be used when laying out the children
* ScrollableSizeHint.FIT - return "true", which causes the width of the
* viewport to be used when laying out the children
* ScrollableSizeHint.STRETCH - return "true" when the viewport width is
* greater than the width of the panel, "false" otherwise.
*
* @param scrollableWidth
* as represented by the ScrollableSizeHint enum.
*/
public void setScrollableWidth(ScrollableSizeHint scrollableWidth) {
this.scrollableWidth = scrollableWidth;
revalidate();
}
/**
* Get the block IncrementInfo for the specified orientation
*
* @return the block IncrementInfo for the specified orientation
*/
public IncrementInfo getScrollableBlockIncrement(int orientation) {
return orientation == SwingConstants.HORIZONTAL ? horizontalBlock : verticalBlock;
}
/**
* Specify the information needed to do block scrolling.
*
* @param orientation
* specify the scrolling orientation. Must be either:
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
* @paran type specify how the amount parameter in the calculation of
* the scrollable amount. Valid values are: IncrementType.PERCENT
* - treat the amount as a % of the viewport size
* IncrementType.PIXEL - treat the amount as the scrollable
* amount
* @param amount
* a value used with the IncrementType to determine the
* scrollable amount
*/
public void setScrollableBlockIncrement(int orientation, IncrementType type, int amount) {
IncrementInfo info = new IncrementInfo(type, amount);
setScrollableBlockIncrement(orientation, info);
}
/**
* Specify the information needed to do block scrolling.
*
* @param orientation
* specify the scrolling orientation. Must be either:
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
* @param info
* An IncrementInfo object containing information of how to
* calculate the scrollable amount.
*/
public void setScrollableBlockIncrement(int orientation, IncrementInfo info) {
switch (orientation) {
case SwingConstants.HORIZONTAL:
horizontalBlock = info;
break;
case SwingConstants.VERTICAL:
verticalBlock = info;
break;
default:
throw new IllegalArgumentException("Invalid orientation: " + orientation);
}
}
/**
* Get the unit IncrementInfo for the specified orientation
*
* @return the unit IncrementInfo for the specified orientation
*/
public IncrementInfo getScrollableUnitIncrement(int orientation) {
return orientation == SwingConstants.HORIZONTAL ? horizontalUnit : verticalUnit;
}
/**
* Specify the information needed to do unit scrolling.
*
* @param orientation
* specify the scrolling orientation. Must be either:
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
* @paran type specify how the amount parameter in the calculation of
* the scrollable amount. Valid values are: IncrementType.PERCENT
* - treat the amount as a % of the viewport size
* IncrementType.PIXEL - treat the amount as the scrollable
* amount
* @param amount
* a value used with the IncrementType to determine the
* scrollable amount
*/
public void setScrollableUnitIncrement(int orientation, IncrementType type, int amount) {
IncrementInfo info = new IncrementInfo(type, amount);
setScrollableUnitIncrement(orientation, info);
}
/**
* Specify the information needed to do unit scrolling.
*
* @param orientation
* specify the scrolling orientation. Must be either:
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
* @param info
* An IncrementInfo object containing information of how to
* calculate the scrollable amount.
*/
public void setScrollableUnitIncrement(int orientation, IncrementInfo info) {
switch (orientation) {
case SwingConstants.HORIZONTAL:
horizontalUnit = info;
break;
case SwingConstants.VERTICAL:
verticalUnit = info;
break;
default:
throw new IllegalArgumentException("Invalid orientation: " + orientation);
}
}
// Implement Scrollable interface
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
public int getScrollableUnitIncrement(Rectangle visible, int orientation, int direction) {
switch (orientation) {
case SwingConstants.HORIZONTAL:
return getScrollableIncrement(horizontalUnit, visible.width);
case SwingConstants.VERTICAL:
return getScrollableIncrement(verticalUnit, visible.height);
default:
throw new IllegalArgumentException("Invalid orientation: " + orientation);
}
}
public int getScrollableBlockIncrement(Rectangle visible, int orientation, int direction) {
switch (orientation) {
case SwingConstants.HORIZONTAL:
return getScrollableIncrement(horizontalBlock, visible.width);
case SwingConstants.VERTICAL:
return getScrollableIncrement(verticalBlock, visible.height);
default:
throw new IllegalArgumentException("Invalid orientation: " + orientation);
}
}
protected int getScrollableIncrement(IncrementInfo info, int distance) {
if (info.getIncrement() == IncrementType.PIXELS)
return info.getAmount();
else
return distance * info.getAmount() / 100;
}
public boolean getScrollableTracksViewportWidth() {
if (scrollableWidth == ScrollableSizeHint.NONE)
return false;
if (scrollableWidth == ScrollableSizeHint.FIT)
return true;
// STRETCH sizing, use the greater of the panel or viewport width
if (getParent() instanceof JViewport) {
return (((JViewport) getParent()).getWidth() > getPreferredSize().width);
}
return false;
}
public boolean getScrollableTracksViewportHeight() {
if (scrollableHeight == ScrollableSizeHint.NONE)
return false;
if (scrollableHeight == ScrollableSizeHint.FIT)
return true;
// STRETCH sizing, use the greater of the panel or viewport height
if (getParent() instanceof JViewport) {
return (((JViewport) getParent()).getHeight() > getPreferredSize().height);
}
return false;
}
/**
* Helper class to hold the information required to calculate the scroll
* amount.
*/
static class IncrementInfo {
private IncrementType type;
private int amount;
public IncrementInfo(IncrementType type, int amount) {
this.type = type;
this.amount = amount;
}
public IncrementType getIncrement() {
return type;
}
public int getAmount() {
return amount;
}
public String toString() {
return "ScrollablePanel[" + type + ", " + amount + "]";
}
}
}
}
答案 0 :(得分:2)
根据您对OP的ItachiUchiha评论的回答,它听起来像是你想要的可滚动文本,这是在可滚动的JPanel上。
如何使用更适合滚动文本的JTextArea(像标签一样装饰),而不是使用JLabel?
对现有代码的修改很少:
import java.awt.*;
import javax.swing.*;
public class ScrollersTest extends JFrame {
public static void main(String args[]) {
new ScrollersTest();
}
public ScrollersTest() {
super("A JScrollPane inside a JScrollPane");
setDefaultCloseOperation(EXIT_ON_CLOSE);
init();
pack();
setVisible(true);
}
public void init() {
JPanel p = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
String text = "This text is inside a JScrollPane of its own. "
+ "But no scroller is shown when the frames size is decreased. "
+ "Wrong viewPort?....................................";
// INNER SCROLLPANE:
JTextArea innerText = new JTextArea(1, 20);
innerText.setText(text);
innerText.setEditable(false);
innerText.setOpaque(false);
JScrollPane innerScroller = new JScrollPane(innerText,
JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
p.add(innerScroller);
// FRAMES SCROLLPANE: ONLY SCROLL VERTICAL
JScrollPane frameScrollpane = new JScrollPane(p,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(frameScrollpane, BorderLayout.CENTER);
}
}
答案 1 :(得分:2)
JScrollPane中。内部JScrollPane只会滚动HORIZONTAL
然后我认为您需要强制组件适合视口。您可以通过为面板实施Scrollable interface
来实现此目的。或者,更简单的方法是使用Scrollable Panel为您完成所有工作。
import java.awt.*;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class ScrollersTest extends JFrame {
public ScrollersTest() {
super("A JScrollPane inside a JScrollPane");
setDefaultCloseOperation(EXIT_ON_CLOSE);
init();
setVisible(true);
pack();
}
public void init() {
// JPanel p = new JPanel(new GridBagLayout());
ScrollablePanel p = new ScrollablePanel( new BorderLayout() );
p.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
GridBagConstraints c = new GridBagConstraints();
// INNER SCROLLPANE: ONLY SCROLL HORIZONTAL: DOSE NOT WORK...
JLabel innerText = new JLabel("This text is inside a JScrollPane of its own. But no scroller is shown when the frames size is decreased. Wrong viewPort?....................................");
JScrollPane innerScroller = new JScrollPane(innerText, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
Dimension d = innerScroller.getPreferredSize();
innerScroller.setPreferredSize( new Dimension(d.width, d.height * 2) );
// p.add(innerScroller, c);
p.add(innerScroller, BorderLayout.NORTH);
// FRAMES SCROLLPANE: ONLY SCROLL VERTICAL
JScrollPane frameScrollpane = new JScrollPane(p, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(frameScrollpane, BorderLayout.CENTER);
}
public static void main(String args[]) {
new ScrollersTest();
}
}
我在这个例子中使用了BorderLayout,因为它更易于使用。如果要使用GridBagLayout,则需要正确配置约束,以便组件以合理的方式增长/缩小。使用默认值时,组件将默认为其最小大小(0,0),因此您只能在框架上看到一个小矩形。
答案 2 :(得分:1)
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.*;
import java.awt.*;
class ScrollersTest {
public static void main(String args[]) {
JFrame frame = new JFrame("Tabbed Pane Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea innerText = new JTextArea("This text is inside a JScrollPane of its own."
+" But no scroller is shown when the frames size is decreased. Wrong viewPort?....................................\n"
+" But no scroller is shown when the frames size is decreased. Wrong viewPort?....................................\n"
+" But no scroller is shown when the frames size is decreased. Wrong viewPort?....................................\n");
innerText.setBounds(100,100,500,500);
JScrollPane innerScroller = new JScrollPane(innerText);
innerScroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
innerScroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel p = new JPanel(new GridBagLayout());
p.add(innerScroller);
JScrollPane jScrollPane = new JScrollPane(p);
jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
frame.add(jScrollPane, BorderLayout.CENTER);
frame.setSize(400, 150);
frame.setVisible(true);
}
}