I have placed a JPanel object inside a JScrollPane and scrolling works as expected. By overriding paintComponent() I have attempted to do custom painting within the JPanel object. However when the JPanel object is placed within the JScrollPane the JPanel no longer paints properly (instead shows only its background color).
Because my application demands the JPanel to be updated constantly, a separate thread is constructed to repaint the JPanel at a specific interval.
The following excerpts of code show my current project:
a) paintComponent() from my JPanel (This method has been cut down to only the painting, the actual paint will be a constantly updating BufferedImage supplied from another thread instead of this big pink static box):
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//Render Frame
// 'RXDisplayCanvas' is the JPanel.
Graphics2D G2D = (Graphics2D)RXDisplayCanvas.getGraphics();
G2D.setColor(Color.PINK);
//800 and 600 are arbitrary values for this example, real values are calculated at runtime. The value calculation code is verified to work (as its used elsewhere in a similar scenario)
G2D.fillRect(0, 0, 800, 600);
G2D.dispose();
}
b) The 'updater' thread that periodically repaints the frame:
@Override
public void run() {
long MaxFrameTime;
long Time;
while(isVisible()){
// 'FPSLimit' is a integer value (default to 30)
MaxFrameTime = Math.round(1000000000.0 / FPSLimit);
Time = System.nanoTime();
try{
SwingUtilities.invokeAndWait(new Runnable(){
@Override
public void run() {
// 'RXDisplayCanvas' is the JPanel.
RXDisplayCanvas.repaint(); //When using this, the JPanel does not display correctly.
//RXDisplayCanvas.paintImmediately(0, 0, RXDisplayCanvas.getWidth(), RXDisplayCanvas.getHeight()); When using this, the JPanel renders correctly but flickers.
}
});
}catch(InterruptedException | InvocationTargetException e){}
Time = System.nanoTime() - Time;
if(Time < MaxFrameTime){
try{
Thread.sleep(Math.round((MaxFrameTime - Time)/1000000.0));
}catch(InterruptedException ex){}
}
}
}
I have taken into account that repaint() does not cause a immediate repainting of the screen but the issue lies with the incorrect rendering of the screen. When the program is left alone, it merely renders the background color of the JPanel until the JScrollPane is scrolled in which it renders correctly for one frame before the next repaint() call paints the incorrect display.
When switching repaint() out for paintImmediately() (in excerpt b) the frame rendered correctly but heavy flickering was present where it constantly alternated between painting the background color and painting the pink box. I have tried adding and removing layout managers, disabling the repaint manager as well enabling and disabling the 'double buffered' flag for both components in which all resulted in one of the two behaviors mentioned above (rendering only background or flickering).
Can anyone aid me on this issue?
N.B: I am well aware of Java's variable naming convention, since this is a private project I am choosing to start variable names with capital letters because I think it looks nicer, please do not post comments regarding this.