Java 绘画图形界面的重叠

Java 绘画图形界面的重叠,java,swing,user-interface,for-loop,repaint,Java,Swing,User Interface,For Loop,Repaint,所以我基本上是在代码运行时创建倒计时, 这很好,我唯一的问题是 数字消失并被i的新值替换,它们保持新值与现有数字重叠。我尝试使用repaint()修复此问题,但它不起作用。我想知道我是否遗漏了什么,或者我是否应该尝试另一种方式 以下是计时器的代码: public void timer (Graphics g,int x){ x=550; for (int i = time;i>0;i--){ g.setColor(deepPlum); g.

所以我基本上是在代码运行时创建倒计时, 这很好,我唯一的问题是 数字消失并被i的新值替换,它们保持新值与现有数字重叠。我尝试使用repaint()修复此问题,但它不起作用。我想知道我是否遗漏了什么,或者我是否应该尝试另一种方式

以下是计时器的代码:

public void timer (Graphics g,int x){
    x=550;

    for (int i = time;i>0;i--){
        g.setColor(deepPlum);
        g.setFont(new Font("Monospaced", Font.PLAIN, 25));
        g.drawString("time: "+i, x, 650);
        repaint();

    } 
}

调用clearRect恢复矩形区域的背景,然后以“猜测”再次绘制 我不喜欢猜测,但似乎我们不会得到一个可运行的示例,它将提供一个关于问题是如何产生的清晰理解

证据。。。
我称之为super paint方法,但称之为paint方法。我知道这很好,因为我所有的其他图形都很好

这“表明”在正常的摆动“绘制”循环中调用了
定时器。如果这是真的,它解释了问题的原因

这个

public void timer (Graphics g,int x){
    x=550;

    for (int i = time;i>0;i--){
        g.setColor(deepPlum);
        g.setFont(new Font("Monospaced", Font.PLAIN, 25));
        g.drawString("time: "+i, x, 650);
        repaint();

    } 
}
就是简单地把所有的数字画在一起,每次画一个循环,这并不是倒计时应该怎么画的

相反,它应该只绘制剩余时间,一个值,而不是尝试绘制所有时间

您可以将“绘制循环”视为“框架”,它绘制组件当前状态的快照。为了使从一个时间点到另一个时间点的更改具有动画效果,您需要绘制许多这样的“帧”

我再次强烈建议你花点时间通读一遍,更好地理解绘画的实际效果

我认为,如果没有更多的证据,Swing
定时器将是更好的解决方案。这可用于计算剩余时间,并定期安排重新喷漆

因为我似乎经常做这类事情,所以我将核心功能封装到一个简单的
计数器
类中,该类有一个“持续时间”(或运行时),可以计算它一直运行的
持续时间
剩余的
时间和
进度
持续时间
运行时
的百分比可能比您需要的要多,但它为您提供了开始的基础

因为绘画是一门不精确的艺术(绘画周期之间的时间是可变的,即使使用
计时器时也是如此),所以我使用了基于“时间”的方法,而不是简单的“计数器”。在处理这些类型的场景时,这将为您提供更高级别的精度

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                // The following two lines just set up the
                // "default" size of the frame
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JComponent {

        private Counter counter;

        public TestPane() {
            Timer timer = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (counter == null) {
                        counter = new Counter(Duration.of(10, ChronoUnit.SECONDS));
                        counter.start();
                    }
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (counter != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                FontMetrics fm = g2d.getFontMetrics();

                long time = counter.getRemaining().getSeconds();

                int x = (getWidth() - fm.stringWidth(Long.toString(time))) / 2;
                int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
                g2d.drawString(Long.toString(time), x, y);
                g2d.dispose();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public static class Counter {

        private Duration length;
        private LocalDateTime startedAt;

        public Counter(Duration length) {
            this.length = length;
        }

        public Duration getLength() {
            return length;
        }

        public void start() {
            startedAt = LocalDateTime.now();
        }

        public void stop() {
            startedAt = null;
        }

        public Duration getDuration() {
            if (startedAt == null) {
                return null;
            }
            Duration duration = Duration.between(startedAt, LocalDateTime.now());
            if (duration.compareTo(getLength()) > 0) {
                duration = getLength();
            }
            return duration;
        }

        public Double getProgress() {
            if (startedAt == null) {
                return null;
            }
            Duration duration = getDuration();
            return Math.min(1.0, (double) duration.toMillis() / length.toMillis());
        }

        public Duration getRemaining() {
            if (startedAt == null) {
                return null;
            }
            Duration length = getLength();
            Duration time = getDuration();

            LocalDateTime endTime = startedAt.plus(length);
            LocalDateTime runTime = startedAt.plus(time);

            Duration duration = Duration.between(runTime, endTime);
            if (duration.isNegative()) {
                duration = Duration.ZERO;
            }

            return duration;
        }
    }

}
在有人告诉我
clearRect
将如何解决这个问题之前,需要注意的是
clearRect
将做两件事。首先,它将只显示循环的“最后”值,这显然不是OP想要的,并且它将用
图形
上下文的当前背景色填充指定区域,这“可能”不是OP想要的(因为它将在之前绘制的内容的顶部绘制一个漂亮的矩形)


如果使用得当,Swing绘制系统将在调用组件的
绘制
方法之前准备
图形
上下文,从而需要使用
clearRect
静音

您的上下文外代码片段引发更多问题,我们无法回答。考虑提供一个焦点-“如何”执行代码(该方法是如何调用的?绘画实际上是如何下降的?”代码>图形< /代码>来自何处,因为在此刻,代码类型的吓唬MeQueS-你正在画外面的需要油漆周期的上下文;您正在为背景使用基于alpha的颜色,以尝试实现透明度;你没有遵守规定的油漆链要求(不调用
super
paint方法)-还有一件事我想不起来,我确实调用了super paint方法,但在paint方法中。我知道这很好,因为我所有的其他图形都运行良好。然后你做了一些其他错误,这在你的上下文外示例中没有演示。如果您调用的是
timer
而不是
paint
方法,那么您使用的方法是错误的,这可能解释了我根本没有触及的背景的整体问题。我使用的是JFrameAll things equal附带的基本灰色,Swing paint引擎应该为
图形
上下文做好“准备”,包括用组件的背景色填充,或者清除上下文(如果是透明的),这表明OP的绘制超出了所需的绘制周期,或者他们正在做其他事情(如破坏绘制链),这在任何情况下都不会解决问题,或者只会掩盖一个更大的问题
clearRect
将“掩盖”更大的问题是——因此,从长远来看,你实际上不是在帮助OP,而是在伤害他们,这意味着我们将得到更多关于代码为什么会进一步偏离轨道的问题,这意味着我们需要强调他们过去给出的“坏建议”,这只会让我们大家看起来。。。好吧,坏消息:P-实际上需要的是一辆MCV-那么我们都可以停止猜测用潜在的“黑客”引导一些误入歧途对任何人都没有帮助-找出“是什么”造成了这个问题将更有助于为答案提供合适的解决方案-这听起来可能是命运多舛的,我只是试图提高问题的质量和提供的答案-并要求你考虑这一事实,他们可能是一个“更大的问题”,在玩并不意味着“有害”的任何人,再次,我很抱歉你采取了我的建议错误的方式,只是因为它存在,并不意味着它是“正确的”。这项工作的工具——我只是说,我们缺乏了解“正确”方法的背景-