为什么我的JComponent paint(Graphics g)无法工作/没有被调用?

时间:2018-06-09 11:07:34

标签: java swing graphics paint jcomponent

我一直在尝试编写这个带有点的多边形的应用程序。当我试图首先运行它时,我认为我的观点存在问题。但是当我开始乱搞,寻找问题时,我意识到我在JComponent中的绘制方法甚至没有被调用。我该怎么做才能解决这个问题?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JToggleButton;

public class PolygonBuilder extends JFrame{

    final static int WIDTH = 1280;
    final static int HEIGHT = 640;
    public static int xPointPos, yPointPos;
    public static void main(String[] args) {
        new PolygonBuilder();
    }
    public PolygonBuilder() {
        setTitle("Build a Polygon");
        this.setSize(WIDTH,HEIGHT);
        setResizable(false);
        JLabel placeholder = new JLabel();
        BuilderDrawingPanel BuilderPanel = new BuilderDrawingPanel();
        this.add(BuilderPanel, BorderLayout.CENTER);

        JToggleButton DotOnOff = new JToggleButton("Dot");
        DotOnOff.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent arg0) {
                // TODO Auto-generated method stub
                if(DotOnOff.isSelected()) {
                    System.out.println("ON");
                } else {
                    System.out.println("OFF");
                }
            }
        });

        DotOnOff.setBounds(100, 100, 90, 35);

        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
        executor.scheduleAtFixedRate(new RepaintTheBoard(this), 0L, 20L, TimeUnit.MILLISECONDS);

        addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent arg0) {}

            @Override
            public void mouseMoved(MouseEvent arg0) {
                Point p = MouseInfo.getPointerInfo().getLocation();
                xPointPos = (int) p.getX();
                yPointPos = (int) p.getY();
                System.out.println(xPointPos+","+yPointPos);
            }
        });

        this.add(DotOnOff);
        this.add(placeholder);
        setVisible(true);
    }
}
class RepaintTheBoard implements Runnable {
    PolygonBuilder theBuilder;

    public RepaintTheBoard(PolygonBuilder theBuilder) {
        this.theBuilder = theBuilder;
    }

    @Override
    public void run() {
        theBuilder.repaint();
    }
}

@SuppressWarnings("serial")
class BuilderDrawingPanel extends JComponent{
    static Graphics2D graphicSettings;
    static Shape drawLine;
    public BuilderDrawingPanel() {
        //stuff to draw at start
        System.out.println("Drawing..");
        drawLine =  new Line2D.Float(480,480,0,0);
    }
    @Override
    public void paint(Graphics g) {

        graphicSettings = (Graphics2D)g;
        System.out.println("Drawing..");
        graphicSettings.setColor(Color.RED);
        graphicSettings.fillRect(0, 0, getWidth(), getHeight());
        graphicSettings.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphicSettings.setPaint(Color.BLUE);
        graphicSettings.draw(drawLine);
    }
}

1 个答案:

答案 0 :(得分:1)

虽然c0der提供了一些有价值的信息和链接,但我觉得应该在答案中解决这方面的问题。

  • JFrame的(内容窗格)的默认布局为BorderLayout
  • 添加到没有约束的边框布局的任何组件都默认为CENTER
  • 边框布局的每个区域(布局约束)都可以显示一个组件。

那么我们来看看这部分代码:

this.add(DotOnOff);
this.add(placeholder);

JVM将尝试将它们添加到已添加构建器绘图面板的内容窗格的中心。所以这就是它甚至没有出现(或被绘制)的原因。

其他提示:

  • 在任何JComponent中,覆盖自定义绘制的正确方法是paintComponent(Graphics)方法。
  • 任何重写的paint方法都应立即调用super方法,以确保绘制背景,边框和其他“自动”元素。
  • Graphics对象是暂时的,因此不应存储为类的属性,并且当然不应声明为static
  • 说到static声明,它们(至少在GUI中)往往是问题的来源而不是解决方案。除非您能解释为什么这样做才有意义,否则不要将GUI属性声明为静态。
  • 请学习常见的Java命名法(命名约定 - 例如EachWordUpperCaseClassfirstWordLowerCaseMethod()firstWordLowerCaseAttribute,除非它是UPPER_CASE_CONSTANT)并一致地使用它。

更新

这是问题中的来源,修复了最直接的问题。它并没有改变推荐的其他东西,也没有触及我在使用代码本身时遇到的其他问题。查看已更改的内容的注释以使其正常工作。

这就是它在这里看到的变化:

enter image description here

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.util.concurrent.*;
import javax.swing.*;

public class PolygonBuilder extends JFrame{

    final static int WIDTH = 640;
    final static int HEIGHT = 320;
    public static int xPointPos, yPointPos;
    public static void main(String[] args) {
        new PolygonBuilder();
    }
    public PolygonBuilder() {
        setTitle("Build a Polygon");
        // let's be nice to the user..
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // this is almost certainly not the correct size, 
        // but in itself could deserve a question
        this.setSize(WIDTH,HEIGHT);
        setResizable(false);
        JLabel placeholder = new JLabel("Label!");
        BuilderDrawingPanel BuilderPanel = new BuilderDrawingPanel();
        this.add(BuilderPanel, BorderLayout.CENTER);

        JToggleButton DotOnOff = new JToggleButton("Dot");
        DotOnOff.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent arg0) {
                if(DotOnOff.isSelected()) {
                    System.out.println("ON");
                } else {
                    System.out.println("OFF");
                }
            }
        });

        DotOnOff.setBounds(100, 100, 90, 35);

        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
        executor.scheduleAtFixedRate(new RepaintTheBoard(this), 0L, 20L, TimeUnit.MILLISECONDS);

        addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent arg0) {}

            @Override
            public void mouseMoved(MouseEvent arg0) {
                Point p = MouseInfo.getPointerInfo().getLocation();
                xPointPos = (int) p.getX();
                yPointPos = (int) p.getY();
                System.out.println(xPointPos+","+yPointPos);
            }
        });

        // create a new panel for these buttons..
        //this.add(DotOnOff);
        //this.add(placeholder);
        JPanel buttonPanel = new JPanel(); // default flow layout
        buttonPanel.add(DotOnOff);
        buttonPanel.add(placeholder);
        // now add that panel above the builder panel
        this.add(buttonPanel, BorderLayout.PAGE_START);
        setVisible(true);
    }
}
class RepaintTheBoard implements Runnable {
    PolygonBuilder theBuilder;

    public RepaintTheBoard(PolygonBuilder theBuilder) {
        this.theBuilder = theBuilder;
    }

    @Override
    public void run() {
        theBuilder.repaint();
    }
}

@SuppressWarnings("serial")
class BuilderDrawingPanel extends JComponent{
    static Graphics2D graphicSettings;
    static Shape drawLine;
    public BuilderDrawingPanel() {
        //stuff to draw at start
        System.out.println("Drawing..");
        drawLine =  new Line2D.Float(480,480,0,0);
    }
    @Override
    public void paint(Graphics g) {

        graphicSettings = (Graphics2D)g;
        System.out.println("Drawing..");
        graphicSettings.setColor(Color.RED);
        graphicSettings.fillRect(0, 0, getWidth(), getHeight());
        graphicSettings.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphicSettings.setPaint(Color.BLUE);
        graphicSettings.draw(drawLine);
    }
}