简体   繁体   English

绘制时,对象不会出现在Java小程序中。 我怎么能在AWT中正确使用paint / repaint方法?

[英]Objects will not appear in the java applet when drawn. How am I supposed to properly use the paint/repaint methods in AWT?

I have an applet interface that is supposed to draw a ball on the screen and have it bounce off the edges when the run button is pressed. 我有一个applet界面,应该在屏幕上绘制一个球,并在按下运行按钮时让它从边缘反弹。 There are other functions, but they require this first one to work. 还有其他功能,但它们需要第一个才能工作。 When run is pressed currently, nothing happens. 当前按下运行时,没有任何反应。 I don't think I am correctly drawing the object right. 我认为我没有正确地绘制对象。 I have put in System.err.println() statements around, and checking the console the program does go to the right methods when the button is clicked. 我已经放入了System.err.println()语句,并在单击按钮时检查控制台程序是否采用了正确的方法。 I just dont know what is wrong with the methods that should be drawing the object. 我只是不知道应该绘制对象的方法有什么问题。

The code is almost 500 lines, but i'll paste it in this body if need be. 代码几乎是500行,但如果需要我会将它粘贴到这个主体中。 Here it is: http://ideone.com/JL0B2 这是: http//ideone.com/JL0B2

First of all, you have to override paint of drawingpanel : this is where you draw your circle. 首先,您必须覆盖绘图drawingpanel :这是您绘制圆的位置。 Currently the circle appears only when you press Run button because it's painted over the components. 目前,只有在按下“运行”按钮时才会显示圆圈,因为它会在组件上绘制。
During normal painting, the applet area is painted (this is where your current paint works), and the all the components you added are painted, over the already painted dot. 在正常绘画期间,小程序区域被绘制(这是您当前paint工作区域),并且您添加的所有组件都在已绘制的点上绘制。

At the start of your program dot is null , so paint can't correctly draw it - it throws NullPointerException. 在程序开始时, dotnull ,因此paint无法正确绘制它 - 它会抛出NullPointerException。

You don't have to "cache" the Graphics instance: always use the Graphics that is given to you in paint. 您不必“缓存”Graphics实例:始终使用在paint中为您提供的Graphics。

If you want the circle to move, you have to create another thread so that it updates the values and then schedules repaint of the drawingpanel . 如果要移动圆,则必须创建另一个线程,以便更新值,然后计划重绘drawingpanel
And you don't have to repaint the entire applet, just the drawingpanel . 而且您不必重新绘制整个applet,只需绘制drawingpanel

If you still need help, ask them in comments. 如果您仍需要帮助,请在评论中询问。

Edit: 编辑:

Here's your drawingpanel where the dot is painted: 这里是你的drawingpanel其中圆点画:

    Panel drawingpanel = new Panel() {
        public void paint(Graphics g) {
            if (dot == null) {
                return;
            }
            g.drawOval(dot.leftOf(), dot.topOf(), dot.widthOf(), dot.heightOf());
            g.fillOval(dot.leftOf(), dot.topOf(), dot.widthOf(), dot.heightOf());
        };
    };

And your Bounce applet does not override paint() method. 并且您的Bounce applet不会覆盖paint()方法。

To implement animation, add Runnable interface to the implements section. 要实现动画,请将Runnable接口添加到implements部分。
Add another field: 添加另一个字段:

    volatile boolean running = false;
    private Thread animationThread;

Now let's implement simple animation: 现在让我们实现简单的动画:

    public void run() {
        while (running) {
            if (!showtails) {
                dot.setColor(drawingpanel.getBackground());
            }
            update();// check if speed, size, or shape changed
            draw();// draw next dot based on move(), or initial condition
            pause();
            move();// calculate and prepare the coordinates for the next
                   // iteration to be drawn
        }
    }

    public void draw() {
        drawingpanel.repaint();
    }

    public void pause() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void move() {
        dot.left--;
        dot.top--;
    }

And the final detail is the action handler: 最后的细节是动作处理程序:

    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();

        if (source == this.runbutton) {
            running = !running;
            if (animationThread == null) {
                animationThread = new Thread(this); 
            }

            if (running) {
                dot = new CircDot(100, 100, sizebar.getValue(), Color.RED);
                animationThread.start();
            }
        } else
            ...
    }

Here's how it works. 这是它的工作原理。 Your implementation started run() in the action handler and didn't return the control back to the EDT, thus your application appeared hung: it stopped handling messages. 您的实现在操作处理程序中启动了run()并且没有将控件返回给EDT,因此您的应用程序显示为挂起:它停止处理消息。

Now when Run button is clicked, the state field running is inversed, then a new thread is created if it wasn't already and started. 现在,当单击“运行”按钮时,将反转running的状态字段,然后创建一个新线程(如果尚未启动)。 The thread executes run() method. 该线程执行run()方法。 So the actions in the while body are executed until running becomes false . 因此,执行while主体中的操作直到running变为false

  • draw method call repaint() on the drawingpanel which schedules a paint operation. draw方法调用绘图drawingpanel上的repaint() ,它调度绘制操作。 When the message queue is empty, the system will call its paint method to re-draw the panel. 当消息队列为空时,系统将调用其paint方法重新绘制面板。
  • pause method calls Thread.sleep(500) to stop execution for 500 milliseconds. pause方法调用Thread.sleep(500)停止执行500毫秒。 The less the number is, the faster the dot will move. 数字越少,点移动得越快。 The value here will depend somehow on speed. 这里的价值取决于速度。 Never implement a pause with loop : you just waste processor time for no gain and you can't predict how much time it will take. 永远不要用循环实现暂停 :你只是浪费处理器时间没有增益,你无法预测需要多长时间。
  • move just decreases top and left coordinates of dot so that it moves to the left top corner of the window. 移动只是减少点的topleft坐标,使其移动到窗口的左上角。

It is worth noting that running is declared volatile because the field is accessed from multiple threads without other means of synchronization. 值得注意的是, running被声明为volatile因为该字段是从多个线程访问的,没有其他同步方法。 If it's not there, the running animation may not see its modification from the EDT in the action handler. 如果不存在,则运行动画可能无法从动作处理程序中的EDT看到它的修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM