0

When moving a JFrame, I sometimes see that part of it, that is the part where the frame and its old position overlap, will not refresh.

Here's an Horrible Paintjob Of An Explanation.

My theory that I hold dear is that by default Java will not update the contents of a JFrame that are hidden behind another window, and that it sometimes fails to understand that this other window is in fact the JFrame itself, but before the move you made it do (and where did that other dog come from...).

Would there be a way to force the JFrame to either entirely repaint itself regardless of its environment or at least make it re-check said environment? And where/how to get the window moving event's interpretation method at the end of which I'd place it?

Code example:

MyFrame:

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
public class MyFrame extends JFrame{
    private static final long serialVersionUID = 1L;
    public MyFrame(){
        this.setTitle("2D view");
        this.setSize(640,480);
        MyPanel mp=new MyPanel();
        this.setContentPane(mp);
        Timer timer=new Timer();
        this.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                timer.cancel();
                MyFrame.this.dispose();
            }
            public void windowOpened(WindowEvent e){
                if(MyFrame.this.isFocused()){
                    mp.requestFocus();
                }
            }
        });
        timer.scheduleAtFixedRate(new TimerTask(){
            public void run() {
                mp.repaint();
            }
        },0,1000/60);
    }
}

MyPanel:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class MyPanel extends JPanel{
    private static final long serialVersionUID = 1L;
    private static final int tsx=15;
    private static final int tsy=15;
    private int vscis;
    private int hscis;
    public MyPanel(){
        this.vscis=this.hscis=-1;
    }
  @Override
    public void setBounds(int x,int y,int width,int height){
        super.setBounds(x, y, width, height);
        this.vscis=-1;
        this.hscis=-1;
    }
    public void paintComponent(Graphics g){
        int w=this.getWidth(),h=this.getHeight();
        if(this.hscis==-1){
            this.hscis=(((w-(1+MyPanel.tsx))/2)/MyPanel.tsx)+1;
        }
        if(this.vscis==-1){
            this.vscis=(((h-(1+MyPanel.tsy))/2)/MyPanel.tsy)+1;
        }
        int i,j,posY=(h-((vscis*2+1)*tsy))/2,bposX=(w-((hscis*2+1)*tsx))/2,posX;
        Color clearC=new Color(11,66,66);
        Color clearW=new Color(0,0,0);
        for(i=0;i<=vscis*2;++i){
            posX=bposX;
            for(j=0;j<=hscis*2;++j){
                g.setColor(clearC);
                g.fillRect(posX,posY,tsx,tsy);
                g.setColor(clearW);
                g.drawLine(posX, posY, posX+tsx, posY);
                g.setColor(clearW);
                g.drawLine(posX, posY, posX, posY+tsy);
                posX+=tsx;
            }
            posY+=tsy;
        }
    }
}

Instantiate a MyFrame, and move it a few times on your screen. I use Win7 and I have the windows' contents not show as I move them (unchecked an option somewhere). This glitch is not reproductible by nature, but I have provided [a screenshot][5] on another website where it is apparent.

[5] user.oc-static (dot) com/upload/2017/03/10/148918317799_Sans%20titrescreencap.png

Can't post more than two links, figures.

Moige
  • 33
  • 6
  • Have you tried to call `frame.repaint();`? – Jérôme Mar 10 '17 at 22:32
  • When it comes down to the window, you're at the mercy of the os, so while you can repaint all you want, the os may either block or prevent those updates from occurring from a verity of reasons (flooding the dispatch thread with events for example). The problem may also be caused by bad painting code or using things like null layout which don't respond to changes in the container size. A runnable example which demonstrates your problem would be more useful the this endless guess work – MadProgrammer Mar 10 '17 at 22:42
  • @Jérôme Yes, I've tried repaint(). I have a homemade FPS enforcer that calls repaint() on my panel at 60Hz and prints on the error stream to show me it's doing its job. @ MadProgrammer If that's because of the OS, I'm screwed. Was my painting code bad it would always give me an error. I don't know about null layout but I had to do a thing for the window resize events and it repaints on resizing without a problem. I could post my code but it's part of an already quite large project, I'd have to select the useful parts. Tell me if you're willing to see it, 'cause I am not doing it for nothing. – Moige Mar 11 '17 at 01:14
  • Moige: concentrate much more on @MadProgrammer's comment than on Jerome's. If you follow his recommendation, you're much more likely to get a satisfactory answer. – Hovercraft Full Of Eels Mar 11 '17 at 01:17
  • We'll want to see an an [sscce](http://sscce.org) or a [minimal example program/mcve](http://stackoverflow.com/help/mcve) where you condense your code into the smallest bit (small enough to post in your question in its entirety) that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem. Yes, this will require work on your part, but it will give you the best chance of getting an answer. – Hovercraft Full Of Eels Mar 11 '17 at 01:19
  • Ultimately, I do not really care. This project's goal is for me to build the classes I will then use on an android app, but this glitch still bothers me. (as all glitches do, really). Also the question is less "What causes this?" and more "Is there a method for that? It could also prevent this.", because I did not find any way to set a flag when the frame is resized (windowListeners do not seem to help), my code would be irrelevant. – Moige Mar 11 '17 at 01:27
  • Ah, new comments, mine seem impolite all of a sudden, but alright, give me ten minutes and I'll post code. – Moige Mar 11 '17 at 01:28
  • 1
    Based on your example, you're violating the paint chain by not calling super.paintComponent – MadProgrammer Mar 11 '17 at 01:58
  • @MadProgrammer And where would that go? (At the beggining on MyPanel.paintComponent I'd guess?) – Moige Mar 11 '17 at 02:00
  • It should be the first thing you, as part of its job is to prepare the graphics context for painting (by filling it with the background Color) – MadProgrammer Mar 11 '17 at 02:01
  • @MadProgrammer My, my, I just read the paintComponent's javadoc, and it is written "if you do not invoker super's implementation you must honor the opaque property, that is if this component is opaque, you must completely fill in the background in a non-opaque color. If you do not honor the opaque property you will likely see visual artifacts. " Problem solved, everybody thank you for your time (and thank you for your answer MadProgrammer), I was just being an impatient idiot. – Moige Mar 11 '17 at 02:04
  • Welcome to the forest, look out for the trees ;) – MadProgrammer Mar 11 '17 at 02:05
  • @Moige: For [example](http://stackoverflow.com/a/7213546/230513). – trashgod Mar 11 '17 at 09:19

0 Answers0