简体   繁体   English

Java Repaint - 当从另一个类调用repaint()时,JComponet需要重新绘制该类

[英]Java Repaint - JComponet needs to repaint the class when the repaint() is called from another class

I am still trying to get a repaint() method to work in a separate class with a class that extends the JComponent. 我仍然试图让一个repaint()方法在一个单独的类中工作,该类具有扩展JComponent的类。 I have placed a couple of post on here and so far I haven't been able to get the code to work. 我在这里放了几个帖子,到目前为止我还没能让代码工作。 I have gotten some good advice. 我得到了一些好的建议。 I am placing below what I have so far. 我现在放在我的目标之下。

Main Class 1: 主要等级1:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class DDHGenericFrame extends JFrame {
        private static final long serialVersionUID = 1L;
        DDHGenericPanel d = new DDHGenericPanel(); /*User defined class that is above*/

        public DDHGenericFrame() {
            initUI();
        }

        public final void initUI() {
            add(d);//Adds the panel to the JFrame
            setSize(650,350);
            setTitle("Lines");
            setLocationRelativeTo(null);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }

        public static void main(String[] args) {
            DDHGenericFrame ex = new DDHGenericFrame();
            ex.setVisible(true);
        }
}

Class 2: 第2类:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;

class DDHGenericPanel extends JPanel {
    private static final long serialVersionUID = 1L;
      public JButton aButton1;
      public JButton aButton2;
      public TestPane tPane = new TestPane();

    DDHGenericPanel(){
        System.out.println("DDH Generic JPanel");

          aButton1 = new JButton();
          aButton1.setText("Button 1");
          aButton1.addActionListener(new myButtonActionListener1());
          add(aButton1);

          aButton2 = new JButton();
          aButton2.setText("Button 2");
          aButton2.addActionListener(new myButtonActionListener2());
          add(aButton2);

          System.out.println("Before the setDraw!!!");
          tPane.setDraw(); 
          System.out.println("After the setDraw!!!");
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        System.out.println("paintComponent of DDHGenericPanel.java");
    }
}   

class myButtonActionListener1 implements ActionListener {
    public TestPane tPane = new TestPane();

    @Override
    public void actionPerformed(ActionEvent arg0) {
         System.out.println("Button 1 -- Before the setDraw!!!");
         tPane.setDraw(); 
         System.out.println("Button 1 -- After the setDraw!!!");
    }
}

class myButtonActionListener2 implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent arg0) {
          System.out.println("Button1 clicked 2");
    }
}

Class 3: (I had this one embedded in the same files as the class above -- it will be separate when I have the finished code) 第3类:(我把这个嵌入到与上面类相同的文件中 - 当我有完成的代码时它将是独立的)

/**
 * This class will draw a cricle with the repaint method
 * @author DDH
 */
class TestPane extends JComponent {
    private static final long serialVersionUID = 1L;
    private static final int LINE_THICKNESS = 4;
      private static final int LINE_GAP = 10;
    private Color lineColor = Color.red;

      /**
      * This method will draw the circle with coordinated (0,0)
      * @param none
      * @return none
      */
      public void setDraw() {
          repaint();//This should call the paintComponent() that is below and paint a circe but it does not for some reason.
      }

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

        int radius = 10;
        BufferedImage buffer = new BufferedImage(radius, radius, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = buffer.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint        (RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);

        Ellipse2D circle = new Ellipse2D.Float(0, 0, radius,radius);
        Shape clip = g2d.getClip();
        g2d.setClip(circle);
        AffineTransform at = g2d.getTransform();

        g2d.setTransform(AffineTransform.getRotateInstance(
                                                    Math.toRadians(45),
                                                    radius / 2, radius / 2));

        int gap = LINE_GAP;

        g2d.setColor(Color.WHITE);
        g2d.fill(circle);

        g2d.setColor(lineColor);
        //g2d.setStroke(new BasicStroke(LINE_THICKNESS));
        for (int index = 0; index < 10; index++) {
            int x1 = index*gap-(LINE_THICKNESS/2);
            int y1 = 0;
            int x2 = index*gap+(LINE_THICKNESS/2);
            int y2 = radius;
            int width = x2 - x1;
            int height = y2 - y1;

            g2d.fillRect(x1, y1, width, height);
            //g2d.drawLine(index * gap, 0, index * gap, getRadius());
        }

        g2d.setTransform(at);
        g2d.setClip(clip);
        g2d.dispose();
        g.drawImage(buffer, 0, 0, this);
    }

}

Frome what I have read and what people have posted this should work. 弗罗姆我所读到的以及人们发布的内容应该有效。 Is there a way to force it to paint right away. 有没有办法迫使它立即油漆。 Repaint() sometimes has a little bit of a delay. 重绘()有时会有一点延迟。 I want to use this as the start of a game and I have to be able to create an ArrayList of Circles and then repaint them immediately. 我想用它作为游戏的开始,我必须能够创建一个圆圈的ArrayList,然后立即重新绘制它们。 Currently this will only draw one circle in the top (0,0) coordinates. 目前,这只会在顶部(0,0)坐标中绘制一个圆圈。

Doug Deines Hauf Doug Deines Hauf

Is there a way to force it to paint right away. 有没有办法迫使它立即油漆。

It will paint right away as soon as the GUI is visible. 一旦GUI可见,它就会立即绘制。 There is nothing special that you need to do. 你不需要做什么特别的事情。 There is no need for a setDraw() method. 不需要setDraw()方法。 All components will automatically be painted when the GUI is displayed. 显示GUI时,将自动绘制所有组件。

      System.out.println("Before the setDraw!!!");
      tPane.setDraw(); 
      System.out.println("After the setDraw!!!");

That code does nothing. 那段代码什么也没做。 The GUI isn't visible yet so there is nothing to paint. GUI尚未可见,因此无需绘制任何内容。 There is no reason for you do invoke a repaint unless you actually change a property of a component on a visible GUI. 除非您实际更改可见GUI上组件的属性,否则没有理由调用重绘。

public void setDraw() {
      repaint();
  }

There is no reason to create a method that simply does a repaint(), get rid of this method. 没有理由创建一个简单地执行repaint()的方法,摆脱这个方法。 That is NOT what I suggested in your last posting. 这不是我在你上一篇文章中建议的内容。 I said you create a method to change a property that will affect the outcome of the painting of the component. 我说你创建了一个方法来改变一个会影响组件绘制结果的属性。

I gave you an example, like when you use setForeground(), the method changes the Color of the text to be painted, so repaint() is automatically invoked when the color is changed. 我给你举了一个例子,就像你使用setForeground()时一样,该方法改变了要绘制的文本的颜色,因此当颜色改变时会自动调用repaint()。

Get rid of all the complex painting code in your paint component and then try to do a simple 摆脱涂料组件中所有复杂的绘画代码,然后尝试做一个简单的

graphics.drawString();

Don't be playing with rotations and clips (even I have problem with these concepts and if not done correctly you may not get anything painted) until you get something basic working. 不要玩旋转和剪辑(即使我有这些概念的问题,如果没有正确完成,你可能得不到任何颜色),直到你得到一些基本的工作。 Then once you get that working you do something more complicated, one step at a time until you understand the basics. 然后,一旦你开始工作,你就会做一些更复杂的事情,一步一步,直到你理解基础知识。 Don't write a complex program until you get something simple working. 在得到简单的工作之前,不要编写复杂的程序。

Also, I don't know why you are attempting to draw from a buffered image. 此外,我不知道你为什么试图从缓冲图像绘制。 Just draw using the Graphics object that is passed into the paintComponent() method. 只需使用传递给paintComponent()方法的Graphics对象进行绘制。 There is no need to use a BufferedImage, Swing is already double buffered so you are just complicating your code. 没有必要使用BufferedImage,Swing已经是双缓冲的,因此您只是使代码复杂化。

Have you read the Custom Painting tutorial yet? 你读过自定义绘画教程了吗? It contains a working example. 它包含一个工作示例。

Edit: 编辑:

Having said all the above you still have two fundamental problems: 说完以上所有内容,你仍然有两个基本问题:

  1. you don't add the component to the panel 您不要将组件添加到面板
  2. the component doesn't have a preferred size so there is nothing to paint. 组件没有首选大小,因此无需绘制任何内容。 You need to override the getPreferredSize() method to return a reasonable size for the component that you want to paint. 您需要覆盖getPreferredSize()方法,以便为要绘制的组件返回合理的大小。

Even these two fixes don't solve the problem of your complex painting, but at least now I can get a simple drawstring(...) to work. 即使这两个修复程序也无法解决复杂绘画的问题,但至少现在我可以使用简单的束带(...)来实现。

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

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