1

I want add JScrolpane to JPanel, but that not appears. In JLabel works fine and its very easy. I am using JPanel beacuse I'll add some image proccessing stuff to my program. There is my code:

public void draw(){  
 panel=new JPanel(){
        protected void paintComponent(Graphics g){
            Graphics g2 = g.create();
            g2.drawImage(image, 0, 0, this);
            g2.dispose();             
        }         
 };   
 panel.setBorder(BorderFactory.createEtchedBorder());
 panel.setPreferredSize(new Dimension(400, 330));
 s=new JScrollPane(panel);
 s.setPreferredSize(new Dimension(400,285));
 this.getContentPane().add(s,BorderLayout.CENTER);
 add(panel);
 revalidate();  
 repaint();     
 }
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Michal
  • 65
  • 2
  • 9
  • 1
    It would help if you posted a sscce http://sscce.org – Aaron Kurtzhals Jan 14 '13 at 18:03
  • 2
    As long as we are giving free advice ;-): Don't call `setPreferredSize()`. Either override `getPreferredSize()` or use an appropriate `LayoutManagerµ . – Guillaume Polet Jan 14 '13 at 18:15
  • @Guillaume Polet You have right partly. See my answer. – Michal Jan 16 '13 at 14:52
  • @Michal in your case, you should obviously override `getPreferredSize()` and return the size of the image you paint. If at some point you were to switch to another image with a different size, all you would need to call is `revalidate(); repaint();` and it would all work perfectly. – Guillaume Polet Jan 16 '13 at 14:58
  • Hmm this trick with s.getPrefferedSize(); not working – Michal Jan 16 '13 at 21:08

3 Answers3

3
 s=new JScrollPane(panel);
 s.setPreferredSize(new Dimension(400,285));
 this.getContentPane().add(s,BorderLayout.CENTER);
 add(panel); // ****** ????????????
 revalidate();  
 repaint();     
}

You're adding the JPanel to the GUI not the JScrollPane, so you really shouldn't expect to see any scrollpanes if they've not been added anywhere.

Solution: Add your JScrollPane, s, that holds the JPanel to the GUI, not JPanel itself.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
3

You dont honor the paint chain, call super.paintComponent(g) as first call in overridden paintComponent method. i.e

@Override
protected void paintComponent(Graphics g){ 
      super.paintComponent(g); 
      //draw here
}

or visual artifacts may occur.

  • Also note the @Override annotation which should be used with overridden methods in order to gain the advantage of compiler checking that we overrode the method correctly.

  • There is no need for getContentPane().add(..) simply call add on JFrame instance as add(..) along with remove(..) and setLayout(..) have been forward to the JFrames contentPane

  • Also not a good idea to go extending JFrame for nor reason, simply create an instance and use that i.e:

    JFrame frame=new JFrame("Title here");
    ...
    frame.add(..);
    ...
    frame.pack();
    frame.visible(true);
    
  • Also draw onto the Graphics object passed into paintComponent g dont go creating your own in paintComponent. Unless of course you're doing if for the reason @HFOE mentioned in below comment :).

  • No need for this parameter in drawImage(..) unless your JPanel implements on ImageObserver or the image may not be fully loaded when painting occurs. Simply use null.

  • And just for the cherry on top use some Graphics2D and RenderHints as seen here. This will allow for a better quality image to be drawn and text.

Community
  • 1
  • 1
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • 1
    It's OK to create a new Graphics object if there's a risk that you may make changes to it that you don't want propagated elsewhere in your GUI such as in your JPanel's children. By changes I mean things such as setting an AffineTransform or Stroke. Otherwise 1+ – Hovercraft Full Of Eels Jan 14 '13 at 18:14
  • @HovercraftFullOfEels +1 good point updated answer accorodingly – David Kroukamp Jan 14 '13 at 18:20
0

I got it! The main reason for me was no-layout manager and no-declarated size of this. There is my code:

public void draw(){
 panel=new JPanel(new BorderLayout()){
 @Override
        protected void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.drawImage(img, 0, 0, null);
        }         
 };   
 panel.setBounds(0, 0, img.getWidth(), img.getHeight());
 panel.setPreferredSize(new Dimension(img.getWidth(),obraz.getHeight()));
 JScrollPane scrolls=new JScrollPane(panel,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);

 add(scrolls);
 validate();  
 repaint();     
 }

But if someone will want copy this code in the future, there is one thing to be known- a size of Jpanel isn't refreshing (it's always one size of first opened image), but I have scrolsl and I am satisfied for now ;). Thanks a lot for everyone.

Michal
  • 65
  • 2
  • 9