【问题标题】:Windows erases content of JFrame when overlapping重叠时 Windows 会擦除 JFrame 的内容
【发布时间】:2012-08-11 00:40:54
【问题描述】:

我使用 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 的大小或最小/最大。

我错过了什么吗?

【问题讨论】:

  • 您丢失的更多代码可能会告诉我们您的错误在哪里。考虑创建一个 small 可编译和可运行的程序,我们可以运行它并为我们展示您的问题。顺便说一句,您几乎不应该直接在顶级 Swing 窗口中绘制,而应该在 JComponent 的 paintComponent 方法中绘制,例如 JPanel。
  • 请同时显示paint() 方法代码或如HFOE 所说创建一个sscce

标签: java swing jframe jpanel paintcomponent


【解决方案1】:

直接向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() 方法。

【讨论】:

  • 使用paintComponent 在JPanel 上绘图是解决方案。似乎 JFrame 上的paint() 是在您调整窗口大小或最小/最大时执行的——而不是当其他窗口覆盖它并擦除内容时。反过来 - paintComponent 被触发并重新绘制内容。
  • @Protechnologia.pl:不仅如此,当你这样做时,你还获得了 Swing 双缓冲的优势。 1+。
  • 我注意到您的第一个 sn-p 中有一个小失误。您从静态方法 Main 调用非静态方法(准确地说 - 从静态方法 Main 中的内部类)。如果我是对的 - 在 Main 中,您应该首先创建一个 Test 类的实例,然后您就可以在其上调用这些方法。
  • @Protechnologia.pl 感谢您更新代码。是按头做的:P
【解决方案2】:

正如 David 在较早的答案中所建议的那样,这不是处理 Swing 的好方法,但如果你必须这样做,或者以某种方式想要这样做,你可能想要使用 WindowListener 接口(或 @987654323 @class,如果你想简化重写方法的任务)并使用windowActivatedwindowDeactivated 函数以某种方式调用repaint() 方法。 这是文档:WindowListener#windowDeactivated

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

【讨论】:

  • 不,最好的选择是不扩展JFrame,也不直接在JFrame中绘制。
  • 是的,你是完全正确的,而且我只是指出了一条出路,以防有人强调以这种方式解决问题。
猜你喜欢
  • 1970-01-01
  • 2021-05-13
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多