ScrollPane resizing unnecessarily

I have an instance of my custom panel in a JScrollPane that is in a JTabbedPane. The panel looks like this:
public class MyPanel extends JPanel {
  private int instance; 
  public MyPanel(int instance) {
    this.instance = instance;
    try {
    jbInit();
    } catch (Exception e) {
      e.printStackTrace();
  private void jbInit() throws Exception {
    this.setLayout(null);
    this.setPreferredSize(new Dimension(775,340));
    this.setSize(new Dimension(775,340));
    this.setMinimumSize(new Dimension(1,1));
    this.setMaximumSize(new Dimension(1200,1200));
    this.setBounds(0,0,775,340);
  protected void paintComponent(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;
    int instanceLineLength = instance * 110 + 70;
    if (instanceLineLength > 800) {
      this.setPreferredSize(new Dimension(instanceLineLength + 100, this.getHeight()));
      this.setSize(new Dimension(instanceLineLength + 100, this.getHeight()));
}My problem is when the if-block in paintComponent() isn't hit, the JScrollPane does not cause there to be a vertical scroll bar. But when the size gets changed in the if-block, it doesn't stay the same height, or not visually during runtime because the JScrollPane creates a vertical scroll bar for 10 pixels worth or so.
Thanks for the help!

Here's the updated code:
public class MyPanel extends JPanel {
  private int instance; 
  public MyPanel(int instance) {
    this.instance = instance;
    try {
    jbInit();
    } catch (Exception e) {
      e.printStackTrace();
  private void jbInit() throws Exception {
    this.setLayout(null);
    this.setPreferredSize(new Dimension(775,340));
    this.setSize(new Dimension(775,340));
    this.setMinimumSize(new Dimension(1,1));
    this.setMaximumSize(new Dimension(1200,1200));
    this.setBounds(0,0,775,340);
  protected void paintComponent(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;
    int instanceLineLength = instance * 110 + 70;
    //draw stuff here...
  //overwrite getPreferredSize() in order to return new size if panel wider than its container
  public Dimension getPreferredSize() {
    if (instance * 110 + 70 > 800)
      return new Dimension(instance * 110 + 170, this.getHeight());
    else
      return super.getPreferredSize();
}

Similar Messages

  • Resizing ScrollPane and Dimension dynamically

    I am currently making a scrollbar program using ScrollPane and Dimension. I have to use those classes.
    When I click "ok" button, that calls dc.enlarge(500,800) method. But it doesn't work.
    When it is clicked, Dimension object should be changed and the panel has to show Horizotal
    and Vertical scrollbar according to the width and height parameters.
    Of course, the size will be calculated by the String contents object's rows and width. But it does not work.
    How to resize the Dimension and How to display the Horizontal, Vertical scrollbar accoring to dc.enlarge's parameters?
    Plz... help me...
    -------------- ScrollerTest.java -----------------------------------------------
    import java.awt.*;
    import java.applet.Applet;
    public class ScrollerTest extends Applet {
       public Scroller sc = null;
        public void init() {
            sc = new Scroller(700,250);
            sc.setVisible(true);
         add(sc);         
    }-------------- Scroller.java -----------------------------------------------
    import java.awt.*;
    import java.awt.Window;
    import java.applet.Applet;
    import java.awt.event.*;
    public class Scroller extends Panel implements  ActionListener {
        private Button btOk;   
        private int width = 0;
        private int height = 0;   
        private DrawCanvas dc;   
        public Scroller(int width, int height){   
            this.width = width;
            this.height = height;   
            dc = new DrawCanvas(width, height);
            setNewsContents();                           
        private void setNewsContents() {
            setLayout(new BorderLayout());
            ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);       
            scroller.add(dc);
            Adjustable vadjust = scroller.getVAdjustable();
            Adjustable hadjust = scroller.getHAdjustable();
            hadjust.setUnitIncrement(10);
            vadjust.setUnitIncrement(10);
            scroller.setSize(615     , 272);
            btOk = new Button("ok");
            btOk.addActionListener(this);
            add("Center", scroller);
            add("South", btOk);       
        public void actionPerformed(ActionEvent event) {
            if(event.getSource()==btOk) {
                dc.enlarge(500,800);
                dc.validate();
    }    -------------- DrawCanvas.java -----------------------------------------------
    import java.awt.*;
    class DrawCanvas extends Component {
        private int width = 0;
        private int height = 0;
        private Dimension d;
        public DrawCanvas(int width, int height) {
            this.width = width;
            this.height = height;
       Dimension theSize = new Dimension(300, 200);   
       public Dimension getPreferredSize() {
            return new Dimension(width,height);               
       public void enlarge(int width, int height) {       
            theSize.width =  width;
            theSize.height = height;
            setSize(theSize);       
        public void update(Graphics g) {
            paint(g);
        public void paint(Graphics g) {       
            Rectangle r = getBounds();       
            String contents[] = {
            "addition to its usual stable of Clydesdale horses, the company will also enlist help this year ",
            "from racing star Dale Earnhardt Jr., some beer-thieving crabs and a scary hitchhiker.",       
            "The Super Bowl represents an enormous commitment for Budweiser. Bob Lachky, chief creative" ,
            "officer of Anheuser-Busch, said the St. Louis-based brewer has been advertising on the game since 1976 and has been the exclusive alcoholic beverage sponsor since 1989",
            "since 1976 and has been the exclusive alcoholic beverage sponsor since 1989, an arrangement that runs through 2012.",
            "It's important to us because it kicks off our selling season, it's the best platform",
            "possible to launch new ideas or to sustain existing campaigns, and it's absolutely the most efficient way to reach the most  it's absolutely the most efficient way to reach the most",
            "adult consumers in one sitting,",
            "Despite the rise of cable, the Internet other media to compete with broadcast television iewers and enticing a huge array of marketers ",
            ", the Super Bowl remains the most-viewed media event all year, drawing in some 90 million ",
            "viewers and enticing a huge array of marketers to pony up the big bucks for an ad",
            ", the price of which is running as high as $2.6 million for this year's broadcast",
            "on CBS Corp.'s CBS network, up slightly from about a top price of about $2.5 million last year.",
            "Comedian Carlos Mencia, of the Comedy Central show  gets ",
            "a big break with a spot set in a classroom. Lachky predicts that Mencia will get an enormous boost Lachky predicts that Mencia will get an enormous boost ",
            "following the appearance, which similarly did wonders for Cedric the Entertainer.",
            "And what would Budweiser Super Bowl ads be without some animated critters? This year, a ga",
            "ng of mischievous red crabs turn up on a beach to carry off a cooler full of beers. As in past years, Bud is keeping many ",
            g.setColor(new Color(226,250,255));
            g.fillRect(0, 0, r.width, r.height);
            g.setColor(new Color(233,231,224));            
            int line = 35;
            int line_1 = 39;
            for (int i = 0; i < contents.length; i++) {       
                 g.setColor(Color.BLACK);
                 g.drawString(contents, 5,line);
         g.setColor(new Color(233,231,224));
         g.drawLine(0,line_1,605,line_1);
         line += 20;
         line_1 += 20;

    I am currently making a scrollbar program using ScrollPane and Dimension. I have to use those classes.
    When I click "ok" button, that calls dc.enlarge(500,800) method. But it doesn't work.
    When it is clicked, Dimension object should be changed and the panel has to show Horizotal
    and Vertical scrollbar according to the width and height parameters.
    Of course, the size will be calculated by the String contents object's rows and width. But it does not work.
    How to resize the Dimension and How to display the Horizontal, Vertical scrollbar accoring to dc.enlarge's parameters?
    Plz... help me...
    -------------- ScrollerTest.java -----------------------------------------------
    import java.awt.*;
    import java.applet.Applet;
    public class ScrollerTest extends Applet {
       public Scroller sc = null;
        public void init() {
            sc = new Scroller(700,250);
            sc.setVisible(true);
         add(sc);         
    }-------------- Scroller.java -----------------------------------------------
    import java.awt.*;
    import java.awt.Window;
    import java.applet.Applet;
    import java.awt.event.*;
    public class Scroller extends Panel implements  ActionListener {
        private Button btOk;   
        private int width = 0;
        private int height = 0;   
        private DrawCanvas dc;   
        public Scroller(int width, int height){   
            this.width = width;
            this.height = height;   
            dc = new DrawCanvas(width, height);
            setNewsContents();                           
        private void setNewsContents() {
            setLayout(new BorderLayout());
            ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);       
            scroller.add(dc);
            Adjustable vadjust = scroller.getVAdjustable();
            Adjustable hadjust = scroller.getHAdjustable();
            hadjust.setUnitIncrement(10);
            vadjust.setUnitIncrement(10);
            scroller.setSize(615     , 272);
            btOk = new Button("ok");
            btOk.addActionListener(this);
            add("Center", scroller);
            add("South", btOk);       
        public void actionPerformed(ActionEvent event) {
            if(event.getSource()==btOk) {
                dc.enlarge(500,800);
                dc.validate();
    }    -------------- DrawCanvas.java -----------------------------------------------
    import java.awt.*;
    class DrawCanvas extends Component {
        private int width = 0;
        private int height = 0;
        private Dimension d;
        public DrawCanvas(int width, int height) {
            this.width = width;
            this.height = height;
       Dimension theSize = new Dimension(300, 200);   
       public Dimension getPreferredSize() {
            return new Dimension(width,height);               
       public void enlarge(int width, int height) {       
            theSize.width =  width;
            theSize.height = height;
            setSize(theSize);       
        public void update(Graphics g) {
            paint(g);
        public void paint(Graphics g) {       
            Rectangle r = getBounds();       
            String contents[] = {
            "addition to its usual stable of Clydesdale horses, the company will also enlist help this year ",
            "from racing star Dale Earnhardt Jr., some beer-thieving crabs and a scary hitchhiker.",       
            "The Super Bowl represents an enormous commitment for Budweiser. Bob Lachky, chief creative" ,
            "officer of Anheuser-Busch, said the St. Louis-based brewer has been advertising on the game since 1976 and has been the exclusive alcoholic beverage sponsor since 1989",
            "since 1976 and has been the exclusive alcoholic beverage sponsor since 1989, an arrangement that runs through 2012.",
            "It's important to us because it kicks off our selling season, it's the best platform",
            "possible to launch new ideas or to sustain existing campaigns, and it's absolutely the most efficient way to reach the most  it's absolutely the most efficient way to reach the most",
            "adult consumers in one sitting,",
            "Despite the rise of cable, the Internet other media to compete with broadcast television iewers and enticing a huge array of marketers ",
            ", the Super Bowl remains the most-viewed media event all year, drawing in some 90 million ",
            "viewers and enticing a huge array of marketers to pony up the big bucks for an ad",
            ", the price of which is running as high as $2.6 million for this year's broadcast",
            "on CBS Corp.'s CBS network, up slightly from about a top price of about $2.5 million last year.",
            "Comedian Carlos Mencia, of the Comedy Central show  gets ",
            "a big break with a spot set in a classroom. Lachky predicts that Mencia will get an enormous boost Lachky predicts that Mencia will get an enormous boost ",
            "following the appearance, which similarly did wonders for Cedric the Entertainer.",
            "And what would Budweiser Super Bowl ads be without some animated critters? This year, a ga",
            "ng of mischievous red crabs turn up on a beach to carry off a cooler full of beers. As in past years, Bud is keeping many ",
            g.setColor(new Color(226,250,255));
            g.fillRect(0, 0, r.width, r.height);
            g.setColor(new Color(233,231,224));            
            int line = 35;
            int line_1 = 39;
            for (int i = 0; i < contents.length; i++) {       
                 g.setColor(Color.BLACK);
                 g.drawString(contents, 5,line);
         g.setColor(new Color(233,231,224));
         g.drawLine(0,line_1,605,line_1);
         line += 20;
         line_1 += 20;

  • Resizing ScrollPane and Dimension

    I am currently making a scrollbar program using ScrollPane and Dimension. I have to use those classes.
    When I click "ok" button, that calls dc.enlarge(500,800) method. But it doesn't work.
    When it is clicked, Dimension object should be changed and the panel has to show Horizotal
    and Vertical scrollbar according to the width and height parameters.
    Of course, the size will be calculated by the String contents object's rows and width. But it does not work.
    How to resize the Dimension and How to display the Horizontal, Vertical scrollbar accoring to dc.enlarge's parameters?
    Plz... help me...
    -------------- ScrollerTest.java -----------------------------------------------
    import java.awt.*;
    import java.applet.Applet;
    public class ScrollerTest extends Applet {
       public Scroller sc = null;
        public void init() {
            sc = new Scroller(700,250);
            sc.setVisible(true);
         add(sc);         
    }-------------- Scroller.java -----------------------------------------------
    import java.awt.*;
    import java.awt.Window;
    import java.applet.Applet;
    import java.awt.event.*;
    public class Scroller extends Panel implements  ActionListener {
        private Button btOk;   
        private int width = 0;
        private int height = 0;   
        private DrawCanvas dc;   
        public Scroller(int width, int height){   
            this.width = width;
            this.height = height;   
            dc = new DrawCanvas(width, height);
            setNewsContents();                           
        private void setNewsContents() {
            setLayout(new BorderLayout());
            ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);       
            scroller.add(dc);
            Adjustable vadjust = scroller.getVAdjustable();
            Adjustable hadjust = scroller.getHAdjustable();
            hadjust.setUnitIncrement(10);
            vadjust.setUnitIncrement(10);
            scroller.setSize(615     , 272);
            btOk = new Button("ok");
            btOk.addActionListener(this);
            add("Center", scroller);
            add("South", btOk);       
        public void actionPerformed(ActionEvent event) {
            if(event.getSource()==btOk) {
                dc.enlarge(500,800);
                dc.validate();
    }    -------------- DrawCanvas.java -----------------------------------------------
    import java.awt.*;
    class DrawCanvas extends Component {
        private int width = 0;
        private int height = 0;
        private Dimension d;
        public DrawCanvas(int width, int height) {
            this.width = width;
            this.height = height;
       Dimension theSize = new Dimension(300, 200);   
       public Dimension getPreferredSize() {
            return new Dimension(width,height);               
       public void enlarge(int width, int height) {       
            theSize.width =  width;
            theSize.height = height;
            setSize(theSize);       
        public void update(Graphics g) {
            paint(g);
        public void paint(Graphics g) {       
            Rectangle r = getBounds();       
            String contents[] = {
            "addition to its usual stable of Clydesdale horses, the company will also enlist help this year ",
            "from racing star Dale Earnhardt Jr., some beer-thieving crabs and a scary hitchhiker.",       
            "The Super Bowl represents an enormous commitment for Budweiser. Bob Lachky, chief creative" ,
            "officer of Anheuser-Busch, said the St. Louis-based brewer has been advertising on the game since 1976 and has been the exclusive alcoholic beverage sponsor since 1989",
            "since 1976 and has been the exclusive alcoholic beverage sponsor since 1989, an arrangement that runs through 2012.",
            "It's important to us because it kicks off our selling season, it's the best platform",
            "possible to launch new ideas or to sustain existing campaigns, and it's absolutely the most efficient way to reach the most  it's absolutely the most efficient way to reach the most",
            "adult consumers in one sitting,",
            "Despite the rise of cable, the Internet other media to compete with broadcast television iewers and enticing a huge array of marketers ",
            ", the Super Bowl remains the most-viewed media event all year, drawing in some 90 million ",
            "viewers and enticing a huge array of marketers to pony up the big bucks for an ad",
            ", the price of which is running as high as $2.6 million for this year's broadcast",
            "on CBS Corp.'s CBS network, up slightly from about a top price of about $2.5 million last year.",
            "Comedian Carlos Mencia, of the Comedy Central show  gets ",
            "a big break with a spot set in a classroom. Lachky predicts that Mencia will get an enormous boost Lachky predicts that Mencia will get an enormous boost ",
            "following the appearance, which similarly did wonders for Cedric the Entertainer.",
            "And what would Budweiser Super Bowl ads be without some animated critters? This year, a ga",
            "ng of mischievous red crabs turn up on a beach to carry off a cooler full of beers. As in past years, Bud is keeping many ",
            g.setColor(new Color(226,250,255));
            g.fillRect(0, 0, r.width, r.height);
            g.setColor(new Color(233,231,224));            
            int line = 35;
            int line_1 = 39;
            for (int i = 0; i < contents.length; i++) {       
                 g.setColor(Color.BLACK);
                 g.drawString(contents, 5,line);
         g.setColor(new Color(233,231,224));
         g.drawLine(0,line_1,605,line_1);
         line += 20;
         line_1 += 20;

    The class names have been changed so you can run this as-is without name-clashing.
    //  <applet code="ST" width="720" height="300"></applet>
    import java.awt.*;
    import java.awt.event.*;
    import java.applet.Applet;
    public class ST extends Applet {
        public ScrollerRx sc;
        public void init() {
            sc = new ScrollerRx(700,250);
            add(sc);
    class ScrollerRx extends Panel implements ActionListener {
        private Button btOk;
        private DrawCanvasRx dc;
        public ScrollerRx(int width, int height) {
            dc = new DrawCanvasRx(width, height);
            setNewsContents();
        private void setNewsContents() {
            setLayout(new BorderLayout());
            ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
            scroller.add(dc);
            Adjustable vadjust = scroller.getVAdjustable();
            Adjustable hadjust = scroller.getHAdjustable();
            hadjust.setUnitIncrement(10);
            vadjust.setUnitIncrement(10);
            scroller.setSize(615, 272);
            btOk = new Button("ok");
            btOk.addActionListener(this);
            add("Center", scroller);
            add("South", btOk);
        public void actionPerformed(ActionEvent event) {
            if(event.getSource()==btOk) {
                dc.enlarge(500,800);
                // validate is a Container method.
                validate();
    class DrawCanvasRx extends Component {
        Dimension theSize = new Dimension(300, 200);
        String[] contents = {
            "addition to its usual stable of Clydesdale horses, the company will " +
            "also enlist help this year ",
            "from racing star Dale Earnhardt Jr., some beer-thieving crabs and a " +
            "scary hitchhiker.",       
            "The Super Bowl represents an enormous commitment for Budweiser. Bob " +
            "Lachky, chief creative" ,
            "officer of Anheuser-Busch, said the St. Louis-based brewer has been " +
            "advertising on the game since 1976 and has been the exclusive alcoholic " +
            "beverage sponsor since 1989",
            "since 1976 and has been the exclusive alcoholic beverage sponsor since " +
            "1989, an arrangement that runs through 2012.",
            "It's important to us because it kicks off our selling season, it's the " +
            "best platform",
            "possible to launch new ideas or to sustain existing campaigns, and it's " +
            "absolutely the most efficient way to reach the most  it's absolutely " +
            "the most efficient way to reach the most",
            "adult consumers in one sitting,",
            "Despite the rise of cable, the Internet other media to compete with " +
            "broadcast television iewers and enticing a huge array of marketers ",
            ", the Super Bowl remains the most-viewed media event all year, drawing " +
            "in some 90 million ",
            "viewers and enticing a huge array of marketers to pony up the big bucks " +
            "for an ad",
            ", the price of which is running as high as $2.6 million for this year's " +
            "broadcast",
            "on CBS Corp.'s CBS network, up slightly from about a top price of about " +
            "$2.5 million last year.",
            "Comedian Carlos Mencia, of the Comedy Central show  gets ",
            "a big break with a spot set in a classroom. Lachky predicts that Mencia " +
            "will get an enormous boost Lachky predicts that Mencia will get an " +
            "enormous boost ",
            "following the appearance, which similarly did wonders for Cedric the " +
            "Entertainer.",
            "And what would Budweiser Super Bowl ads be without some animated " +
            "critters? This year, a ga",
            "ng of mischievous red crabs turn up on a beach to carry off a cooler " +
            "full of beers. As in past years, Bud is keeping many ",
        public DrawCanvasRx(int width, int height) {
            theSize.setSize(width, height);
        public Dimension getPreferredSize() {
            System.out.printf("theSize = [%d, %d]%n", theSize.width, theSize.height);
            return theSize;
        public void enlarge(int width, int height) {
            theSize.width  = width;
            theSize.height = height;
            // Mark this component as needing a new layout.
            invalidate();
        public void update(Graphics g) {
            paint(g);
        public void paint(Graphics g) {
            Rectangle r = getBounds();
            g.setColor(new Color(226,250,255));
            g.fillRect(0, 0, r.width, r.height);
            g.setColor(new Color(233,231,224));
            int line = 35;
            int line_1 = 39;
            for (int i = 0; i < contents.length; i++) {
                g.setColor(Color.BLACK);
                 g.drawString(contents, 5, line);
         g.setColor(new Color(233,231,224));
         g.drawLine(0, line_1, 605, line_1);
         line += 20;
         line_1 += 20;

  • Scrollpane Image Resize?

    When you load an image into the scrollpane via the
    contentPath it displays the image full size, ie if the image is
    larger than the scrollpane window you get scroll bars so that you
    can view the complete image.
    Is there a way to resize the image so that it fits into the
    current scrollpane window?

    One thing that I have discovered is that the scrollpane
    apparently does not resize when new content is loaded into it. It
    scales to accept the first data that is loaded into it and then
    doesn't check again. Since you need to load the content before you
    scale it, this presents a problem because the scroll bars will
    scale to the original content size and not the altered size.
    So you should use a holder mc as your default content ,sized
    to fit the desired scrollpane, then load your final image into that
    holder and finally scale your image.
    Hope that helps.
    M

  • Automatic Resizing of panel with drawings added to a scrollPane

    I have a Panel with rectangles text and arcs drawn .and it is added to a scrollPane.both vertical and Horizontal scrollbars are enabled for scrollPane.My problem is that i have to draw arcs connecting these rectangles with text enclosed in it. and when i connect two rectangles a span is formed connecting the two..and as hierarchy goes deeper ie connecting spans of already linked rectangles with similar spans..There wont be enough space at top for arc to be drawn..So ive to either readjust all objects related with drawings in panel or is there any other way to increase panel size automatically as drawings need more space..Please suggest me some method for this problem

    Panels Preffered size is set as (3000,1000) and TextRectangles are drawn in panel Cordinates of textRectangle are set in setTextRectangle method and all further drawings connecting rectangle are done by mouse clicks on specific rectangles.
    and layout in setTextRectangle is TextLayout of the text enclosed in rectangles.So when i coordinates for arc drawn exceeds the panel should i call separate method for resetting panel size is that what you have suggested
       screen_Resolution = Toolkit.getDefaultToolkit().
                               getScreenResolution();
             screen_Width = Toolkit.getDefaultToolkit().
                               getScreenSize().width;
             screen_Height = Toolkit.getDefaultToolkit().
                              getScreenSize().height;
    public void setTextRectangle(Graphics g, Font font)
              Graphics2D g2 = (Graphics2D) g;
             FontMetrics metrics= g.getFontMetrics (font);
            int textHeight = metrics.getHeight();
            int left=textHeight;
            int yCordRectangle=(int)(screen_Height/5);
            for (int i = 0; i < layouts.size (); i++) {
                 int top=(int)(screen_Resolution*2);
                 for (int j = 0; j < layouts.get (i).size (); j++) {
                     top += textHeight;
        TextRectangle textRectangle=new TextRectangle(left,yCordRectangle,wrapWidth,top-150);
         addtoarray( textRectangle, rectangles);
        left += wrapWidth + textHeight;
       

  • Custom graphics in java.awt.ScrollPane

    Hi all,
    I have to draw a custom created image in a scroll pane. As the image is very large I want to display it in a scroll pane. As parts of the image may change within seconds, and drawing the whole image is very time consuming (several seconds) I want to draw only the part of the image that is currently visible to the user.
    My idea: creating a new class that extends from java.awt.ScrollPane, overwrite the paint(Graphics) method and do the drawings inside. Unfortunately, it does not work. The background of the scoll pane is blue, but it does not show the red box (the current viewport is not shown in red).
    Below please find the source code that I am using:
    package graphics;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.ScrollPane;
    import java.awt.event.AdjustmentEvent;
    public class CMyComponent extends ScrollPane {
         /** <p>Listener to force a component to repaint when a scroll bar changes its
          * position.</p>
         private final class ScrollBarAdjustmentListener implements java.awt.event.AdjustmentListener {
              /** <p>The component to force to repaint.</p> */
              private final Component m_Target;
              /** <p>Default constructor.</p>
               * @param Target The component to force to repaint.
              private ScrollBarAdjustmentListener(Component Target) { m_Target = Target; }
              /** <p>Forces to component to repaint upon adjustment of the scroll bar.</p>
               *  @see java.awt.event.AdjustmentListener#adjustmentValueChanged(java.awt.event.AdjustmentEvent)
              public void adjustmentValueChanged(AdjustmentEvent e) { m_Target.paint(m_Target.getGraphics()); }
         public CMyComponent() {
              // Ensure that the component repaints upon changing of the scroll bars
              ScrollBarAdjustmentListener sbal = new ScrollBarAdjustmentListener(this);
              getHAdjustable().addAdjustmentListener(sbal);
              getVAdjustable().addAdjustmentListener(sbal);
         public void paint(Graphics g) {
              setBackground(Color.BLUE);
              g.setColor(Color.RED);
              g.fillRect(getScrollPosition().x, getScrollPosition().y, getViewportSize().width, getViewportSize().height);
         public final static void main(String[] args) {
              java.awt.Frame f = new java.awt.Frame();
              f.add(new CMyComponent());
              f.pack();
              f.setVisible(true);
    }

    Dear all,
    I used the last days and tried several things. I think now I have a quite good working solution (just one bug remains) and it is very performant. To give others a chance to see what I have done I post the source code of the main class (a canvas drawing and implementing scrolling) here. As soon as the sourceforge project is accepted, I will publish the whole sources at there. Enjoy. And if you have some idea for my last bug in getElementAtPixel(Point), then please tell me.
    package internetrail.graphics.hexgrid;
    import java.awt.Canvas;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.Point;
    import java.awt.Polygon;
    import java.awt.event.ComponentEvent;
    import java.awt.event.ComponentListener;
    import java.awt.geom.Area;
    import java.awt.image.BufferedImage;
    import java.util.WeakHashMap;
    import java.util.Map;
    /** <p>Hex grid view.</p>
    * <p>Visualizes a {@link IHexGridModel}.</p>
    * @version 0.1, 03.06.2006
    * @author Bjoern Wuest, Germany
    public final class CHexGridView extends Canvas implements ComponentListener, IHexGridElementListener {
         /** <p>Serial version unique identifier.</p> */
         private static final long serialVersionUID = -965902826101261530L;
         /** <p>Instance-constant parameter for the width of a hex grid element.</p> */
         public final int CONST_Width;
         /** <p>Instance-constant parameter for 1/4 of the width of a hex grid element.</p> */
         public final int CONST_Width1fourth;
         /** <p>Instance-constant parameter for 3/4 of the width of a hex grid element.</p> */
         public final int CONST_Width3fourth;
         /** <p>Instance-constant parameter for 1.5 times of the width of a hex grid element.</p> */
         public final int CONST_Width1dot5;
         /** <p>Instance-constant parameter for 4 times of the width of a hex grid element.</p> */
         public final int CONST_Widthquad;
         /** <p>Instance-constant parameter for the height of a hex grid element.</p> */
         public final int CONST_Height;
         /** <p>Instance-constant parameter for 1/2 of the height of a hex grid element.</p> */
         public final int CONST_Heighthalf;
         /** <p>Instance-constant parameter for the double height of a hex grid element.</p> */
         public final int CONST_Heightdouble;
         /** <p>The steepness of a side of the hex grid element (calculated for the upper left arc).</p> */
         public final double CONST_Steepness;
         /** <p>The model of this hex grid </p> */
         private final IHexGridModel m_Model;
         /** <p>A cache for already created images of the hex map.</p> */
         private final Map<Point, Image> m_Cache = new WeakHashMap<Point, Image>();
         /** <p>The graphical area to draw the selection ring around a hex element.</p> */
         private final Area m_SelectionRing;
         /** <p>The image of the selection ring around a hex element.</p> */
         private final BufferedImage m_SelectionRingImage;
         /** <p>The current position of the hex grid in pixels (top left visible corner).</p> */
         private Point m_ScrollPosition = new Point(0, 0);
         /** <p>Flag to define if a grid is shown ({@code true}) or not ({@code false}).</p> */
         private boolean m_ShowGrid = true;
         /** <p>Flag to define if the selected hex grid element should be highlighted ({@code true}) or not ({@code false}).</p> */
         private boolean m_ShowSelected = true;
         /** <p>The offset of hex grid elements shown on the screen, measured in hex grid elements.</p> */
         private Point m_CurrentOffset = new Point(0, 0);
         /** <p>The offset of the image shown on the screen, measured in pixels.</p> */
         private Point m_PixelOffset = new Point(0, 0);
         /** <p>The index of the currently selected hex grid element.</p> */
         private Point m_CurrentSelected = new Point(0, 0);
         /** <p>The width of a buffered pre-calculated image in pixel.</p> */
         private int m_ImageWidth;
         /** <p>The height of a buffered pre-calculated image in pixel.</p> */
         private int m_ImageHeight;
         /** <p>The maximum number of columns of hex grid elements to be shown at once on the screen.</p> */
         private int m_MaxColumn;
         /** <p>The maximum number of rows of hex grid elements to be shown at once on the screen.</p> */
         private int m_MaxRow;
         /** <p>Create a new hex grid view.</p>
          * <p>The hex grid view is bound to a {@link IHexGridModel} and registers at
          * that model to listen for {@link IHexGridElement} updates.</p>
          * @param Model The model backing this view.
         public CHexGridView(IHexGridModel Model) {
              // Set the model
              m_Model = Model;
              CONST_Width = m_Model.getElementsWidth();
              CONST_Height = m_Model.getElementsHeight();
              CONST_Width1fourth = CONST_Width/4;
              CONST_Width3fourth = CONST_Width*3/4;
              CONST_Width1dot5 = CONST_Width*3/2;
              CONST_Heighthalf = CONST_Height/2;
              CONST_Widthquad = CONST_Width*4;
              CONST_Heightdouble = CONST_Height*2;
              CONST_Steepness = (double)CONST_Heighthalf / CONST_Width1fourth;
              m_ImageWidth = getSize().width+CONST_Widthquad;
              m_ImageHeight = getSize().height+CONST_Heightdouble;
              m_MaxColumn = m_ImageWidth / CONST_Width3fourth;
              m_MaxRow = m_ImageHeight / CONST_Height;
              // Register this canvas for various notifications
              m_Model.addElementListener(this);
              addComponentListener(this);
              // Create the selection ring to highlight hex grid elements
              m_SelectionRing = new Area(new Polygon(new int[]{-1, CONST_Width1fourth-1, CONST_Width3fourth+1, CONST_Width+1, CONST_Width3fourth+1, CONST_Width1fourth-1}, new int[]{CONST_Heighthalf, -1, -1, CONST_Heighthalf, CONST_Height+1, CONST_Height+1}, 6));
              m_SelectionRing.subtract(new Area(new Polygon(new int[]{2, CONST_Width1fourth+2, CONST_Width3fourth-2, CONST_Width-2, CONST_Width3fourth-2, CONST_Width1fourth+2}, new int[]{CONST_Heighthalf, 2, 2, CONST_Heighthalf, CONST_Height-2, CONST_Height-2}, 6)));
              m_SelectionRingImage = new BufferedImage(CONST_Width, CONST_Height, BufferedImage.TYPE_INT_ARGB);
              Graphics2D g = m_SelectionRingImage.createGraphics();
              g.setColor(Color.WHITE);
              g.fill(m_SelectionRing);
         @Override public synchronized void paint(Graphics g2) {
              // Caculate the offset of indexes to show
              int offsetX = 2 * (m_ScrollPosition.x / CONST_Width1dot5) - 2;
              int offsetY = (int)(Math.ceil(m_ScrollPosition.y / CONST_Height) - 1);
              m_CurrentOffset = new Point(offsetX, offsetY);
              // Check if the image is in the cache
              Image drawing = m_Cache.get(m_CurrentOffset);
              if (drawing == null) {
                   // The image is not cached, so draw it
                   drawing = new BufferedImage(m_ImageWidth, m_ImageHeight, BufferedImage.TYPE_INT_ARGB);
                   Graphics2D g = ((BufferedImage)drawing).createGraphics();
                   // Draw background
                   g.setColor(Color.BLACK);
                   g.fillRect(0, 0, m_ImageWidth, m_ImageHeight);
                   // Draw the hex grid
                   for (int column = 0; column <= m_MaxColumn; column += 2) {
                        for (int row = 0; row <= m_MaxRow; row++) {
                             // Draw even column
                             IHexGridElement element = m_Model.getElementAt(offsetX + column, offsetY + row);
                             if (element != null) { g.drawImage(element.getImage(m_ShowGrid), (int)(column*(CONST_Width3fourth-0.5)), CONST_Height*row, null); }
                             // Draw odd column
                             element = m_Model.getElementAt(offsetX + column+1, offsetY + row);
                             if (element!= null) { g.drawImage(element.getImage(m_ShowGrid), (int)(column*(CONST_Width3fourth-0.5)+CONST_Width3fourth), CONST_Heighthalf*(row*2+1), null); }
                   // Put the image into the cache
                   m_Cache.put(m_CurrentOffset, drawing);
              // Calculate the position of the image to show
              offsetX = CONST_Width1dot5 + (m_ScrollPosition.x % CONST_Width1dot5);
              offsetY = CONST_Height + (m_ScrollPosition.y % CONST_Height);
              m_PixelOffset = new Point(offsetX, offsetY);
              g2.drawImage(drawing, -offsetX, -offsetY, null);
              // If the selected element should he highlighted, then do so
              if (m_ShowSelected) {
                   // Check if the selected element is on screen
                   if (isElementOnScreen(m_CurrentSelected)) {
                        // Correct vertical offset for odd columns
                        if ((m_CurrentSelected.x % 2 == 1)) { offsetY -= CONST_Heighthalf; }
                        // Draw the selection circle
                        g2.drawImage(m_SelectionRingImage, (m_CurrentSelected.x - m_CurrentOffset.x) * CONST_Width3fourth - offsetX - ((m_CurrentSelected.x + 1) / 2), (m_CurrentSelected.y - m_CurrentOffset.y) * CONST_Height - offsetY, null);
         @Override public synchronized void update(Graphics g) { paint(g); }
         public synchronized void componentResized(ComponentEvent e) {
              // Upon resizing of the component, adjust several pre-calculated values
              m_ImageWidth = getSize().width+CONST_Widthquad;
              m_ImageHeight = getSize().height+CONST_Heightdouble;
              m_MaxColumn = m_ImageWidth / CONST_Width3fourth;
              m_MaxRow = m_ImageHeight / CONST_Height;
              // And flush the cache
              m_Cache.clear();
         public void componentMoved(ComponentEvent e) { /* do nothing */ }
         public void componentShown(ComponentEvent e) { /* do nothing */ }
         public void componentHidden(ComponentEvent e) { /* do nothing */ }
         public synchronized void elementUpdated(IHexGridElement Element) {
              // Clear cache where the element may be contained at
              for (Point p : m_Cache.keySet()) { if (isElementInScope(Element.getIndex(), p, new Point(p.x + m_MaxColumn, p.y + m_MaxRow))) { m_Cache.remove(p); } }
              // Update the currently shown image if the update element is shown, too
              if (isElementOnScreen(Element.getIndex())) { repaint(); }
         /** <p>Returns the model visualized by this grid view.</p>
          * @return The model visualized by this grid view.
         public IHexGridModel getModel() { return m_Model; }
         /** <p>Returns the current selected hex grid element.</p>
          * @return The current selected hex grid element.
         public IHexGridElement getSelected() { return m_Model.getElementAt(m_CurrentSelected.x, m_CurrentSelected.y); }
         /** <p>Sets the current selected hex grid element by its index.</p>
          * <p>If the selected hex grid element should be highlighted and is currently
          * shown on the screen, then this method will {@link #repaint() redraw} this
          * component automatically.</p>
          * @param Index The index of the hex grid element to become the selected one.
          * @throws IllegalArgumentException If the index refers to a non-existing hex
          * grid element.
         public synchronized void setSelected(Point Index) throws IllegalArgumentException {
              // Check that the index is valid
              if ((Index.x < 0) || (Index.y < 0) || (Index.x > m_Model.getXElements()) || (Index.y > m_Model.getYElements())) { throw new IllegalArgumentException("There is no hex grid element with such index."); }
              m_CurrentSelected = Index;
              // If the element is on screen and should be highlighted, then repaint
              if (m_ShowSelected && isElementOnScreen(m_CurrentSelected)) { repaint(); }
         /** <p>Moves the visible elements to the left by the number of pixels.</p>
          * <p>To move the visible elements to the left by one hex grid element, pass
          * {@link #CONST_Width3fourth} as the parameter. The component will
          * automatically {@link #repaint()}.</p>
          * @param Pixels The number of pixels to move to the left.
          * @return The number of pixels moved to the left. This is always between 0
          * and {@code abs(Pixels)}.
         public synchronized int moveLeft(int Pixels) {
              int delta = m_ScrollPosition.x - Math.max(0, m_ScrollPosition.x - Math.max(0, Pixels));
              if (delta != 0) {
                   m_ScrollPosition.x -= delta;
                   repaint();
              return delta;
         /** <p>Moves the visible elements up by the number of pixels.</p>
          * <p>To move the visible elements up by one hex grid element, pass {@link
          * #CONST_Height} as the parameter. The component will automatically {@link
          * #repaint()}.</p>
          * @param Pixels The number of pixels to move up.
          * @return The number of pixels moved up. This is always between 0 and {@code
          * abs(Pixels)}.
         public synchronized int moveUp(int Pixels) {
              int delta = m_ScrollPosition.y - Math.max(0, m_ScrollPosition.y - Math.max(0, Pixels));
              if (delta != 0) {
                   m_ScrollPosition.y -= delta;
                   repaint();
              return delta;
         /** <p>Moves the visible elements to the right by the number of pixels.</p>
          * <p>To move the visible elements to the right by one hex grid element, pass
          * {@link #CONST_Width3fourth} as the parameter. The component will
          * automatically {@link #repaint()}.</p>
          * @param Pixels The number of pixels to move to the right.
          * @return The number of pixels moved to the right. This is always between 0
          * and {@code abs(Pixels)}.
         public synchronized int moveRight(int Pixels) {
              int delta = Math.min(m_Model.getXElements() * CONST_Width3fourth + CONST_Width1fourth - getSize().width, m_ScrollPosition.x + Math.max(0, Pixels)) - m_ScrollPosition.x;
              if (delta != 0) {
                   m_ScrollPosition.x += delta;
                   repaint();
              return delta;
         /** <p>Moves the visible elements down by the number of pixels.</p>
          * <p>To move the visible elements down by one hex grid element, pass {@link
          * #CONST_Height} as the parameter. The component will automatically {@link
          * #repaint()}.</p>
          * @param Pixels The number of pixels to move down.
          * @return The number of pixels moved down. This is always between 0 and
          * {@code abs(Pixels)}.
         public synchronized int moveDown(int Pixels) {
              int delta = Math.min(m_Model.getYElements() * CONST_Height + CONST_Heighthalf - getSize().height, m_ScrollPosition.y + Math.max(0, Pixels)) - m_ScrollPosition.y;
              if (delta != 0) {
                   m_ScrollPosition.y += delta;
                   repaint();
              return delta;
         /** <p>Checks if the hex grid element of the given index is currently
          * displayed on the screen (even just one pixel).</p>
          * <p>The intention of this method is to check if a {@link #repaint()} is
          * necessary or not.</p>
          * @param ElementIndex The index of the element to check.
          * @return {@code true} if the hex grid element of the given index is
          * displayed on the screen, {@code false} if not.
         public synchronized boolean isElementOnScreen(Point ElementIndex) { return isElementInScope(ElementIndex, m_CurrentOffset, new Point(m_CurrentOffset.x + m_MaxColumn, m_CurrentOffset.y + m_MaxRow)); }
         /** <p>Checks if the hex grid element of the given index is within the given
          * indexes.</p>
          * <p>The intention of this method is to check if a {@link #repaint()} is
          * necessary or not.</p>
          * @param ElementIndex The index of the element to check.
          * @param ReferenceIndexLeftTop The left top index of the area to check.
          * @param ReferenceIndexRightBottom The right bottom index of the area to check.
          * @return {@code true} if the hex grid element of the given index is within
          * the given area, {@code false} if not.
         public synchronized boolean isElementInScope(Point ElementIndex, Point ReferenceIndexLeftTop, Point ReferenceIndexRightBottom) { if ((ElementIndex.x >= ReferenceIndexLeftTop.x) && (ElementIndex.x <= ReferenceIndexRightBottom.x) && (ElementIndex.y >= ReferenceIndexLeftTop.y) && (ElementIndex.y <= (ReferenceIndexRightBottom.y))) { return true; } else { return false; } }
         /** <p>Return the {@link IHexGridElement hex grid element} shown at the given
          * pixel on the screen.</p>
          * <p><b>Remark: There seems to be a bug in retrieving the proper element,
          * propably caused by rounding errors and unprecise pixel calculations.</p>
          * @param P The pixel on the screen.
          * @return The {@link IHexGridElement hex grid element} shown at the pixel.
         public synchronized IHexGridElement getElementAtPixel(Point P) {
              // @FIXME Here seems to be some bugs remaining
              int dummy = 0; // Variable for warning to indicate that there is something to do :)
              // Calculate the pixel on the image, not on the screen
              int px = P.x + m_PixelOffset.x;
              int py = P.y + m_PixelOffset.y;
              // Determine the x-index of the column (is maybe decreased by one)
              int x = px / CONST_Width3fourth + m_CurrentOffset.x;
              // If the column is odd, then shift the y-pixel by half element height
              if ((x % 2) == 1) { py -= CONST_Heighthalf; }
              // Determine the y-index of the row (is maybe decreased by one)
              int y = py / CONST_Height + m_CurrentOffset.y;
              // Normative coordinates to a single element
              px -= (x - m_CurrentOffset.x) * CONST_Width3fourth;
              py -= (y - m_CurrentOffset.y) * CONST_Height;
              // Check if the normative pixel is in the first quarter of a column
              if (px < CONST_Width1fourth) {
                   // Adjustments to the index may be necessary
                   if (py < CONST_Heighthalf) {
                        // We are in the upper half of a hex-element
                        double ty = CONST_Heighthalf - CONST_Steepness * px;
                        if (py < ty) { x--; }
                   } else {
                        // We are in the lower half of a hex-element
                        double ty = CONST_Heighthalf + CONST_Steepness * px;
                        if (py > ty) {
                             x--;
                             y++;
              return m_Model.getElementAt(x, y);
    }Ah, just to give you some idea: I use this component to visualize a hex grid map with more than 1 million grid elements. And it works, really fast, and requires less than 10 MByte of memory.

  • Problem with drawing in a scrollpane using clipbounds

    Hello
    Setup is a JFrame containing a splitpane with on the left just some config buttons and on the right a scrollpane.
    Inside the scrollpane I want to draw big waveforms.
    This is represented by a long array of 1's and 0's for the Y coordinates.
    On drawing in paintComponents method I allways reconstruct a GeneralPath, based on the Clipbouns returned by the Graphics variable.
    I have to reconstruct the GeneralPath polygon because my data can be millions long. And therefor I have to limit the points that are drawn.
    When I allways reconstruct this GeneralPath, upon scrolling the polygon is shown scrappy, as in the line connecting the points will only be half shown or almost not.
    Resizing the window or just minimize maximize and it is shown ok.
    I do not have this problem when the GeneralPath I construct is only once made upfront and never remade in the paintComponent method.
    But as I need the clipbounds to know which part to construct I need to rebuild this polygon over and over again.
    I have tried to draw it with Line2D.Double but I get almost the same effect, parts of the lines not being drawn ok.
    Below is the code of the Panel inside the ScrollPane responsible for this drawing.
    public class Usr_Test_L extends JPanel
      final static Color bg   = Color.black;
      final static Color fg   = Color.white;
      final static Color wave = Color.red;
      final static Color txt  = Color.green;
      final static Color grid = Color.lightGray;
      private static final BasicStroke SOLID = new BasicStroke(1.0f);
      private static final BasicStroke BOLD  = new BasicStroke(3.0f);
      private double maxX = 0.0;
      private double maxY = 0.0;
      private double gridWidth;
      private double gridHeight;
      private int panelWidth;
      private int panelHeight;
      boolean firstTime = true;
      private double[] xPoints = null;
      private double[] yPoints = null;
      GeneralPath polygon;
      boolean polyOk = false;
      private double waveHeight = 0;
      private boolean gridOn = true;
      private Usr_Test_R scrollPane = null;
      Usr_Test_L(Usr_Test_R scrollPane)
        super(true);
        this.scrollPane = scrollPane;
        buildGui();
      void buildGui()
        setBackground(bg);
        setForeground(fg);
        //Let the user scroll by dragging to outside the window.
        setAutoscrolls(true); //enable synthetic drag events
    //    addMouseMotionListener(this); //handle mouse drags
        repaint();
      private void generateWave(int cycles, double height)
        waveHeight = height;
        xPoints = new double[cycles];
        yPoints = new double[cycles];
        Random r = new Random();
        for ( int i = 0; i < cycles; i++ )
          xPoints[i] = i;
          yPoints[i] = (int)( Math.pow(-1.0,i) ) * ( r.nextInt(2) );
    //      if ( ( i % 10 ) == 0 ) yPoints[i] = height;
    //      else                   yPoints[i] = height + gridHeight;
    //      System.err.println("P"+i+"("+xPoints[i]+","+yPoints[i]+")");
      private void generateSineWave(int cycles, double height)
        waveHeight = height;
        xPoints = new double[cycles];
        yPoints = new double[cycles];
        double j, xval, yval;
        j = 0;
        int i = 0;
        while (i < cycles)
          xval = j;
          yval = Math.sin(j) * 10.0 + 20;
          xPoints[i] = xval;
          yPoints[i] = yval;
          i++;
          j += 0.01;
      public Dimension getPreferredSize()  // <== used because of revalidate, parent scrollpane asks preferredsize ..., so we overruled the method
        return new Dimension(panelWidth, panelHeight);
      public void drawLine(int cycles, int height)
        generateWave(cycles,(int)(gridHeight*height));
        maxX = gridWidth  * cycles;
        maxY = gridHeight * cycles;
        while ( maxX > panelWidth  ) panelWidth  *= 2;
        while ( maxY > panelHeight ) panelHeight *= 2;
    //    polyOk = buildPolygon();
        revalidate();
        repaint();
      public void drawSine(int cycles, int height)
        generateSineWave(cycles,(int)(gridHeight*height));
        maxX = gridWidth  * cycles;
        maxY = gridHeight * cycles;
        while ( maxX > panelWidth  ) panelWidth  *= 2;
        while ( maxY > panelHeight ) panelHeight *= 2;
    //    polyOk = buildPolygon();
        revalidate();
        repaint();
      public void zoomIn()
        gridWidth  *= 2;
        gridHeight *= 2;
        repaint();
      public void zoomOut()
        gridWidth  /= 2;
        gridHeight /= 2;
        repaint();
      private void initPanel()
        Dimension d = getSize();
        panelWidth = d.width;
        panelHeight = d.height;
        maxX = panelWidth;
        maxY = panelHeight;
        gridWidth  = panelWidth / 8;
        gridHeight = panelHeight / 8;
        scrollPane.getHorBar().setUnitIncrement((int)(gridWidth*3));           // times 2 otherwise no clipbounds are allways too small
        scrollPane.getHorBar().setBlockIncrement((int)(gridWidth*3));
        scrollPane.getVerBar().setUnitIncrement((int)(gridHeight*3));
        scrollPane.getVerBar().setBlockIncrement((int)(gridHeight*3));
      public void grid()
        if ( gridOn ) gridOn = false;
        else          gridOn = true;
      private void drawGrid(Graphics2D g2, Rectangle clip)
        if ( ! gridOn ) return;
        // draw grid
        g2.setPaint(grid);
        // new good grid
        double startX = clip.getX() + ( gridWidth - ( clip.getX() % gridWidth ) );
        double endX   = clip.getX() + clip.getWidth();
        double startY = clip.getY() + ( gridHeight - ( clip.getY() % gridHeight ) );
        double endY   = clip.getY() + clip.getHeight();
        double y = startY;
        while ( startX < endX )
          while ( y < endY )
            g2.draw(new Rectangle2D.Double( startX - 0.5, y - 0.5, 1.0, 1.0 ));
            y += gridHeight;
          y = startY;
          startX += gridWidth;
      private boolean buildPolygon(Rectangle clip)
        if ( xPoints != null && yPoints != null )
          polygon = new GeneralPath(GeneralPath.WIND_NON_ZERO,xPoints.length);
        else
          return false;
        double x = xPoints[0] * gridWidth;
        double y = waveHeight;
        polygon.moveTo((float)xPoints[0], (float)yPoints[0]);
        for ( int index = 0; index < xPoints.length; index++ )
          x = xPoints[index] * gridWidth;
          y = waveHeight + ( yPoints[index] * gridHeight );
          if ( x > ( clip.getX() + clip.getWidth() ) ) break;
          if ( y < clip.getY() || y > ( clip.getY() + clip.getHeight() ) ) continue;
          if ( x < clip.getX() || x > ( clip.getX() + clip.getWidth()  ) ) continue;
          polygon.lineTo((float)x, (float)y);
        return true;
      private boolean drawLines(Graphics2D g2, Rectangle clip)
        if ( xPoints == null || yPoints == null ) return false;
        double x1 = xPoints[0] * gridWidth;
        double y1 = waveHeight;
        double x2, y2;
        boolean cont = false;
        for ( int index = 0; index < xPoints.length; index++ )
          x2 = xPoints[index] * gridWidth;
          y2 = waveHeight + ( yPoints[index] * gridHeight );
          if ( x1 > ( clip.getX() + clip.getWidth() ) )
            break;
          if ( x2 > ( clip.getX() + clip.getWidth() ) )
            break;
          if ( y2 < clip.getY() || y2 > ( clip.getY() + clip.getHeight() ) )
            cont = true;
          if ( x2 < clip.getX() || x2 > ( clip.getX() + clip.getWidth()  ) )
            cont = true;
          if ( ! cont ) g2.draw(new Line2D.Double(x1,y1,x2,y2));
          x1 = x2;
          y1 = y2;
          cont = false;
        return true;
      public void paintComponent(Graphics g)
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        if ( firstTime )
          initPanel();
          firstTime = false;
        // get clip bounds
        Rectangle clip = new Rectangle();
        clip = g2.getClipBounds(clip);
        // draw grid
        drawGrid(g2,clip);
        // draw waveform
        g2.setPaint(wave);
        g2.setStroke(SOLID);
        if ( buildPolygon(clip) ) g2.draw(polygon);
    //    if ( polyOk ) g2.draw(polygon);
    //    drawLines(g2,clip);
      }

    I have added a standalone testcase for ease.
    import java.awt.*;
    import java.awt.geom.*;
    import javax.swing.*;
    import java.util.*;
    public class Scrolling {
        public static void main(String[] args) {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(new JScrollPane(new DrawPanel()));
            f.setSize(400,300);
            f.setLocationRelativeTo(null);
            f.setVisible(true);
    class DrawPanel extends JPanel {
        private GeneralPath polygon = new GeneralPath(GeneralPath.WIND_NON_ZERO,1000);
        private int[] coords;
        public DrawPanel() {
            setBackground(Color.white);
            buildPolygon();
        private void buildPolygon() {
         coords = new int[2000];
            Random r = new Random();
            int height = 80;
            int gridHeight = 10;
            int gridWidth = 10;
         int j = 0;       
            for (int i=0, dir=-1; i<1000; i++, dir=-dir) {
                coords[j++] = i * gridWidth;
                coords[j++] = height + dir*gridHeight*r.nextInt(2);
        private void drawPolygonClipped(Rectangle clip)
    polygon = new GeneralPath(GeneralPath.WIND_NON_ZERO,1000);
           polygon.moveTo(0,80);
           for ( int i = 0; i < 2000; i++ )
          if ( coords[i] > ( clip.getX() + clip.getWidth() ) ) break;
          if ( coords[i+1] < clip.getY() || coords[i+1] > ( clip.getY() + clip.getHeight() ) ) continue;
          if ( coords[i] < clip.getX() || coords[i] > ( clip.getX() + clip.getWidth()  ) ) continue;
                polygon.lineTo(coords[i++],coords);
    private void drawPolygon(Rectangle clip)
    polygon = new GeneralPath(GeneralPath.WIND_NON_ZERO,1000);
         polygon.moveTo(0,80);
         for ( int i = 0; i < 2000; i++ )
              polygon.lineTo(coords[i++],coords[i]);
    protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;
         Rectangle clip = new Rectangle();
         g.getClipBounds(clip);
         drawPolygonClipped(clip);
         //drawPolygon(clip);
    g2.draw(polygon);
    public Dimension getPreferredSize() {
    return new Dimension(1500,500);

  • How to resize a custom tree node like you would a JFrame window?

    Hello,
    I am trying to resize a custom tree node like you would a JFrame window.
    As with a JFrame, when your mouse crosses the Border, the cursor should change and you are able to drag the edge to resize the node.
    However, I am faced with a problem. Border cannot detect this and I dont want to use a mouse motion listener (with a large number of nodes, I fear it will be inefficient, calculating every node's position constantly).
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Insets;
    import java.util.EventObject;
    import javax.swing.BorderFactory;
    import javax.swing.Box;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTree;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeCellEditor;
    import javax.swing.tree.DefaultTreeCellRenderer;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreeSelectionModel;
    public class ResizeNode extends JPanel {
           AnilTreeCellRenderer2 atcr;
           AnilTreeCellEditor2 atce;
           DefaultTreeModel treeModel;
           JTree tree;
           DefaultMutableTreeNode markedNode = null;
         public ResizeNode() {
                super(new BorderLayout());
                   treeModel = new DefaultTreeModel(null);
                   tree = new JTree(treeModel);          
                  tree.setEditable(true);
                   tree.getSelectionModel().setSelectionMode(
                             TreeSelectionModel.SINGLE_TREE_SELECTION);
                   tree.setShowsRootHandles(true);
                  tree.setCellRenderer(atcr = new AnilTreeCellRenderer2());
                  tree.setCellEditor(atce = new AnilTreeCellEditor2(tree, atcr));
                   JScrollPane scrollPane = new JScrollPane(tree);
                   add(scrollPane,BorderLayout.CENTER);
         public void setRootNode(DefaultMutableTreeNode node) {
              treeModel.setRoot(node);
              treeModel.reload();
           public static void main(String[] args){
                ResizeNode tb = new ResizeNode();
                tb.setPreferredSize(new Dimension(400,200));
                  JFrame frame = new JFrame("ResizeNode");
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  frame.setContentPane(tb);
                  frame.setSize(400, 200);
                  frame.pack();
                  frame.setVisible(true);
                  tb.populate();
         private void populate() {
              TextAreaNode2 r = new TextAreaNode2(this);
               setRootNode(r);
               TextAreaNode2 a = new TextAreaNode2(this);
               treeModel.insertNodeInto(a, r, r.getChildCount());          
    class AnilTreeCellRenderer2 extends DefaultTreeCellRenderer{
    TreeBasic panel;
    DefaultMutableTreeNode currentNode;
      public AnilTreeCellRenderer2() {
         super();
    public Component getTreeCellRendererComponent
       (JTree tree, Object value, boolean selected, boolean expanded,
       boolean leaf, int row, boolean hasFocus){
         TextAreaNode2 currentNode = (TextAreaNode2)value;
         NodeGUI2 gNode = (NodeGUI2) currentNode.gNode;
        return gNode.box;
    class AnilTreeCellEditor2 extends DefaultTreeCellEditor{
      DefaultTreeCellRenderer rend;
      public AnilTreeCellEditor2(JTree tree, DefaultTreeCellRenderer r){
        super(tree, r);
        rend = r;
      public Component getTreeCellEditorComponent(JTree tree, Object value,
       boolean isSelected, boolean expanded, boolean leaf, int row){
        return rend.getTreeCellRendererComponent(tree, value, isSelected, expanded,
         leaf, row, true);
      public boolean isCellEditable(EventObject event){
        return true;
    class NodeGUI2 {
         final ResizeNode view;
         Box box = Box.createVerticalBox();
         final JTextArea aa = new JTextArea( 1, 5 );
         final JTextArea aaa = new JTextArea( 1, 8 );
         NodeGUI2( ResizeNode view_ ) {
              this.view = view_;
              box.add( aa );
              aa.setBorder( BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.GREEN ) );
              box.add( aaa );
              box.setBorder( BorderFactory.createMatteBorder( 5, 5, 5, 5, Color.CYAN ) );
         private Dimension getEditorPreferredSize() {
              Insets insets = box.getInsets();
              Dimension boxSize = box.getPreferredSize();
              Dimension aaSize = aa.getPreferredSize();
              Dimension aaaSize = aaa.getPreferredSize();
              int height = aaSize.height + aaaSize.height + insets.top + insets.bottom;
              int width = Math.max( aaSize.width, aaaSize.width );
              if ( width < boxSize.width )
                   width += insets.right + insets.left + 3;     // 3 for cursor
              return new Dimension( width, height );               
    class TextAreaNode2 extends DefaultMutableTreeNode {  
         NodeGUI2 gNode;
         TextAreaNode2(ResizeNode view_) {     
              gNode = new NodeGUI2(view_);
    }

    the node on the tree is only painted on using the
    renderer to do the painting work. A mouse listener
    has to be added to the tree, and when moved over an
    area, you have to determine if you are over the
    border and which direction to update the cursor and
    to know which way to resize when dragged. One of the
    BasicRootPaneUI has some code that can help determine
    that.Thanks for replying. What is your opinion on this alternative idea that I just had?
    I am wondering if it might be easier to have a toggle button in the node that you click when you want to resize the node. Then a mouse-down and dragging the mouse will resize the node. Mouse-up will reset the toggle button, and so will mouse down in an invalid area.
    Anil

  • How do I create an infinite drawing canvas in a ScrollPane?

    I wanted to figure this out on my own, but it is time to ask for help. I've tried too many different things. The closest I've come to the behaviour I want is with this code:
    final BorderPane root = new BorderPane();
    final Pane canvasWrapper = new Pane();
    canvasWrapper.setPrefSize(800, 500);
    canvasWrapper.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    canvasWrapper.setStyle("-fx-background-color: lightgray; -fx-border-color: green; -fx-border-width: 2px;");
    final Group canvas = new Group();
    canvasWrapper.getChildren().add(canvas);
    final ScrollPane scroll = new ScrollPane();
    scroll.setContent(canvasWrapper);
    root.setCenter(scroll);
    // event code for adding circles and lines to the canvas
    I want the ScrollPane to be filled with the Pane, so it can catch events for drawing. When the stage is resized, the ScrollPane is resized too. This the result of the BorderPane. What I want is to expand the window and have canvasWrapper expand to fill the entire ScrollPane viewport. When the stage is made smaller the ScrollPane shrinks, but I want the canvasWrapper to retain its size. The idea is the drawing canvas can only grow. When it gets too large for the current stage/ScrollPane size, the scrollpane can be used to navigate around the canvas.
    I tried using
    scroll.setFitToHeight(true);
    scroll.setFitToWidth(true);
    but this causes the Pane to be made smaller when the viewport is made smaller.

    I figured it out!
    Use
    scroll.setFitToHeight(true);
    scroll.setFitToWidth(true);
    to resize the Pane as the view port changes.
    Save the canvas' size as the Pane's size.
    canvas.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
                @Override
                public void changed(ObservableValue<? extends Bounds> ov, Bounds t, Bounds t1) {
                    canvasWrapper.setMinSize(t1.getMaxX(), t1.getMaxY());
    This forces the Pane to always be as large as the group is.
    Missed a piece of code - jrguenther

  • How to have automatic resizing of container when JInternalFrame resizes?

    Is there a good way for the automatic resizing of its container when a JInternalFrame is resized?
    The intent is to have the JTree below, automatically resize. for example,
    if you type newlines into the JTextArea contained in JInternalFrames.
    (Tried adding the JInternalFrames to a JDesktopPane, but it did not display them. I wonder if it is inefficient to have a JDesktopPane for each tree node).
    Is there any way to know if a JInternalFrame is resizing? Perhaps then one can reload the tree as:
    treeModel.reload()thanks,
    Anil
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.util.EventObject;
    import javax.swing.BorderFactory;
    import javax.swing.Box;
    import javax.swing.JDesktopPane;
    import javax.swing.JFrame;
    import javax.swing.JInternalFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTabbedPane;
    import javax.swing.JTextArea;
    import javax.swing.JToggleButton;
    import javax.swing.JTree;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeCellEditor;
    import javax.swing.tree.DefaultTreeCellRenderer;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreeSelectionModel;
    public class TreeFrames extends JPanel {
           AnilTreeCellRenderer3 atcr;
           AnilTreeCellEditor4 atce;
           DefaultTreeModel treeModel;
           JTree tree;
         public TreeFrames() {
                super(new BorderLayout());
                   treeModel = new DefaultTreeModel(null);
                   tree = new JTree(treeModel);
                  tree.setEditable(true);
                   tree.getSelectionModel().setSelectionMode(
                             TreeSelectionModel.SINGLE_TREE_SELECTION);
                   tree.setShowsRootHandles(true);
                  tree.setCellRenderer(atcr = new AnilTreeCellRenderer3());
                  tree.setCellEditor(atce = new AnilTreeCellEditor4(tree, atcr));
                   JScrollPane scrollPane = new JScrollPane(tree);
                   add(scrollPane,BorderLayout.CENTER);
         public void setRootNode(DefaultMutableTreeNode node) {
              treeModel.setRoot(node);
              treeModel.reload();
           public static void main(String[] args) throws ClassNotFoundException,
           InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException{
                TreeFrames tb = new TreeFrames();
                tb.setPreferredSize(new Dimension(800,600));
                  JFrame frame = new JFrame("Tree Windows UI Failed");
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  frame.setContentPane(tb);
                  frame.setSize(800, 600);
                  frame.pack();
                  frame.setVisible(true);
                  tb.populate();
         private void populate() {
              TextAreaNode3 r = new TextAreaNode3(this);
              setRootNode(r);
              r.gNode.addFrame();
              r.gNode.addFrame();
              TextAreaNode3 a = new TextAreaNode3(this);
              a.gNode.addFrame();
              treeModel.insertNodeInto(a, r, r.getChildCount());
              treeModel.reload();
    class AnilTreeCellRenderer3 extends DefaultTreeCellRenderer{
         TreeFrames panel;
    DefaultMutableTreeNode currentNode;
      public AnilTreeCellRenderer3() {
         super();
    public Component getTreeCellRendererComponent
       (JTree tree, Object value, boolean selected, boolean expanded,
       boolean leaf, int row, boolean hasFocus){
         TextAreaNode3 currentNode = (TextAreaNode3)value;
         NodeGUI4 gNode = (NodeGUI4) currentNode.gNode;
        return gNode.hBox;
    class AnilTreeCellEditor4 extends DefaultTreeCellEditor{
      DefaultTreeCellRenderer rend;
      public AnilTreeCellEditor4(JTree tree, DefaultTreeCellRenderer r){
        super(tree, r);
        rend = r;
      public Component getTreeCellEditorComponent(JTree tree, Object value,
       boolean isSelected, boolean expanded, boolean leaf, int row){
        return rend.getTreeCellRendererComponent(tree, value, isSelected, expanded,
         leaf, row, true);
      public boolean isCellEditable(EventObject event){
        return true;
    * this is done to keep gui separate from model - as in MVC.
    * not necessary.
    * @author juwo
    class NodeGUI4 {
         JPanel notes = new JPanel();
         final TreeFrames view;
         Box hBox = Box.createHorizontalBox();
         final JTextArea textArea = new JTextArea( 1, 5 );
         NodeGUI4( TreeFrames view_ ) {
              this.view = view_;
              hBox.add( textArea );
              textArea.setBorder( BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.GREEN )
              hBox.add(notes);
              hBox.setBorder( BorderFactory.createMatteBorder( 5, 5, 5, 5, Color.CYAN ) );
         void addFrame() {
            MyInternalFrame frame = new MyInternalFrame();
            frame.add(new JTextArea(1,5));
            frame.setVisible(true); //necessary as of 1.3
            notes.add(frame);
            try {
                frame.setSelected(true);
            } catch (java.beans.PropertyVetoException e) {}
    class TextAreaNode3 extends DefaultMutableTreeNode {
         NodeGUI4 gNode;
         TextAreaNode3(TreeFrames view_t) {
              gNode = new NodeGUI4(view_t);
    class MyInternalFrame extends JInternalFrame {
        static int openFrameCount = 0;
        static final int xOffset = 0, yOffset = 0;
        public MyInternalFrame() {
            super("Document #" + (++openFrameCount),
                  true, //resizable
                  true, //closable
                  true, //maximizable
                  true);//iconifiable
            //...Create the GUI and put it in the window...
            //...Then set the window size or call pack...
            setSize(300,300);
            //Set the window's location.
            setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
            this.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);
    }

    I think this does what you want; it's basically the same technique as we used before.
    It also suffers from an interesting bug: if I type in the text area inside the internal frame, the editor resizes nicely
    with the node below it staying visible; if I type in the text area next to the panel, the editor will resize over the node
    below it. I didn't dig into it further to see the cause.
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Insets;
    import java.awt.Rectangle;
    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    import java.util.EventObject;
    import javax.swing.BorderFactory;
    import javax.swing.Box;
    import javax.swing.JFrame;
    import javax.swing.JInternalFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTree;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.plaf.basic.BasicTreeUI;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeCellEditor;
    import javax.swing.tree.DefaultTreeCellRenderer;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreePath;
    import javax.swing.tree.TreeSelectionModel;
    public class TreeFrames extends JPanel {
         AnilTreeCellRenderer3 atcr;
         AnilTreeCellEditor4 atce;
         DefaultTreeModel treeModel;
         JTree tree;
         public TreeFrames() {
              super( new BorderLayout() );
              treeModel = new DefaultTreeModel( null );
              tree = new JTree( treeModel );
              tree.setUI( new TextAreaTreeUI() );
              tree.setEditable( true );
              tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
              tree.setShowsRootHandles( true );
              tree.setCellRenderer( atcr = new AnilTreeCellRenderer3() );
              tree.setCellEditor( atce = new AnilTreeCellEditor4( tree, atcr ) );
              JScrollPane scrollPane = new JScrollPane( tree );
              add( scrollPane, BorderLayout.CENTER );
         public void setRootNode( DefaultMutableTreeNode node ) {
              treeModel.setRoot( node );
              treeModel.reload();
         public static void main( String[] args ) throws ClassNotFoundException, InstantiationException,
                   IllegalAccessException, UnsupportedLookAndFeelException {
              TreeFrames tb = new TreeFrames();
              tb.setPreferredSize( new Dimension( 800, 600 ) );
              JFrame frame = new JFrame( "Tree Windows UI Failed" );
              frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
              frame.setContentPane( tb );
              frame.setSize( 800, 600 );
              frame.pack();
              frame.setVisible( true );
              tb.populate();
         private void populate() {
              TextAreaNode3 r = new TextAreaNode3( this );
              setRootNode( r );
              r.gNode.addFrame();
              r.gNode.addFrame();
              TextAreaNode3 a = new TextAreaNode3( this );
              a.gNode.addFrame();
              treeModel.insertNodeInto( a, r, r.getChildCount() );
              treeModel.reload();
         private static class AnilTreeCellRenderer3 extends DefaultTreeCellRenderer {
              TreeFrames panel;
              DefaultMutableTreeNode currentNode;
              public AnilTreeCellRenderer3() {
                   super();
              public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded,
                        boolean leaf, int row, boolean hasFocus ) {
                   TextAreaNode3 currentNode = (TextAreaNode3) value;
                   NodeGUI4 gNode = (NodeGUI4) currentNode.gNode;
                   return gNode.hBox;
         private static class AnilTreeCellEditor4 extends DefaultTreeCellEditor {
              DefaultTreeCellRenderer rend;
              public AnilTreeCellEditor4( JTree tree, DefaultTreeCellRenderer r ) {
                   super( tree, r );
                   rend = r;
              public Component getTreeCellEditorComponent( JTree tree, Object value, boolean isSelected, boolean expanded,
                        boolean leaf, int row ) {
                   return rend.getTreeCellRendererComponent( tree, value, isSelected, expanded, leaf, row, true );
              public boolean isCellEditable( EventObject event ) {
                   return true;
          * this is done to keep gui separate from model - as in MVC. not necessary.
          * @author juwo
         private static class NodeGUI4 {
              JPanel notes = new JPanel();
              final TreeFrames view;
              Box hBox = Box.createHorizontalBox();
              final JTextArea textArea = new JTextArea( 1, 5 );
              NodeGUI4( TreeFrames view_ ) {
                   this.view = view_;
                   hBox.add( textArea );
                   textArea.setBorder( BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.GREEN ) );
                   hBox.add( notes );
                   hBox.setBorder( BorderFactory.createMatteBorder( 5, 5, 5, 5, Color.CYAN ) );
                   DocumentListener dl = new DocumentListener() {
                        public void insertUpdate( DocumentEvent de ) {
                             resizeEditor();
                        public void removeUpdate( DocumentEvent de ) {
                             resizeEditor();
                        public void changedUpdate( DocumentEvent de ) {
                   textArea.getDocument().addDocumentListener( dl );
              void addFrame() {
                   MyInternalFrame frame = new MyInternalFrame();
                   frame.getContentPane().add( new JTextArea( 1, 5 ) );
                   frame.setVisible( true ); // necessary as of 1.3
                   notes.add( frame );
                   try {
                        frame.setSelected( true );
                   } catch ( java.beans.PropertyVetoException e ) {
                   frame.addComponentListener( new ComponentAdapter() {
                        public void componentResized( ComponentEvent e ) {
                             resizeEditor();
              private void resizeEditor() {
                   TreePath path = view.tree.getEditingPath();
                   if ( path != null ) {
                        Rectangle nodeBounds = ( (BasicTreeUI) view.tree.getUI() ).getPathBounds( view.tree, path );
                        Dimension editorSize = getEditorPreferredSize();
                        hBox.setBounds( nodeBounds.x, nodeBounds.y,
                                  editorSize.width, editorSize.height );
                        hBox.validate();
                        Rectangle visRect = view.tree.getVisibleRect();
                        view.tree.paintImmediately( nodeBounds.x, nodeBounds.y,
                                  visRect.width + visRect.x - nodeBounds.x,
                                  editorSize.height );
                        ( (TextAreaTreeUI) view.tree.getUI() ).resizeTree( path );
              private Dimension getEditorPreferredSize() {
                   Insets insets = hBox.getInsets();
                   Dimension boxSize = hBox.getPreferredSize();
                   Dimension taSize = textArea.getPreferredSize();
                   Dimension nSize = notes.getPreferredSize();
                   int height = taSize.height + nSize.height + insets.top
                             + insets.bottom;
                   int width = taSize.width + nSize.width;
                   if ( width < boxSize.width )
                        width += insets.right + insets.left + 3; // 3 for cursor
                   return new Dimension( width, height );
         private static class TextAreaNode3 extends DefaultMutableTreeNode {
              NodeGUI4 gNode;
              TextAreaNode3( TreeFrames view_t ) {
                   gNode = new NodeGUI4( view_t );
         private static class MyInternalFrame extends JInternalFrame {
              static int openFrameCount = 0;
              static final int xOffset = 0, yOffset = 0;
              public MyInternalFrame() {
                   super( "Document #" + ( ++openFrameCount ), true, // resizable
                             true, // closable
                             true, // maximizable
                             true );// iconifiable
                   // ...Create the GUI and put it in the window...
                   // ...Then set the window size or call pack...
                   setSize( 300, 300 );
                   // Set the window's location.
                   setLocation( xOffset * openFrameCount, yOffset * openFrameCount );
                   this.putClientProperty( "JInternalFrame.isPalette", Boolean.TRUE );
         private class TextAreaTreeUI extends BasicTreeUI {
              public void resizeTree( TreePath path ) {
                  treeState.invalidatePathBounds(path);
                  updateSize();
    }

  • How to restrict the maximum size of a java.awt.ScrollPane

    Dear all,
    I would like to implement a scroll pane which is resizable, but not to a size exceeding the maximum size of the java.awt.Canvas that it contains.
    I've sort of managed to do this by writing a subclass of java.awt.ScrollPane which implements java.awt.event.ComponentListener and has a componentResized method that checks whether the ScrollPane's viewport width (height) exceeds the content's preferred size, and if so, resizes the pane appropriately (see code below).
    It seems to me, however, that there ought to be a simpler way to achieve this.
    One slightly weird thing is that when the downsizing of the pane happens, the content can once be moved to the left by sliding the horizontal scrollbar, but not by clicking on the arrows. This causes one column of gray pixels to disappear and the rightmost column of the content to appear; subsequent actions on the scrollbar does not have any further effect. Likewise, the vertical scrollbar can also be moved up once.
    Also, I would like a java.awt.Frame containing such a restrictedly resizable scrollpane, such that the Frame cannot be resized by the user such that its inside is larger than the maximum size of the scrollpane. The difficulty I encountered with that is that setSize on a Frame appears to set the size of the window including the decorations provided by the window manager (fvwm2, if that matters), and I haven't been able to find anything similar to getViewportSize, which would let me find out the size of the area inside the Frame which is available for the scrollpane which the frame contains.
    Thanks in advance for hints and advice.
    Here's the code of the componentResized method:
      public void componentResized(java.awt.event.ComponentEvent e)
        java.awt.Dimension contentSize = this.content.getPreferredSize();
        this.content.setSize(contentSize);
        java.awt.Dimension viewportSize = getViewportSize();
        System.err.println("MaxSizeScrollPane: contentSize = " + contentSize);
        System.err.println("MaxSizeScrollPane: viewportSize = " + viewportSize);
        int dx = Math.max(0, (int) (viewportSize.getWidth() - contentSize.getWidth()));
        int dy = Math.max(0, (int) (viewportSize.getHeight() - contentSize.getHeight()));
        System.err.println("MaxSizeScrollPane: dx = " + dx + ", dy = " + dy);
        if ((dx > 0) || (dy > 0))
          java.awt.Dimension currentSize = getSize();
          System.err.println("MaxSizeScrollPane: currentSize = " + currentSize);
          setSize(new java.awt.Dimension(((int) currentSize.getWidth()) - dx, ((int) currentSize.getHeight()) - dy));
        System.err.println();
      }Best regards, Jan

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    public class ScrollPaneTest
        GraphicCanvas canvas;
        CustomScrollPane scrollPane;
        private Panel getScrollPanel()
            canvas = new GraphicCanvas();
            scrollPane = new CustomScrollPane();
            scrollPane.add(canvas);
            // GridBagLayout allows scrollPane to remain at
            // its preferred size during resizing activity
            Panel panel = new Panel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            panel.add(scrollPane, gbc);
            return panel;
        private WindowListener closer = new WindowAdapter()
            public void windowClosing(WindowEvent e)
                System.exit(0);
        private Panel getUIPanel()
            int w = canvas.width;
            int h = canvas.height;
            int visible = 100;
            int minimum = 200;
            int maximum = 500;
            final Scrollbar
                width  = new Scrollbar(Scrollbar.HORIZONTAL, w,
                                       visible, minimum, maximum),
                height = new Scrollbar(Scrollbar.HORIZONTAL, h,
                                       visible, minimum, maximum);
            AdjustmentListener l = new AdjustmentListener()
                public void adjustmentValueChanged(AdjustmentEvent e)
                    Scrollbar scrollbar = (Scrollbar)e.getSource();
                    int value = scrollbar.getValue();
                    if(scrollbar == width)
                        canvas.setWidth(value);
                    if(scrollbar == height)
                        canvas.setHeight(value);
                    canvas.invalidate();
                    scrollPane.validate();
            width.addAdjustmentListener(l);
            height.addAdjustmentListener(l);
            Panel panel = new Panel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(2,2,2,2);
            gbc.weightx = 1.0;
            addComponents(new Label("width"),  width,  panel, gbc);
            addComponents(new Label("height"), height, panel, gbc);
            gbc.anchor = GridBagConstraints.CENTER;
            return panel;
        private void addComponents(Component c1, Component c2, Container c,
                                   GridBagConstraints gbc)
            gbc.anchor = GridBagConstraints.EAST;
            c.add(c1, gbc);
            gbc.anchor = GridBagConstraints.WEST;
            c.add(c2, gbc);
        public static void main(String[] args)
            ScrollPaneTest test = new ScrollPaneTest();
            Frame f = new Frame();
            f.addWindowListener(test.closer);
            f.add(test.getScrollPanel());
            f.add(test.getUIPanel(), "South");
            f.pack();
            f.setLocation(200,200);
            f.setVisible(true);
            f.addComponentListener(new FrameSizer(f));
    class GraphicCanvas extends Canvas
        int width, height;
        public GraphicCanvas()
            width = 300;
            height = 300;
        public void paint(Graphics g)
            super.paint(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            int dia = Math.min(width, height)*7/8;
            g2.setPaint(Color.blue);
            g2.draw(new Rectangle2D.Double(width/16, height/16, width*7/8, height*7/8));
            g2.setPaint(Color.green.darker());
            g2.draw(new Ellipse2D.Double(width/2 - dia/2, height/2 - dia/2, dia-1, dia-1));
            g2.setPaint(Color.red);
            g2.draw(new Line2D.Double(width/16, height*15/16-1, width*15/16-1, height/16));
        public Dimension getPreferredSize()
            return new Dimension(width, height);
        public Dimension getMaximumSize()
            return getPreferredSize();
        public void setWidth(int w)
            width = w;
            repaint();
        public void setHeight(int h)
            height = h;
            repaint();
    class CustomScrollPane extends ScrollPane
        Dimension minimumSize;
        public Dimension getPreferredSize()
            Component child = getComponent(0);
            if(child != null)
                Dimension d = child.getPreferredSize();
                if(minimumSize == null)
                    minimumSize = (Dimension)d.clone();
                Insets insets = getInsets();
                d.width  += insets.left + insets.right;
                d.height += insets.top + insets.bottom;
                return d;
            return null;
        public Dimension getMinimumSize()
            return minimumSize;
        public Dimension getMaximumSize()
            Component child = getComponent(0);
            if(child != null)
                return child.getMaximumSize();
            return null;
    class FrameSizer extends ComponentAdapter
        Frame f;
        public FrameSizer(Frame f)
            this.f = f;
        public void componentResized(ComponentEvent e)
            Dimension needed = getSizeForViewport();
            Dimension size = f.getSize();
            if(size.width > needed.width || size.height > needed.height)
                f.setSize(needed);
                f.pack();
         * returns the minimum required frame size that will allow
         * the scrollPane to be displayed at its preferred size
        private Dimension getSizeForViewport()
            ScrollPane scrollPane = getScrollPane(f);
            Insets insets = f.getInsets();
            int w = scrollPane.getWidth() + insets.left + insets.right;
            int h = getHeightOfChildren() + insets.top + insets.bottom;
            return new Dimension(w, h);
        private ScrollPane getScrollPane(Container cont)
            Component[] c = cont.getComponents();
            for(int j = 0; j < c.length; j++)
                if(c[j] instanceof ScrollPane)
                    return (ScrollPane)c[j];
                if(((Container)c[j]).getComponentCount() > 0)
                    return getScrollPane((Container)c[j]);
            return null;
        private int getHeightOfChildren()
            Component[] c = f.getComponents();
            int extraHeight = 0;
            for(int j = 0; j < c.length; j++)
                int height;
                if(((Container)c[j]).getComponent(0) instanceof ScrollPane)
                    height = ((Container)c[j]).getComponent(0).getHeight();
                else
                    height = c[j].getHeight();
                extraHeight += height;
            return extraHeight;
    }

  • Resizing JFrame on button click to show an image on the JFrame

    Dear All,
    I have a JFrame which has an empty label. On button click I want to set an icon for the label and want the JFrame to be resized to show that icon. I am using frame.pack() and I am not using any other sizing function. The code that I have right now, prints the image on the panel, but does not resize the frame to show the image. Pleae could someone help.package gui;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ItemEvent;
    import java.awt.event.ItemListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    public class ComponentDemo extends JPanel implements ActionListener,
    ItemListener, MouseListener, KeyListener {
         private JTextArea textarea;
         private JButton button;
         private final static String newline = "\n";
         private JLabel imageIcon;
         public ComponentDemo() {
              button = new JButton("JButton welcomes you  to CO2001");
              button.addActionListener(this);
              add(button);
              textarea = new JTextArea(10, 50);
              textarea.setEditable(false);
              addMouseListener(this);
              textarea.addKeyListener(this);
              JScrollPane scrollPane = new JScrollPane(textarea);
              add(scrollPane);
              imageIcon = new JLabel();
              add(imageIcon);
              setBackground(Color.pink);
              new JScrollPane(this);
          * Create the GUI and show it. For thread safety, this method should be
          * invoked from the event-dispatching thread.
         private static void createAndShowGUI() {
              // Create and set up the window.
              JFrame frame = new JFrame("Simple FrameDemo");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              frame.setLocation(700, 200);
              // get the content pane and set the background colour;
              frame.add(new ComponentDemo());
         //     frame.setSize(screenSize);
              // frame.getContentPane().setBackground(Color.cyan);
              // Display the window.
              frame.pack();
              frame.setVisible(true);
              frame.setResizable(true);
         public static void main(String[] args) {
              // Schedule a job for the event-dispatching thread:
              // creating and showing this application's GUI.
              javax.swing.SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
                        createAndShowGUI();
         @Override
         public void actionPerformed(ActionEvent e) {
              // TODO Auto-generated method stub
              if (e.getSource() instanceof JButton) {
                   // System.out.println(e.getSource());
                   String text = ((JButton) e.getSource()).getText();
                   textarea.append(text + newline);
                   textarea.setBackground(Color.cyan);
                   textarea.setForeground(Color.BLUE);
                   textarea.setCaretPosition(textarea.getDocument().getLength());
                   imageIcon.setIcon(createImageIcon("SwingingDuke.png",
                   "Image to be displayed"));
         @Override
         public void itemStateChanged(ItemEvent arg0) {
              // TODO Auto-generated method stub
         @Override
         public void mouseClicked(MouseEvent arg0) {
              textarea.append("A Mouse click welcomes you to CO2001" + newline);
              textarea.setBackground(Color.green);
              textarea.setCaretPosition(textarea.getDocument().getLength());
         @Override
         public void mouseEntered(MouseEvent arg0) {
              // TODO Auto-generated method stub
         @Override
         public void mouseExited(MouseEvent arg0) {
              // TODO Auto-generated method stub
         @Override
         public void mousePressed(MouseEvent arg0) {
              // TODO Auto-generated method stub
         @Override
         public void mouseReleased(MouseEvent arg0) {
              // TODO Auto-generated method stub
         @Override
         public void keyPressed(KeyEvent e) {
              System.out.println(e.getKeyChar());
              textarea.append("The key " + e.getKeyChar()
                        + " click welcomes you to CO2001" + newline);
              textarea.setBackground(Color.YELLOW);
              textarea.setFont(new Font("Arial", Font.ITALIC, 16));
              textarea.setCaretPosition(textarea.getDocument().getLength());
         @Override
         public void keyReleased(KeyEvent e) {
              System.out.println(e.getKeyChar());
              // textarea.append("The key "+
              // e.getKeyChar()+" click welcomes you to CO2001" + newline);
              // textarea.setBackground(Color.green);
              // textarea.setCaretPosition(textarea.getDocument().getLength());
         @Override
         public void keyTyped(KeyEvent e) {
              // TODO Auto-generated method stub
              System.out.println(e.getKeyChar());
              // textarea.append("The key "+
              // e.getKeyChar()+" click welcomes you to CO2001" + newline);
              // textarea.setBackground(Color.blue);
              // textarea.setCaretPosition(textarea.getDocument().getLength());
         /** Returns an ImageIcon, or null if the path was invalid. */
         protected ImageIcon createImageIcon(String path, String description) {
              java.net.URL imgURL = getClass().getResource(path);
              if (imgURL != null) {
                   System.out.println("found");
                   return new ImageIcon(imgURL, description);
              } else {
                   System.err.println("Couldn't find file: " + path);
                   return null;
    }

    myJPanel.setPerferredSize(new Dimension(new_width, new_hight));
    myJFrame.pack();

  • JTable in JPanel last Column resize clips JTable doesnt repaint JPanel

    I have a JTable in a JPanel, when I drag the last column of the JTableHeader (u can see the column resizing as the text of the Table HeaderColumn moves with the drag) the JTable is outside the JPanel. Only when u click on another component and then click back on the JTableHeader does it repaint.
    I have tried jPanel.revalidate(); in the mouseDragged event of MouseMotionListener on the JTableHeader and all manner or repaints and fireTableStructureChanged. But I dont understand the order of events.
    The last bug to fix!!!
    NB I dont want to use scrollpane as its not necessary and as many tables are synchronized with one table it makes repaints less smooth
    Thanks Paul

    Well, I didn't find an answer but I did find a solution.
    The JPanel is the problem. I use it to help with layout which is not obvious in this example.
    As you can see in the code the JTable is placed in a JScrollPane which is place in a JPanel which is placed in a JTabbedPane.
    If I use Box instead of JPanel the JTable in the JScrollPane in the Box in the TabbedPane in the JFrame resizes correclty.
    So although JPanel is resizable with setSize it does not get resized when it's JFrame gets resized.
    I would still like to know why?
    ////////KBS
    JTabbedPane myTP = new JTabbedPane();
    Box myOne = Box.createHorizontalBox();
    Box myTwo = Box.createHorizontalBox();
    myOne.add(pane);
    myTP.add("One", myOne);
    myTP.add("Two", myTwo);
    ////////KBS

  • Resize jtable in jscrollpane

    Hi,
    I have a frame containing a JTable and a panel with buttons. When the window gets resized, I would like that the jtable takes the extra space and that the button panel stays the same. How can I do that? The jtable panel is already the "Center" and both panels stay the same...
    Thanks,
    Marie
    Here's the code:
    package test;
    import javax.swing.*;
    import java.awt.AWTEvent;
    import java.awt.event.WindowEvent;
    import java.awt.BorderLayout;
    import java.awt.GridLayout;
    import javax.swing.table.TableColumn;
    import javax.swing.table.TableColumnModel;
    public class Testframe extends JFrame {
        private JPanel mainPanel = new JPanel();
        private JPanel buttonPanel = new JPanel();
        private JPanel tablePanel = new JPanel();
        //Button panel
        private JButton applyTableBt = new JButton("Generate Table");
        private JButton addBt = new JButton("Add");
        private JButton editBt = new JButton("Edit");
        private JButton deleteBt = new JButton("Delete");
        private JButton matchBt = new JButton("Find");
        private JButton saveBt = new JButton("Save to file");
        private JButton loadBt = new JButton("Load from file");
         * Constructor.
         * @param a_parent Frame
        protected Testframe() {
            enableEvents(AWTEvent.WINDOW_EVENT_MASK);
            try {
                jbInit();
                this.setResizable(true);
                this.setVisible(true);
                pack();
            } catch (Exception e) {
                e.printStackTrace();
         * Initialization of the dialog.
         * @throws Exception
        private void jbInit() throws Exception {
            this.setTitle("Pattern management - CAT");
            Object[][] data = { {"11", "12", "13", "14", "15", "16", "17", "18"},
                              {"21", "22", "23", "24", "25", "26", "27", "28"}
            Object[] names = {"col1", "col2", "col3", "col4", "col5", "col6",
                             "col7", "col8"};
            JTable table = new JTable(data, names);
            table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
            //table.setColu
            TableColumnModel colModel = table.getColumnModel();
            for (int i = 0; i < table.getColumnCount(); i++) {
                TableColumn column = colModel.getColumn(i);
                column.setPreferredWidth(511);
            JScrollPane scrollPane = new JScrollPane(table);
            tablePanel.add(scrollPane);
            //Layout = vertical box with vertical gap
            buttonPanel.setLayout(new GridLayout(7, 1, 0, 5));
            buttonPanel.add(applyTableBt);
            buttonPanel.add(addBt);
            buttonPanel.add(editBt);
            buttonPanel.add(deleteBt);
            buttonPanel.add(matchBt);
            buttonPanel.add(saveBt);
            buttonPanel.add(loadBt);
            //mainPanel.setLayout(new BorderLayout());
            mainPanel.add(tablePanel, BorderLayout.CENTER);
            mainPanel.add(buttonPanel, BorderLayout.EAST);
            this.setContentPane(mainPanel);
         * Overrides this class to call the good method when the dialog is closed.
         * @param a_windowE WindowEvent
        protected void processWindowEvent(WindowEvent a_windowE) {
            //If it is a request to close the window (X)
            if (a_windowE.getID() == WindowEvent.WINDOW_CLOSING) {
                cancel();
            super.processWindowEvent(a_windowE);
         * Closes the dialog.
        private void cancel() {
            dispose();
        private static void createAndDisplayFrame() {
            //Make sure we have nice window decorations.
            JFrame.setDefaultLookAndFeelDecorated(true);
            new Testframe();
        public static void main(String[] args) {
            createAndDisplayFrame();
    }

    try changing these lines
    mainPanel.add(tablePanel, BorderLayout.CENTER);
    mainPanel.add(buttonPanel, BorderLayout.EAST);
    this.setContentPane(mainPanel);
    to this
    mainPanel.add(buttonPanel, BorderLayout.EAST);
    getContentPane().add(scrollPane, BorderLayout.CENTER);
    getContentPane().add(mainPanel, BorderLayout.EAST);

  • Can't resize JScrollPane

    I put a JTable in a JScrollPane using
    new JScrollPane(table);
    I can't change the Dimension of the JScrollPane and if the table is greater than the Panel it is cuted even if I scroll max ...
    Any Help is welcomed

    if changing size of the scrollpane does not work and the reason is not the layout you use you could try to put the scrollpane on a panel with Gridlayout(1,1) and resize the panel.

Maybe you are looking for