简体   繁体   English

为什么会出现这种输出?

[英]Why does this kind of output appear?

I am following a tutorial and the output window prints "Hello World!" 我正在学习一个教程,输出窗口将显示“ Hello World!”。 there. 那里。 My question is, of the paint() method is not called from anywhere, then how does it print "Hello World!" 我的问题是,不是从任何地方调用paint()方法的,那么它将如何打印“ Hello World!”。 ?

Here is the code .. 这是代码..

package javagame;

import java.awt.Graphics;

import javax.swing.JFrame;


public class JavaGame extends JFrame{

    public JavaGame(){

        setTitle("sadid java game");    
        setSize(500, 500);
        setResizable(false);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    }

    public void paint(Graphics g){
        g.drawString("Hello world !!!!",30,30);
    }

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

    }

}

In the tutorial it prints normally the window with "Hello World!" 在本教程中,它通常使用“ Hello World!”打印窗口。 but when I run the same code this horrible output appears. 但是当我运行相同的代码时,会出现可怕的输出 How can this kind of output appear and why? 这种输出如何出现?为什么? Is there any problem in the code..? 代码中有什么问题吗?

This is a Swing GUI, the posted class extends JFrame and overrides the paint method (something you should not do). 这是一个Swing GUI,发布的类扩展了JFrame并覆盖了paint方法(您不应这样做)。

To answer your question, the paint method override of all Swing components are called automatically by the JVM whenever the component is rendered. 为了回答您的问题,每当呈现组件时,JVM都会自动调用所有Swing组件的paint方法覆盖。 The component is rendered when the application starts, if the component is visible, when it is resized, and when the operating system feels that the window with the component is "dirty" and needs to be repainted. 当应用程序启动时,如果可见的组件,调整组件的大小以及操作系统感觉到带有组件的窗口为“脏”并且需要重新绘制时,将呈现组件。

The component can also be painted if you suggest that it be repainted by calling repaint() on the component or on any container above it in its hierarchy. 如果您建议通过在组件上或其层次结构上的任何容器上调用repaint()来重涂组件,则可以对其进行绘制。 Note that I say "suggested" since you can only ask that the repaint manager paint the component but usually don't "demand" that it do so, so you can give the repaint manager the option of not repainting a region if repaint requests stack up. 请注意,我说“建议”是因为您只能要求重绘管理器绘制组件,但通常不“要求”这样做,因此,如果重绘请求堆栈,您可以为重绘管理器提供不重绘区域的选项起来。

So this means that paint method is never under your direct control and can be called many times or infrequently. 因此,这意味着Paint方法永远不受您的直接控制,并且可以被多次调用或不被频繁调用。

The reason that this code is not good code to follow is that: 该代码不适合遵循的原因是:

  • Their paint example does not call the super.paint(g) method, and so you're overriding a JFrame's paint method without telling it to do its normal painting. 他们的绘制示例未调用super.paint(g)方法,因此您将覆盖JFrame的绘制方法,而无需告诉其进行常规绘制。
  • The paint method is responsible for drawing a component's children and borders, and for a JFrame this is super-important. paint方法负责绘制组件的子代和边框,而对于JFrame,这是非常重要的。 By not calling the super method, you risk messing up these parts of the JFrame royally. 通过不调用super方法,您可能会冒乱弄乱JFrame的这些部分。
  • The paint method does not do double buffering by default, and if you try to do animation with it, you are guaranteed to have choppy animation unless you double buffer manually. paint方法默认情况下不执行双缓冲,并且如果您尝试使用它进行动画处理,除非手动进行双缓冲,否则可以保证具有不稳定的动画。

So in sum, don't override a JFrame's paint method unless you are very sure about what you are doing (which the author of your video was not ) and know the risks involved. 因此,总而言之,除非您非常确定自己在做什么(视频的作者没有这样做)并且知道所涉及的风险,否则不要重写JFrame的paint方法。 To draw correctly, check out the official Painting in Swing Tutorials , and follow their examples. 要正确绘制,请查看Swing教程中的官方绘画 ,并按照其示例进行操作。 For a more detailed explanation, please read Painting in AWT and Swing . 有关详细说明,请阅读AWT和Swing中的绘画

A better example of what the tutorial is trying to show would be: 本教程试图显示的一个更好的例子是:

import java.awt.*;
import javax.swing.*;

// draw in a JPanel, not in a JFrame
public class JavaGame2 extends JPanel {
   private static final int PREF_W = 500;
   private static final int PREF_H = PREF_W;

   public JavaGame2() {

   }

   // draw within the JPanel's paintComponent method
   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g); // be sure to first call the super's method
      g.drawString("Hello world !!!!", 30, 30);
   };

   // better to set size this way
   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      JavaGame2 mainPanel = new JavaGame2();

      // no need to extend JFrame. Instead just use one when needed
      JFrame frame = new JFrame("sadid java game");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {

      // be sure to start your Swing GUI in a thread-safe way
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

First you have to tell it's parent that you want to draw something (super.paint(g)).I think it will work: 首先你要告诉它的父母你想画点东西(super.paint(g)),我认为它会起作用:

import java.awt.Graphics;

import javax.swing.JFrame;

public class JavaGame extends JFrame{

    public JavaGame(){

        super("sadid java game");   
        setSize(500, 500);
        setResizable(true);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    }

    public void paint(Graphics g){
        super.paint(g);
        g.drawString("Hello world !!!!",200,300);


    }

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

    }

}

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

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