java popup menu scroll bar 적용 질문드립니다.

say5371의 이미지

밑에 있는 코드는 java의 jpopupmenu에 scroll을 적용시키는 예제입니다.
jscrollpopupmenu로 객체를 생성하면 스크롤이 잘 적용되기는 하는데 크기를 고정해서 쓰려니까 아이템이 추가가 되면
일부 아이템이 보이지 않는 현상이 발생합니다.
아이템 갯수에 따라 스크롤바의 크기를 조정할 수 있었으면 좋겠는데... 제가 초보인지라 많이 부족해 이곳에 여쭤봅니다.
제발 도와주세요 ㅠㅠ

(참고)크기조정은 menu.setPreferredSize(new Dimension(630, height)); 이런식으로 하고 있습니다.

 
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
 
import javax.swing.JPopupMenu;
import javax.swing.JScrollBar;
 
public class JScrollPopupMenu extends JPopupMenu {
protected int maximumVisibleRows = 8;
 
	public JScrollPopupMenu() {
	    this(null);
	}
 
 
	public JScrollPopupMenu(String label) {
	    super(label);
	    setLayout(new ScrollPopupMenuLayout());
 
	    super.add(getScrollBar());
	    addMouseWheelListener(new MouseWheelListener() {
	        @Override public void mouseWheelMoved(MouseWheelEvent event) {
	            JScrollBar scrollBar = getScrollBar();
	            int amount = (event.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
	                         ? event.getUnitsToScroll() * scrollBar.getUnitIncrement()
	                         : (event.getWheelRotation() < 0 ? -1 : 1) * scrollBar.getBlockIncrement();
 
	            scrollBar.setValue(scrollBar.getValue() + amount);
	            event.consume();
	        }
	    });
	}
 
	private JScrollBar popupScrollBar;
	protected JScrollBar getScrollBar() {
	    if(popupScrollBar == null) {
	        popupScrollBar = new JScrollBar(JScrollBar.VERTICAL);
	        popupScrollBar.addAdjustmentListener(new AdjustmentListener() {
	            @Override public void adjustmentValueChanged(AdjustmentEvent e) {
	                doLayout();
	                repaint();
	            }
	        });
 
	        popupScrollBar.setVisible(false);
	    }
 
	    return popupScrollBar;
	}
 
	public int getMaximumVisibleRows() {
	    return maximumVisibleRows;
	}
 
	public void setMaximumVisibleRows(int maximumVisibleRows) {
	    this.maximumVisibleRows = maximumVisibleRows;
	}
 
	public void paintChildren(Graphics g){
	    Insets insets = getInsets();
	    g.clipRect(insets.left, insets.top, getWidth(), getHeight() - insets.top - insets.bottom);
	    super.paintChildren(g);
	}
 
	protected void addImpl(Component comp, Object constraints, int index) {
	    super.addImpl(comp, constraints, index);
 
	    if(maximumVisibleRows < getComponentCount()-1) {
	        getScrollBar().setVisible(true);
	    }
	}
 
	public void remove(int index) {
	    // can't remove the scrollbar
	    ++index;
 
	    super.remove(index);
 
	    if(maximumVisibleRows >= getComponentCount()-1) {
	        getScrollBar().setVisible(false);
	    }
	}
 
	public void show(Component invoker, int x, int y){
	    JScrollBar scrollBar = getScrollBar();
	    if(scrollBar.isVisible()){
	        int extent = 0;
	        int max = 0;
	        int i = 0;
	        int unit = -1;
	        int width = 0;
	        for(Component comp : getComponents()) {
	            if(!(comp instanceof JScrollBar)) {
	                Dimension preferredSize = comp.getPreferredSize();
	                width = Math.max(width, preferredSize.width);
	                if(unit < 0){
	                    unit = preferredSize.height;
	                }
	                if(i++ < maximumVisibleRows) {
	                    extent += preferredSize.height;
	                }
	                max += preferredSize.height;
	            }
	        }
 
	        Insets insets = getInsets();
	        int widthMargin = insets.left + insets.right;
	        int heightMargin = insets.top + insets.bottom;
	        scrollBar.setUnitIncrement(unit);
	        scrollBar.setBlockIncrement(extent);
	        scrollBar.setValues(0, heightMargin + extent, 0, heightMargin + max);
 
	        width += scrollBar.getPreferredSize().width + widthMargin;
	        int height = heightMargin + extent;
	        setPopupSize(new Dimension (width,height));
	    }
 
	    super.show(invoker, x, y);
	}
 
	protected static class ScrollPopupMenuLayout implements LayoutManager{
	    @Override public void addLayoutComponent(String name, Component comp) {}
	    @Override public void removeLayoutComponent(Component comp) {}
 
	    @Override public Dimension preferredLayoutSize(Container parent) {
	        int visibleAmount = Integer.MAX_VALUE;
	        Dimension dim = new Dimension();
	        for(Component comp :parent.getComponents()){
	            if(comp.isVisible()) {
	                if(comp instanceof JScrollBar){
	                    JScrollBar scrollBar = (JScrollBar) comp;
	                    visibleAmount = scrollBar.getVisibleAmount();
	                }
	                else {
	                    Dimension pref = comp.getPreferredSize();
	                    dim.width = Math.max(dim.width, pref.width);
	                    dim.height += pref.height;
	                }
	            }
	        }
 
	        Insets insets = parent.getInsets();
	        dim.height = Math.min(dim.height + insets.top + insets.bottom, visibleAmount);
 
	        return dim;
	    }
 
	    @Override public Dimension minimumLayoutSize(Container parent) {
	        int visibleAmount = Integer.MAX_VALUE;
	        Dimension dim = new Dimension();
	        for(Component comp : parent.getComponents()) {
	            if(comp.isVisible()){
	                if(comp instanceof JScrollBar) {
	                    JScrollBar scrollBar = (JScrollBar) comp;
	                    visibleAmount = scrollBar.getVisibleAmount();
	                }
	                else {
	                    Dimension min = comp.getMinimumSize();
	                    dim.width = Math.max(dim.width, min.width);
	                    dim.height += min.height;
	                }
	            }
	        }
 
	        Insets insets = parent.getInsets();
	        dim.height = Math.min(dim.height + insets.top + insets.bottom, visibleAmount);
 
	        return dim;
	    }
 
	    @Override public void layoutContainer(Container parent) {
	        Insets insets = parent.getInsets();
 
	        int width = parent.getWidth() - insets.left - insets.right;
	        int height = parent.getHeight() - insets.top - insets.bottom;
 
	        int x = insets.left;
	        int y = insets.top;
	        int position = 0;
 
	        for(Component comp : parent.getComponents()) {
	            if((comp instanceof JScrollBar) && comp.isVisible()) {
	                JScrollBar scrollBar = (JScrollBar) comp;
	                Dimension dim = scrollBar.getPreferredSize();
	                scrollBar.setBounds(x + width-dim.width, y, dim.width, height);
	                width -= dim.width;
	                position = scrollBar.getValue();
	            }
	        }
 
	        y -= position;
	        for(Component comp : parent.getComponents()) {
	            if(!(comp instanceof JScrollBar) && comp.isVisible()) {
	                Dimension pref = comp.getPreferredSize();
	                comp.setBounds(x, y, width, pref.height);
	                y += pref.height;
	            }
	        }
	    }
	}
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.