Difference Between Paint, Paintcomponent and Paintcomponents in Swing

Difference between paint, paintComponent and paintComponents in Swing

  • AWT, override paint().
  • Swing top-level container (e.g.s are JFrame, JWindow, JDialog, JApplet ..), override paint(). But there are a number of good reasons not to paint in a TLC. A subject for a separate question, perhaps.
  • The rest of Swing (any component that derives from JComponent), override paintComponent().
  • Neither override nor explicitly call paintComponents(), leave it to the API to call it when needed.

Be sure to also use @Override notation whenever overriding a method.

Doing so would hint at the problem of trying to override paintComponent(..) in a JFrame (it has no such method), which is quite common to see.

Difference between paint() and paintcomponent()?

Quoting from documentation of paint() method

This method actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren.
...
A subclass that just wants to specialize the UI (look and feel) delegate's paint method should just override paintComponent.

It looks like the paint() method actually draws the component, including the border and children. If you only want to customize the component's appearance excluding the border and children, you use paintComponent().

http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#paint(java.awt.Graphics)

paintComponent() vs paint() and JPanel vs Canvas in a paintbrush-type GUI

I've been trying to find a workarounds, but have not found one,
especially for the getGraphics() method: how else can the graphics be
added to the panel?

You remember what needs to be painted as a variable and use that in paintComponent().
For example, what you seemed to be trying to do in your other question would look like:

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

public class PaintRectangle extends JPanel {

private Point mouseLocation;

public PaintRectangle() {
setPreferredSize(new Dimension(500, 500));

MouseAdapter listener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
updateMouseRectangle(e);
}

private void updateMouseRectangle(MouseEvent e) {
mouseLocation = e.getPoint();
repaint();
}

@Override
public void mouseDragged(MouseEvent e) {
updateMouseRectangle(e);
}

@Override
public void mouseReleased(MouseEvent e) {
mouseLocation = null;
repaint();
}
};
addMouseListener(listener);
addMouseMotionListener(listener);
}

private Rectangle getRectangle() {
if(mouseLocation != null) {
return new Rectangle(mouseLocation.x - 5, mouseLocation.y - 5, 10, 10);
}
else {
return null;
}
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle rectangle = getRectangle();
if(rectangle != null) {
Graphics2D gg = (Graphics2D) g;
gg.setColor(Color.BLUE);
gg.fill(rectangle);
gg.setColor(Color.BLACK);
gg.draw(rectangle);
}
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new PaintRectangle());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

See also http://docs.oracle.com/javase/tutorial/uiswing/painting/

Java paintComponents is not being called

You're overriding Container#paintComponents(), which was inherited by your JFrame. Instead of extending JFrame, you need to extend JPanel so you can override its paintComponent() and getPreferredSize(). Then you can add() the panel to a JFrame, like they show here and here.

How to use Multiple Paint Components at the same time in java

I've used Thread.sleep()

Don't use Thread.sleep(...) when code is executing on the Event Dispatch Thread (EDT). This will prevent the GUI from painting itself.

The point of the paintComponent(...) method is to paint the current state of the component.

So you need a method(s) that will allow you to dynamically alter the state of the component. So maybe you have a property like: setPathLength(...). So once you calculate the longest path you know how many iterations are required to display the entire path.

Then you need to use a Timer to schedule your animation. Every time the Timer fires you need to increase the "path length" by 1 and then repaint() your component. So each time one more node is painted.

Read the section from the Swing tutorial on How to Use Swing Timers for more information.

Overriding paintComponent in AWT

how do you call this method? and where do you get the Graphics for it's parameter?

Call the component's repaint() method. It will call paintComponent() (as soon as the event dispatch thread is not busy). Actually you only need to do this call manually when conditions on which the painting depends change. Otherwise, your paint methods will be called automatically whenever the relevant part of the window needs painting, and that's all you need.

Why is paint()/paintComponent() never called?

These were the main problems with the original code that caused it not to work:

  1. not calling validate() after an add() operation
  2. not setting the preferred size of the component.
  3. not calling super.paintComponent() when overriding it (this made the
    setBackground() call not work)
  4. I needed to inherit from JPanel in order for it to get painted. Neither Component nor JComponent was sufficient for the setBackground() call to work, even when fixing point 3.

Having done the above, it really didn't matter if calling the method paintComponent or paint, both seemed to work as long as I remembered to call the super constructor at the start.

This info was assembled from what @jitter, @tackline, and @camickr wrote, so big kudos!

P.S. No idea if answering your own question is considered bad form, but since the information I needed was assembled from several answers, I thought the best way was upmodding the other answers and writing a sum up like this.

How to paint components in layers in Java?

You do not need to (and shouldn’t) extend BlackRect and MovingRect from JComponent.

For example, BlackRect could be a simple object, like:

class BlackRect {
int x, y;
int w = 100, h = 100;

public BlackRect(int x, int y) {
this.x = x;
this.y = y;
}

public void paint(Graphics2D g2d) {
g2d.setColor(Color.BLACK);
g2d.fillRect(x, y, w, h);
}
}

You should override GreenRect’s paint method, to paint rectangles on that panel:

public GreenRect extends JPanel {
// Existing members

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

Graphics2D g2d = (Graphics2D) g;

for (BlackRect black_rect : r) {
black_rect.paint(g2d);
}

// Also paint list of moving rectangles here
}
}

When GreenRect.repaint() is called, it will paint its background, and all rectangles from the r (and m list when you add that code). If the m rectangles have had their positions updated, they will be drawn at their new positions, so they will appear to be moving. Since moving rectangles are drawn last, they would appear “on top”.

Use a Swing Timer to drive the animation. When the timer expires, it should move all of the moving rectangles slightly (ie, call MovingRec.update()), and call repaint() on GreenRect.

Relationship between paint, paintComponent, repaint, etc

Firstly take a look at...

  • Performing Custom Painting and
  • Painting in AWT and Swing

The second should be compulsory reading for all Swing developers.

paint is (within the context of this question) the top level method called (update is actually called first, which just forwards to paint) when the RepaintManager wants a component to be painted.

paint is responsible for (amongst other things) calling paintComponent, paintBorder and paintChildren. If you're not careful you could compromise your components ability to paint. So if you HAVE to override paint, make sure you are calling super.paint.

It's important to note, the if a child component is updated, the parent component may not be repainted, so it don't try and use paint to provide overlays for your component.

paintComponent is responsible for painting the "background" of the component. This basically delegates to the look and feel.

In the case of something like JPanel, it will fill the background with the background color (if set to opaque). In the case of something like JTable, it will paint the rows, columns and cell values.

It is very important to ALWAYS call super.paintComponent, especially when dealing with transparent components.

repaint will make a request to the RepaintManager which may consolidate the paint requests so as to reduce the actual number of paint events that are raised. This helps improve performance.

The important thing to note here is that you don't control the paint process, so don't try, work with it instead.

Your paint method is also expected to run quickly, so avoid time consuming operations, like loading resources, or compound loops where possible. If you can, create backing buffers and paint those instead

ps- Paint is fun ;)

PaintComponent don't seem to get call or to show

You are adding a Swing component (javax.swing.JComponent) to an AWT frame (java.awt.Frame). Noone will call the paintComponents() method, that's why you don't get any output or result. Extend from javax.swing.JFrame instead, so you have a Swing frame with a Swing component.



Related Topics



Leave a reply



Submit