奇怪的JFrame行为 [英] Strange JFrame Behavior

查看:91
本文介绍了奇怪的JFrame行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下程序,运行时会有一些非常奇怪和不想要的行为。它应该有两个按钮,开始和停止,但是当我单击开始时,在开始正下方显示另一个按钮。这是我正在谈论的内容的打印屏幕:

I have the following program which has some very strange and unwanted behavior when it runs. Its supposed to have two buttons, "Start" and "Stop, but when I click "Start" another button shows up right below "Start". Here's a print screen of what I'm talking about:

我在做什么错了,如何解决这个丑陋的问题?

What am I doing wrong and how do I fix this ugly problem?

下面是代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class TwoButtonsTest {

    JFrame frame;
    Timer timer;
    boolean isClicked;

    public static void main(String[] args) {
    TwoButtonsTest test = new TwoButtonsTest();
    test.go();
    }

    public void go() {
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(500, 500);

    JButton startButton = new JButton("Start");
    startButton.addActionListener(new StartListener());
    JButton stopButton = new JButton("Stop");
        stopButton.addActionListener(new StopListener());

    final DrawPanel myDraw = new DrawPanel();

    frame.getContentPane().add(BorderLayout.CENTER, myDraw);
    frame.getContentPane().add(BorderLayout.NORTH, startButton);
    frame.getContentPane().add(BorderLayout.SOUTH, stopButton);


    frame.setVisible(true);

    timer = new Timer(50, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            myDraw.repaint();
        }
        });
    }

    class StartListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        //needs to be implemented
        if(!isClicked) {
        }
        isClicked = true;
        timer.start();
    }
    }

    class StopListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        //needs to be implemented
        timer.stop();
        isClicked = false;
    }
    }

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

        int red = (int)(Math.random()*256);
        int blue = (int)(Math.random()*256);
        int green = (int)(Math.random()*256);

        g.setColor(new Color(red, blue, green));

        Random rand = new Random();
        // following 4 lines make sure the rect stays within the frame
        int ht = rand.nextInt(getHeight());
        int wd = rand.nextInt(getWidth());

        int x = rand.nextInt(getWidth()-wd);
        int y = rand.nextInt(getHeight()-ht);

        g.fillRect(x,y,wd,ht);
    }
    } // close inner class
}

也我试图让开始按钮做两件事。当然,一种方法是开始播放动画,但是当按下停止按钮并再次按开始时,我希望它可以清洁屏幕,这样可以说并重新开始动画。

Also I'm trying to get the Start button to do two things. One is to of course start the animation but when the Stop button is pressed and I press Start again, I want it to clean the screen so to speak and start the animation again a new. Any tips on that?

推荐答案

您不会调用 super.paintComponent(Graphics g)在重写的 paintComponent(..)方法中,应尊重 paint链,并因此尊重其他组件的绘制。

You do not call super.paintComponent(Graphics g) in overriden paintComponent(..) method which you should in order to honor the paint chain and thus the painting of other components.

此调用也应该是方法中的第一个调用:

This call should also be the first call within the method:

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

    //do painting here
}  

可能会进行探查出现图纸不是永久性的。然后,您必须有一种方法来存储图形并每次重新绘制。最常见的是 ArrayList ,它将保存要绘制的对象(因此您不能将其添加到列表中,移除等),然后遍历列表并重新绘制其中的每个对象。 paintComponent 。请参阅我的答案此处

A probem might arise that drawings are not persistent. You must than have a way to store drawings and redraw every time. The most common is an ArrayList which will hold objects to be drawn (thus you cann add to the list remove etc), you would than iterate over the list and redraw each object in paintComponent. See my answer here for an example.

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
         //create UI and components here
    }
});


  • 不要调用 setSize(..) JFrame 上,而不是覆盖 JPanel getPreferredSize()并返回适合所有组件的合适高度,然后在设置 JFrame 可见之前调用 JFrame#pack()(但在添加所有组件)。

  • Dont call setSize(..) on JFrame rather override getPreferredSize() of JPanel and return an appropriate height which fits all components, than call JFrame#pack() before setting JFrame visible (but after adding all components).

    自<>起,无需 getContentPane()。add(..) Java 6+ add(..)默认为 contentPane

    No need for getContentPane().add(..) as of Java 6+ add(..) defaults to contentPane

    Do不重新声明 Random Random r = new Random()每次 paintComponent 之所以被调用,是因为这将使值的分布减少 random ,而在创建类并在实例上调用方法时将其初始化一次

    Do not re declare Random i.e Random r=new Random() each time paintComponent is called as this will make the distributions of the values less random rather initiate it once when class is created and call methods on the instance

    这是固定代码(已实施上述修复):

    Here is the fixed code (with above fixes implemented):

    import java.awt.*;
    import java.awt.event.*;
    import java.util.ArrayList;
    import java.util.Random;
    import javax.swing.*;
    
    public class TwoButtonsTest {
    
        JFrame frame;
        Timer timer;
        boolean isClicked;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    TwoButtonsTest test = new TwoButtonsTest();
                    test.go();
                }
            });
        }
        final DrawPanel myDraw = new DrawPanel();
    
        public void go() {
            frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JButton startButton = new JButton("Start");
            startButton.addActionListener(new StartListener());
            JButton stopButton = new JButton("Stop");
            stopButton.addActionListener(new StopListener());
    
    
            frame.add(myDraw, BorderLayout.CENTER);
            frame.add(startButton, BorderLayout.NORTH);
            frame.add(stopButton, BorderLayout.SOUTH);
    
    
            frame.pack();
            frame.setVisible(true);
    
            timer = new Timer(50, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    myDraw.repaint();
                }
            });
        }
    
        class StartListener implements ActionListener {
    
            @Override
            public void actionPerformed(ActionEvent e) {
                //needs to be implemented
                if (!isClicked) {
                }
    
                myDraw.clearRects();
    
                isClicked = true;
                timer.start();
            }
        }
    
        class StopListener implements ActionListener {
    
            public void actionPerformed(ActionEvent e) {
                //needs to be implemented
                timer.stop();
                isClicked = false;
            }
        }
    
        class DrawPanel extends JPanel {
    
            private ArrayList<MyRectangle> rects = new ArrayList<>();
            private Random rand = new Random();
    
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                addRect();
                for (MyRectangle r : rects) {
                    g.setColor(r.getColor());
                    g.fillRect(r.x, r.y, r.width, r.height);
                }
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(500, 500);
            }
    
            public void clearRects() {
                rects.clear();
            }
    
            public void addRect() {
                // following 4 lines make sure the rect stays within the frame
                int ht = rand.nextInt(getHeight());
                int wd = rand.nextInt(getWidth());
    
                int x = rand.nextInt(getWidth() - wd);
                int y = rand.nextInt(getHeight() - ht);
    
                int red = (int) (Math.random() * 256);
                int blue = (int) (Math.random() * 256);
                int green = (int) (Math.random() * 256);
    
                rects.add(new MyRectangle(x, y, wd, ht, new Color(red, blue, green)));
            }
        } // close inner class
    }
    
    class MyRectangle extends Rectangle {
    
        Color color;
    
        public MyRectangle(int x, int y, int w, int h, Color c) {
            super(x, y, w, h);
            this.color = c;
        }
    
        public Color getColor() {
            return color;
        }
    }
    

    这篇关于奇怪的JFrame行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆