0

I am having issues with the java.awt.ScrollPane class's SCROLLBARS_AS_NEEDED display policy handling component resize. Ideally, if I have a ScrollPane that contains a Component that is significantly smaller than the Scrollpane and I shrink the Scrollpane to a size that is still greater than the child component, no scrollbars will appear. However, in practice both scrollbars seem to flicker while the resize operation is occurring and may even persist until the next redraw after the operation completes. Here is a small example to demonstrate what I mean:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Tester implements Runnable{

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.setProperty("sun.awt.noerasebackground", "true");
        Tester t = new Tester();
        SwingUtilities.invokeLater(t);
    }

    @SuppressWarnings("serial")
    @Override
    public void run() {
        JFrame frame = new JFrame("Tooltip tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 800);
        Canvas c = new Canvas(){
            @Override
            public void paint(Graphics g){
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
            }
        };
        c.setPreferredSize(new Dimension(400, 400));
        ScrollPane s = new ScrollPane();
        s.add(c);
        frame.add(s);
        frame.setVisible(true);
    }
}

Shrinking the window in the application above should cause scrollbars to flash. I believe this is caused by a bug in the implementation of the peer of the ScrollPane. (Source Here) I've copied the method that I believe has the error (line 145 in the link).

Dimension getChildSize() {
   ScrollPane sp = (ScrollPane)target;
    if (sp.countComponents() > 0) {
        Component c = sp.getComponent(0);
        return c.size();
    } else {
        return new Dimension(0, 0);
    }
}

To me, it seems like the getChildSize() method should call c.getPreferredSize() rather than c.size(). If the ScrollPane child's size is greater than its current preferred size, it should be able to shrink without scroll bars showing up (in my opinion). To test this theory, I overrode the size() method in my example from above:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Tester implements Runnable{

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.setProperty("sun.awt.noerasebackground", "true");
        Tester t = new Tester();
        SwingUtilities.invokeLater(t);
    }

    @SuppressWarnings("serial")
    @Override
    public void run() {
        JFrame frame = new JFrame("Tooltip tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 800);
        Canvas c = new Canvas(){
            private Dimension prefSize = new Dimension();
            @Override
            public void paint(Graphics g){
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
            }

            @Override
            public void setPreferredSize(Dimension preferredSize) {
                prefSize = preferredSize;
                super.setPreferredSize(preferredSize);
            }

            @Override
            public Dimension size() {
                return prefSize;
            }
        };
        c.setPreferredSize(new Dimension(400, 400));
        ScrollPane s = new ScrollPane();
        s.add(c);
        frame.add(s);
        frame.setVisible(true);
    }
}

This code behaves exactly how I want it to. However, overriding the size() method to do something other than what the documentation says it should do isn't a particularly elegant way to fix this problem. I feel like I must be doing something wrong here. Is it possible that a fairly basic functionality of the ScrollPane peer for X11 is broken?

A few other related notes:
-Use of java.awt.Canvas is non-negotiable for my purposes. In my actual application, I am drawing something very quickly using Java AWT Native Interface.
-While I read the documentation about new improvements to light/heavyweight compatibility in Java 7 and later versions of Java 6, I didn't really see an improvement in either case so I decided to stick with awt.ScrollPane over swing.JScrollPane. Either way, a ScrollPane should work correctly in the simple case I showed above.

EDM
  • 1
  • 1
  • 2
    I still wonder about your rationale for using AWT, whether your attempted Swing drawing code is the elephant in the room, and whether this needs to be the issue addressed and improved. – Hovercraft Full Of Eels Jun 26 '12 at 17:18
  • You are entirely correct that Swing would be the solution to this issue in most cases. However, I noticed a significant performance increase between drawing in Swing with Java Graphics and drawing with Java AWT Native Interface. Debating the difference between the two, while it may prove fruitful eventually, is an orthogonal issue and could take up an entire thread/question to itself. I believe there should be a simpler solution to the problem I outlined. – EDM Jun 26 '12 at 17:23
  • 1
    nice discusion, but maybe disadvantage could be your top_secret project, for better help sooner post an [SSCCE](http://sscce.org/) demonstrated some generated issue with quick painting and AWT Component, – mKorbel Jun 26 '12 at 17:26

1 Answers1

1

hard to help you without SSCCE, for future readers

However, in practice both scrollbars seem to flicker while the resize operation is occurring and may even persist until the next redraw after the operation completes

  • used LCD/LED panel caused those flickering (including MsExcell e.g., btw many times discused),

  • same flickering is for Swing JFrame with JScrollPane

  • not presented on CRT or Plasma display

  • if you playing FullHD video on PC, then every good multimedia players waiting until resize ended, thenafter fill available space into its container


  • you have to add ComponentListener, put there Swing Timer with small delay (KMPlayer show me 350-500milisecs), untill resize continue call for Timer#restart,

  • Canvas is good workaround for CAD / CAM, OpenGL(CL), good Java video players are based on AWT

  • you have to avoiding mixing Swing Container with AWT contents, lets everything is based on AWT (undecorated container)

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I'm more than a little confused by this. I gave an SSCCE demonstrating the problem and another showing a proposed solution. Did you try running either of them? This is an entirely software problem, meaning the type of monitor I use does not affect the outcome. This flickering does not occur with a Swing JScrollPane. Finally, I have already implemented a different workaround for this problem using a Swing Timer but it's even less elegant than the solution I proposed. – EDM Jun 26 '12 at 20:34
  • I tried both your examples, I miss there rendered Objects, resize of empty container is too different as in compare with with 5k resiziable lines, then my answer is based only on some of experiences with CAD / CAM, OpenGL(CL), nothing else – mKorbel Jun 26 '12 at 21:02
  • The point of an SSCCE is to strip out any unrelated complications to pare the problem down to its essential features so that's what I did. Were you able to tell how the two SSCCEs behaved differently from each other on resize? – EDM Jun 26 '12 at 21:22
  • I didn't see any difference, because I put there 5k resiziable lines (on short periond) with to change for Colors ([based on this thread](http://stackoverflow.com/questions/8614972/passing-current-date)), nor when I'm very fast to resize, nor with compare with mentioned MsExcell, – mKorbel Jun 26 '12 at 21:32
  • I'm not sure what you mean by "5k resiziable lines". Is this lines of code? Pixel rows? My question has nothing to do with resize performance and the content of the Scroll Pane is also irrelevant (as demonstrated by my SSCCEs that use a blank Canvas). The problem that I am encountering is that in the first SSCCE, scroll bars show up on resize when they shouldn't (because the ScrollPane's child is smaller than the ScrollPane). – EDM Jun 26 '12 at 21:39
  • aaaach put there ComponentListener I saw Scrollbars if Viewport is 400 and smaller, in both cases, `System.out.println(frame.getRootPane().getBounds()); System.out.println(s.getBounds()); System.out.println(s.getViewportSize());` – mKorbel Jun 26 '12 at 22:11
  • and I hope that your JDK is higher than Java4 and smaler than Java7_04, those I can to test – mKorbel Jun 26 '12 at 22:16