Требует ли вызов `repaint ()` «invoke»?

#java #performance #swing #timer

#java #Производительность #swing #таймер

Вопрос:

Component#repaint Требуется ли для вызова invokeLater или invokeAndWait если он не вызывается в потоке отправки событий AWT?

Я создал минимальные часы (просто для практики и для дальнейшего расширения), код как MCVE ниже:

 package digiclock;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.time.Instant;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ClockPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    public class ClockTimerTask extends TimerTask {

        @Override
        public void run() {
            SwingUtilities.invokeLater(new Repainter());
            var delay = calculateDelay(precision);
            timer.schedule(new ClockTimerTask(), delay);
        }
    }

    public class Repainter implements Runnable {

        @Override
        public void run() {
            ClockPanel.this.repaint();
        }
    }

    private Timer timer;
    private Precision precision;

    public ClockPanel(Precision precision) {
        this.precision = precision;
        
        this.setBackground(Color.DARK_GRAY);

        // note that the Swing timer is so imprecise that it's usefulness is basically reduced to zero
        this.timer = new Timer("ClockTimer");
        var initialDelay = calculateDelay(precision);
        this.timer.schedule(new ClockTimerTask(), initialDelay);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.GREEN);
        // TODO take care of resizing specific to size of time etc
        g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 40));
        g.drawString(getTimeString(precision, LocalTime.now()), 10, 50);
    }

    private static int calculateDelay(Precision precission) {
        Instant delayNow = Instant.now();
        return precission.getInMilli() - (int) (delayNow.toEpochMilli() % precission.getInMilli());
    }

    private static String getTimeString(Precision precision, LocalTime time) {
        // TODO take care of precision
        
        // pattern for 24 hrs
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("HH:mm:ss");
        return time.format(pattern);
    }
}
 
 package digiclock;

import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.JFrame;

public class DigiClock extends JFrame {

    private static final long serialVersionUID = 1L;

    private static final double MM_IN_INCH = 0.0393701;

    private static final Dimension DIMENSION_IN_MM = new Dimension(120, 40);

    private static int RES = Toolkit.getDefaultToolkit().getScreenResolution();

    private static Dimension convertFromDimensionInMM(Dimension dimInMM) {
        return new Dimension(mmToPixels(dimInMM.width), mmToPixels(dimInMM.height));

    }

    private static int mmToPixels(int mm) {
        return (int) (mm * MM_IN_INCH * RES);
    }

    public static void main(String[] args) {
        var clock = new DigiClock();
        clock.setTitle("24-hour clock");
        clock.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        clock.setSize(convertFromDimensionInMM(DIMENSION_IN_MM));
        clock.add(new ClockPanel(Precision.SECOND));
        clock.setVisible(true);
    }
}
 

и, наконец,:

 package digiclock;

public enum Precision {
    DECISECOND(100), SECOND(1000), MINUTE(60_000);

    private int inMS;

    private Precision(int inMS) {
        this.inMS = inMS;
    }

    public int getInMilli() {
        return inMS;
    }
}
 

и я хочу, чтобы мой код ждал как можно меньше времени по понятным причинам.

Комментарии:

1. Поточно-безопасный вызов потока repaint() отправки событий Swing (EDT)

2. Соответствующий поиск в Google: site:stackoverflow.com java swing перерисовывает вызов из edt

3. @HovercraftFullOfEels Ах, спасибо, я пытался найти его, используя invoke в поисках, но это привело к сбоям. В любом случае, теперь я могу упростить свои часы.

4. Да, ключ часто заключается в том, чтобы знать правильные условия поиска

5. Да, и обычно у меня это неплохо получается, но да, иногда вы терпите неудачу.