Java 在满足一定条件时画一个圆

Java 在满足一定条件时画一个圆,java,swing,graphics,awt,frame,Java,Swing,Graphics,Awt,Frame,我的程序是把字母转换成一些信号。我的主要方法是生成一些随机字母。该字母被传递给另一个方法,该方法根据生成的字母调用repaint方法。PaintComponent方法用于绘制一个填充白色的圆。当我执行该程序时,我只得到一个Jframe。我看不到圆圈,请帮忙 package morsecode; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Random; impo

我的程序是把字母转换成一些信号。我的主要方法是生成一些随机字母。该字母被传递给另一个方法,该方法根据生成的字母调用repaint方法。PaintComponent方法用于绘制一个填充白色的圆。当我执行该程序时,我只得到一个Jframe。我看不到圆圈,请帮忙

package morsecode;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
import java.awt.*;


public class MorseCode extends Frame {


    public static void main(String[] args) {

                MorseCode mc = new MorseCode();
                 MorseCode frame = new MorseCode();


        final String chars = "abcdefghijklmnopqrstuvwxyz1234567890";
        char word;

                for(int i=1;i<=1;i++)

                {
            Random rand = new Random();
            int x = rand.nextInt(36);
            word = chars.charAt(x);
            System.out.print(word);
                        frame.setBackground(Color.BLACK);
                        frame.addWindowListener(
      new WindowAdapter()
      {
         @Override
         public void windowClosing(WindowEvent we)
         {
            System.exit(0);
         }
      }
      );

      frame.setSize(400, 400);
      frame.setVisible(true);
                         mc.toMorseCode(word);
                }
    }


    void toMorseCode(char letter)
    {

    switch(letter)
    {
        case 'A' | 'a':
            repaint();
            Thread.sleep(1000);
            repaint();
            Thread.sleep(2000);
            break;
        case 'B' | 'b':
            repaint();
            Thread.sleep(1000);
             repaint();
              Thread.sleep(1000);
              repaint();
                Thread.sleep(1000);
             repaint();
             Thread.sleep(2000);
            break; ..............
       }
}
    public void paintComponent(Graphics g) {
     Graphics2D ga = (Graphics2D)g;
     ga.setColor(Color.white);
     ga.fillOval(125,125,150,150);

  }
}
有两件事

首先,调用Thread.sleep2000;事件调度线程将阻止EDT处理事件队列上的事件,包括绘制事件

第二,框架没有paintComponent

添加@Override注释并尝试调用super.paintComponent会突出显示此问题,因为代码不会编译

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
首先,使用JPanel保存核心逻辑并执行自定义绘制

其次,使用javax.swing.Timer执行动画。有关更多详细信息,请参阅

更新

基本概念相对简单。您需要某种第二/后台线程,它可以在输出中的更改之间生成延迟。然后,您需要在每次延迟之前根据您试图显示的信息类型更新UI

由于Swing和大多数GUI框架一样是单线程的,并且不是线程安全的,所以实现变得很棘手

这意味着,您不能阻止GUI线程,这样做将阻止重新绘制UI,并且您必须在GUI线程的上下文中更新任何UI组件的状态

这意味着,虽然可以使用线程在后台运行,但必须确保对UI的所有更改/修改仅在EDT内执行

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MorseCodeTest {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static final int GAP = 500;
    public static final int DOT = 1000;
    public static final int DASH = 4000;

    public interface Transmitter {

        public void setTap(boolean tap);

    }

    public class TestPane extends JPanel implements Transmitter {

        private MorseCode code;
        private boolean tapped;

        public TestPane() {

            code = MorseCode.create('A').addDot().addDash();

            addMouseListener(new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    Signalar signalar = new Signalar(TestPane.this, code);
                    signalar.execute();
                }

            });

        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (tapped) {
                Graphics2D g2d = (Graphics2D) g.create();
                int diameter = Math.min(getWidth(), getHeight()) / 2;
                int x = (getWidth() - diameter) / 2;
                int y = (getHeight() - diameter) / 2;
                g2d.fillOval(x, y, diameter, diameter);
                g2d.dispose();
            }
        }

        @Override
        public void setTap(boolean tap) {
            tapped = tap;
            repaint();
        }

    }

    public class Signalar extends SwingWorker<Void, Boolean> {

        private final MorseCode code;
        private final Transmitter transmitter;

        public Signalar(Transmitter transmitter, MorseCode code) {
            this.code = code;
            this.transmitter = transmitter;
        }

        @Override
        protected void process(List<Boolean> chunks) {
            transmitter.setTap(chunks.get(chunks.size() - 1));
        }

        @Override
        protected Void doInBackground() throws Exception {
            for (Tone tone : code.getTones()) {
                publish(true);
                Thread.sleep(tone.getDelay());
                publish(false);
                Thread.sleep(GAP);
            }
            return null;
        }

    }

    public static class Tone {

        private final int delay;

        public Tone(int delay) {
            this.delay = delay;
        }

        public int getDelay() {
            return delay;
        }

    }

    public static class DashTone extends Tone {

        public DashTone() {
            super(DASH);
        }

    }

    public static class DotTone extends Tone {

        public DotTone() {
            super(DOT);
        }

    }

    public static class MorseCode {

        private final char value;
        private final List<Tone> tones;

        public static MorseCode create(char value) {
            MorseCode code = new MorseCode(value);
            return code;
        }

        public MorseCode(char value) {
            this.value = value;
            this.tones = new ArrayList<>(25);
        }

        public char getValue() {
            return value;
        }

        public MorseCode addDash() {
            return addTone(new DashTone());
        }

        public MorseCode addDot() {
            return addTone(new DotTone());
        }

        public MorseCode addTone(Tone tone) {
            tones.add(tone);
            return this;
        }

        public Iterable<Tone> getTones() {
            return tones;
        }

    }

}

使用逻辑一致的代码格式样式!代码缩进旨在帮助人们遵循程序流程。Swing是一个单线程框架,这意味着如果您阻止事件调度线程主UI线程,它将无法绘制或响应用户输入。看我在画法里面加了睡眠线。我仍然没有得到预期的结果。就像案例A一样,它应该闪烁三次。对于情况B,它应该闪烁两次,以此类推。有没有办法实现它。请帮助。Swing是一个单线程环境。任何阻止Swing thread(如thread.sleep)的操作都会阻止绘制。我从开关盒中删除了thread.sleep,并将其添加到绘制方法中。我看到一个眨眼。但是从case调用repaint并不能像我预期的那样在JFrame中重新绘制。你没有抓住要点。在事件调度线程上下文中调用Thread.sleep将阻止用户界面被绘制,到此为止!唯一的解决方案是设置第二个线程,负责管理计时和更改UI的状态。这是有问题的,因为您不应该从EDT以外的任何线程更改UI的状态,请参阅更新