【问题标题】:Why isn't the ENTIRE JPanel repainting?为什么不重新绘制整个 JPanel?
【发布时间】:2015-01-25 11:26:57
【问题描述】:

为什么在 Java 中,当我尝试将窗口从屏幕一侧移动到中心时,整个 JPanel 不会自行重新绘制?

示例:当我尝试将窗口从屏幕的一侧(因此只有大约一半的窗口可见)拖动到中心时发生了这种情况:

如果我添加一个组件监听器,然后将repaint() 放在componentMoved 方法中,它会正常工作,但每次移动窗口时它都会重新绘制。

相关代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class TEST extends JFrame
{

    public TEST()
    {
        super ("TEST!");
        setSize (500,400);
        setLocationRelativeTo(null);
        setContentPane(new MyPanel());
        addComponentListener(this);
    }

    class MyPanel extends JPanel
    {   
        public void paintComponent (Graphics g)
        {

            super.paintComponent(g);

            Graphics g2d =  (Graphics2D) g;

            int R = (int)(Math.random()*256);
            int G = (int)(Math.random()*256);
            int B= (int)(Math.random()*256);
            Color color = new Color(R, G, B);

            g2d.setColor(color);
            g2d.fillOval(0, 0, getWidth(), getHeight());

        }
    }

    public static void main (String[] args)
    {
        TEST t = new TEST();
        t.setVisible(true);
    }
}

【问题讨论】:

  • 你似乎有一个线程竞争条件,面板已被完全绘制,但更新被......覆盖了一些新的随机颜色。确保您的 UI 是在事件调度线程的上下文中创建和启动的,有关更多详细信息,请参阅Initial Threads。另外,您使用的是什么操作系统?
  • 只是一个旁注:图形 g2d = (Graphics2D) g;这种情况什么也不做(当你投射 Graphics -> Graphics2D -> Graphics)
  • @Joeblade 但是,除非你有条件,否则你不能使用Graphics2D中的所有好东西... OP没有使用...
  • @MadProgrammer 是的,我只是指出,在他的演员阵容之后,他隐含地将其转换回 Graphics(因为变量 g2d 实际上是 Graphics,而不是 Graphics2D)
  • @VinceEmigh 这可以解释条带,正如 camickr 在他的回答中指出的那样,这似乎是绘画过程中的优化问题......

标签: java swing graphics jpanel paintcomponent


【解决方案1】:

有趣,我以前从未注意到这一点。

当您将框架拖到桌面边界之外时,没有任何反应。但是,当您将框架拖回中心时,组件会重新绘制,但绘制区域会被剪裁。根据您移动框架的速度,剪辑宽度(假设水平拖动)可能是几个像素或多个像素宽。

您可以通过在您的 paintComponent() 方法中添加以下内容来验证这一点:

 System.out.println(g.getClipBounds());

这显然是由Swing绘画机制控制的,不是我们能控制的。

解决方案是不要在每次调用paintComponent() 方法时更改绘画颜色,因为您已经注意到您无法控制何时调用paintComponent()。因此,将椭圆的颜色作为类的属性,并在创建类时生成随机颜色。

【讨论】:

  • 我看到,当我慢慢移动它时,宽度从 484 变为大约 1 或 2。我只是在 Java 中进行试验,因为我知道这也发生在 C# 中。我还想补充一点,当从桌面边界外水平或垂直移动框架时,会重现此效果。但是,如果您沿对角线拖动,则它将按应有的方式重新绘制。奇怪...
  • @whoareyou,对角拖动是有道理的。剪辑区域只是需要绘制的区域的矩形。当您水平拖动时,宽度只有几个像素,但高度是整个高度。当您垂直拖动时,宽度是整个宽度,高度是几个像素。当您沿对角线拖动时,您结合了水平和垂直拖动的最大宽度/高度,这意味着您需要重新绘制整个宽度和高度。如果它回答了您的问题,请不要忘记“接受”答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 1970-01-01
  • 2011-05-22
  • 2014-05-20
  • 2018-08-12
  • 1970-01-01
  • 2013-05-07
相关资源
最近更新 更多