当窗口重叠时,Windows会擦除JFrame的内容

4

我使用JFrame创建并显示一个窗口,设置了一些基本属性。

public FrameVertices( String sTitle, Graph mMap, int iMul ) {
    super( sTitle );

    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    setSize ( 300, 300 );
    setLocation ( 600, 300 );
    setVisible ( true);

    this.iMul = iMul;
    this.gGraph = mMap;
}

然后我使用 paint() 方法在窗口内绘制一些内容。

问题是,当其他窗口覆盖我的JFrame并再次显示出来时,JFrame的内容不会重新绘制,除非我调整大小或最小化/最大化JFrame

我是否忽略了什么?


3
你缺少更多的代码,可能会显示出错误的位置。考虑创建一个小型可编译和可运行的程序,我们可以运行并演示您的问题。另外,你几乎永远不应该直接在顶层Swing窗口中绘制,而应该在JComponent(如JPanel)的paintComponent方法中进行绘制。 - Hovercraft Full Of Eels
3
请同时展示paint()方法的代码,或者像HFOE所说创建一个sscce - David Kroukamp
2个回答

7

直接在JFrame上绘制并不是一个好的实践。更好的方法是在JPanel中重写paintComponent()方法,并将JPanel添加到JFrame中:

Test.java:

public class Test extends JFrame {

    public static void main(String[] args) {

       SwingUtilities.invokeLater(new Runnable() {
          public void run() {
           new Test().createUI();
          }
       });

    }

  void createUI() {

             setSize(500,500);
             getContentPane().add(new MyPanel());
             setVisible(true);      
       }
}

MyPanel.java:

class MyPanel extends JPanel {

    @override
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      //paint what you want here
      g.drawString("Hello world",250,250);
    }
}

然而,如果你必须这样做,我建议添加一个窗口 FocusListener,并在其获得焦点时调用 JFrame 实例的 repaint() 方法:http://docs.oracle.com/javase/tutorial/uiswing/events/windowlistener.html
通过 windowGainedFocus(WindowEvent e)windowStateChanged(WindowEvent e)windowActivated(WindowEvent e) 方法之一来调用 repaint(),然后会调用 paint() 方法。请注意不要删除 HTML 标签。

2
使用paintComponent在JPanel上绘制是解决方案。似乎当你调整窗口大小或最小化/最大化时,JFrame上的paint()方法会被执行 - 而不是当其他窗口覆盖它并擦除内容时。反过来 - paintComponent被触发并重新绘制内容。 - Protechnologia.pl
2
@Protechnologia.pl:不仅如此,当您这样做时,还可以获得Swing的双缓冲优势。1+。 - Hovercraft Full Of Eels
1
我注意到你的第一个片段中有一点小错误。你从一个静态方法Main中调用了非静态方法(确切地说,是从一个位于静态方法Main内部类中调用)。如果我没错的话,在Main中,你应该首先创建一个Test类的实例,然后才能在其上调用那些方法。 - Protechnologia.pl
@Protechnologia.pl 谢谢您更新的代码。我之前是凭记忆写的 :P - David Kroukamp

1

正如David在之前的回答中所建议的那样,这不是一个好的Swing编程方式,但如果你必须这样做,或者以某种方式想要这样做,你可能需要使用WindowListener接口(或WindowAdapter类,如果你想简化重写方法的任务),并使用windowActivatedwindowDeactivated函数来调用repaint()方法。

这里有文档:WindowListener#windowDeactivated

编辑:
从给定的代码示例中,似乎您已经扩展了JFrame类,因此您唯一的选择是实现WindowListener接口。


不,最好的选择不是扩展JFrame,也不是直接在JFrame中绘制。 - Hovercraft Full Of Eels
是的,你说得完全正确,我只是提出了一种解决问题的方法,以防万一有人强调要用那种方式解决问题。 - SpiXel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接