I have been trying to code this application that makes polygons with points. When I have tried to run it at first, I thought that there was a problem with my points. But when I started messing around, looking for the problem, I realized that my paint method in a JComponent isn't even being called. What should I do to fix this?
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);
}
}
While c0der has provided some valuable information and links, I feel there are aspects of this that should be addressed in an answer.
JFrame
is a BorderLayout
.CENTER
.So then we come to this part of the code:
this.add(DotOnOff);
this.add(placeholder);
The JVM will try to add them to the center of the content pane to which the builder drawing panel has already been added. So that's why it does not even appear (or get painted).
Other tips:
JComponent
, the correct method to override for custom painting is the paintComponent(Graphics)
method.Graphics
object is transient, so should not be stored as an attribute of the class, and should certainly not be declared as static
.static
declarations, they are (in GUIs at least) more often a source of problems than solutions. Don't declare GUI attributes as static unless you can explain why it makes sense to do so.EachWordUpperCaseClass
, firstWordLowerCaseMethod()
, firstWordLowerCaseAttribute
unless it is an UPPER_CASE_CONSTANT
) and use it consistently.This is the source seen in the question, with the most immediate problem fixed. It does not change much of the other stuff recommended, nor does it touch on other problems I saw when working with the code itself. Look at the comments for the things that were changed to make it work.
This is how it looks here, with the changes:
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);
}
}