如何在没有actionlistener的情况下绘制线条?

时间:2015-06-06 03:52:32

标签: java swing

我正在编写一个应该在面板上写行和圆圈的GUI,我应该使用滑块来改变它们添加到面板的速度。我应该添加一个清除整个面板的清除按钮,然后当我移动滑块时,它们应该使圆圈和线条再次开始在面板上写入。滑块开头应该有一个特定的停止点。我们被告知要在滑块上没有动作滑块的情况下执行此操作。我在理解如何完成这项工作时遇到了一些麻烦。

以下是作业的要求: 编写一个提供以下功能的Swing程序:

在随机坐标处绘制随机颜色的随机长度线,每条线的绘图之间有暂停。

允许用户使用滑块设置线条之间的暂停长度。让最慢的值实际上停止绘制线条(即,一旦它在滑块上的值处于减速状态,它就会减速。)

有一个清除按钮,清除所有线条&界。确保清除按钮始终可用。

在随机坐标处绘制随机颜色的随机大小圆圈,每个圆圈的绘图之间有暂停。 (使用绘制,而不是填充。)

允许用户使用滑块设置圆圈之间的暂停长度。让最慢的值实际上停止绘制圆圈(即,一旦它在滑块上的那个值,它就会减慢到停止)。这与线的速度无关。

圆圈和线条都是独立绘制的,每个都在自己的线程中。 不要使用Timer,扩展Thread和/或Runnable。

    public class OhMy extends JFrame 
    {
        private static final int MAX_COLOR = 225;
        private static final long STOP_SLEEP = 0;

        public OhMy()
        {
            this.setTitle("Oh My Window");
            Container canvas = this.getContentPane();
            canvas.setLayout(new GridLayout(2,1));              
            JPanel panControl = new JPanel(new GridLayout(1,1));
            JPanel panDraw = new JPanel(new GridLayout(1,1));
            canvas.add(panControl);
            canvas.add(panDraw);                
            panControl.add(createPanControl());
            panDraw.add(createPanDraw());
            this.setSize(800, 600);
            this.setVisible(true);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }

        private JPanel createPanControl()
        {
            JPanel panControl = new JPanel();
            JLabel lines = new JLabel("Lines");
            panControl.add(lines);
            lines.setForeground(Color.RED);
            JSlider sldSpeedLines = new JSlider(1, 30, 5);
            panControl.add(sldSpeedLines);
            JButton btnClear = new JButton("Clear");
            panControl.add(btnClear);
            btnClear.setForeground(Color.RED);
            JSlider sldSpeedCircles = new JSlider(0, 30, 5);
            panControl.add(sldSpeedCircles);
            JLabel circles = new JLabel("Circles");
            panControl.add(circles);
            circles.setForeground(Color.RED);               
            btnClear.addActionListener((e)->
            {
                repaint();                  
            });             
            return panControl;              
        }           
        private JPanel createPanDraw()
        {
            JPanel panDraw = new JPanel();              
            class LinesThread extends Thread 
            {
                @Override
                public void run()
                {
                    try
                    {
                      Graphics g = panDraw.getGraphics();
                       while(g == null)
                        {
                         Thread.sleep(STOP_SLEEP);
                          g = panDraw.getGraphics();
                         }
                      Random rand = new Random();
                      int red = rand.nextInt(MAX_COLOR);
                      int green = rand.nextInt(MAX_COLOR);
                      int blue = rand.nextInt(MAX_COLOR);    
                      Color color = new Color(red, green, blue);    
                      int x1 = rand.nextInt(panDraw.getWidth());
                      int y1 = rand.nextInt(panDraw.getHeight());
                      int x2 = rand.nextInt(panDraw.getWidth());
                      int y2 = rand.nextInt(panDraw.getHeight());               
                      g.setColor(color);
                      g.drawLine(x1, y1, x2, y2);
                    }
                    catch(InterruptedException e1)
                    {
                        //awake now
                    }
                }
            }
            return panDraw;             
        }

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new OhMy();
            }
        });    
    }    
}

1 个答案:

答案 0 :(得分:2)

你说:

  

“我们被告知要在滑块上没有动作滑块的情况下这样做......”

  • ,因为JSliders不接受ActionListener。
  • JSliders会接受ChangeListener,但你可能甚至不需要使用它。
  • 相反,给clear按钮一个ActionListener(你根本无法使用ActionListeners)。
  • 在该ActionListener中,只需在其上调用getValue(),即可重置图形并从JSliders获取值
  • 不要通过调用JPanel上的getGraphics()来获取您的Graphics对象,因为这样获得的Graphics对象不会很稳定,有图像损坏,或者更糟糕的是,NullPointerException(看看我的意思,最小化和恢复)当前申请时的绘图)。
  • 相反,要么绘制在JPanel的paintComponent方法中显示的BufferedImage,要么直接在paintComponent本身中绘制。
  • 避免使用Thread和Thread.sleep,而是使用Swing Timer - 这样可以更加轻松地确保您的代码正确地进行了线程化。
  • 使用此值调整Swing Timer的速度。

修改
感谢Abishek Manoharan在我的回答中指出问题......

  • 如果JSliders需要在绘图进行时更改绘图速度,那么 实际上需要在滑块上使用ChangeListener。
  • 在该监听器中更改一个字段,告诉线程要睡多长时间。
  • 我发现你还需要使用后台线程。如果是这样,那么一定要在Swing事件线程上进行所有Swing调用。因此,如果您在后台线程中并且需要进行Swing调用,则通过调用SwingUtilities.invokeLater(...)在Swing事件线程上对其进行排队,并传入一个具有Swing调用的Runnable。