What is the difference between the Canvas class and the JPanel class, as far as graphics goes?
Are there any advantages or disadvantages to either of these classes?
I always use the Canvas class. Should I be using one class over the other? If so, why?
There are a few differences. JPanel:
is a Container, so you can add other Components to it
setBackground will automatically fill the background color
Set / Add tooltip
Add a Border
printComponent for printing
Fairly minor stuff, but sometimes important
Canvas: AWT
JPanel: Swing
Swing is based on AWT, so Canvas can be more lightweight and in lower layer.
If canvas meet all your requirements, just use Canvas.
PS: I don't think there would be too much expensive to use JPanel, just choose the one you like.
Related
I have been under the impression that a Canvas or a JPanel were necessary to put graphics on a JFrame, however I saw a video earlier in which the person was using paint(graphics g)while extending JFrame and hadn't made a panel or a canvas. If this is a case, why do people bother with making a Canvas or a JPanel?
JFrame extends from Frame, which extends from Window, which extends from Container, extends from Component which defines paint.
If this is a case, why do people bother with making a Canvas or a JPanel?
To answer that question, you need to have a better understanding of JFrame (and window based classes).
Complicated
JFrame is actually a composite component, that is, it's made of a number of other components which provide the core functionality of the window
What this means is, if you override paint and perform custom painting on the frame, it's very possible that you will paint over the child components or the child components will paint over it, and because of the way the paint subsystem works, will do so any time without the frame's paint method been called.
Decorations
Frame's include the window decorations within their available area. This means that the "viewable" area is actually smaller then the defined area of the frame.
This is also why it's recommend to use pack instead of setSize
This means that if you override paint you could actually paint under the window decorations (yes, this happens all the time, and we're tired of answering it)
Screen shot from How can I set in the midst?
The contentPane of JFrame takes care of this, as it's laid out within the viewable area.
Double buffering
Top level containers, like JFrame aren't double buffered, so, even if you overcome all of the above, you will get updates which flicker. Sure you could "devise" you're own double buffering algorithm, but in Swing (ie JPanel), it's free, so why bother
Locked in
As a general recommendation, we generally discourage extending from JFrame (or other top level containers) as it locks you into a single use case and prevents the possibility of re-use.
On the other hand, if you use a JPanel, you can add it to what ever container you want, when ever you want
When using a JFrame, I noticed some people spent their time doing
setSize(new Dimension(400,400));
rather than simply
setSize(400,400);
Are there any particular advantages to using the prior rather than the latter if not storing the object in a variable?
Also, can I not draw directly in JFrame? do I need a canvas for it? is it simply best to extend Canvas? no JComponent alternative to Canvas?
When using a JFrame, I noticed some people spent their time doing
setSize(new Dimension(400,400));
rather than simply
setSize(400,400);
Are there any particular advantages to using the prior rather than the
latter if not storing the object in a variable?
No. Basically it's just a connivance so you don't need to do something like...
Dimension dim = new Dimension(400, 400);
setSize(dim.width, dim.height);
You could just do
setSize(dim);
Having said that, you shouldn't rely on it, as pack will produce better results, if you've build you base components properly...
Also, can I not draw directly in JFrame? do I need a canvas for it?
Generally, no, you shouldn't paint directly to the frame, there are a number of important reasons why, to start with, JFrame (and other top level containers) are not double buffered, so repaints will flicker, also, the frame decorations are painted WITHIN the frame, so if you paint directly to the frame, you run the risk of painting under the decorations...
For example...
How to get the EXACT middle of a screen, even when re-sized
Graphics rendering in title bar
How can I set in the midst?
And just because I can't be bothered typing it again...
Why is overriding paint in a top-level container so bad?
is it simply best to extend Canvas? no JComponent alternative to Canvas?
This depends on your needs. Canvas is a heavy weight component, so adding it to a JFrame can cause problems. It is also not double buffered, so either you need to implement a BufferStrategy or implement your own double buffering...
And no, there is no Swing alternative to Canvas, but remember, Swing components are double buffered already and (at least since Java 6...I think), support hard ware acceleration through either Direct3D or OpenGL where available...
I've been searching many sources yet I still cannot find a decent explanation. Why should I use it, what is its' purpose and why does it differ from JPanels and such?
The speciality of Canvas is that, like Window, it can provide customized hardware-accelerated double-buffering and page-flipping. See BufferStrategy.
A canvas is for drawing on, basically. It also serves like a Panel for creating a custom AWT-based component, but unlike Panel it can't contain other components.
From my understanding, Canvas is just the AWT version of Swing's JComponent. You shouldn't use it directly, unless you're making a pure AWT app. You can find more info here.
public class Canvas
extends Component
implements Accessible
A Canvas component represents a blank rectangular area of the screen onto which the application can draw or from which the application can trap input events from the user.
An application must subclass the Canvas class in order to get useful functionality such as creating a custom component. The paint method must be overridden in order to perform custom graphics on the canvas.
A canvas is for drawing on, basically. It also serves like a Panel for creating a custom AWT-based component, but unlike Panel it can't contain other components.
Since JPanel and Canvas are both same-level components, the solution would probably be some sort of a 'hack'. This question says that you won't be able to add the lightweight component to the heavyweight canvas (I want JPanel transparent).
If this isn't posible, then would putting a transparent Component work? Also, is it feasible to add Swing components to the Component (it just has to work, even if it's bad). And how would I go about actually putting it over the canvas (since they are both same-level components)?
Note: I would never do something like this in a real app, I just need it in this case
One possiblity is to add the JPanel to whatever container the Canvas is on, then setting the color of the JPanel to have an alpha of 0. This should add it over the old one, without blocking out the Canvas. Is this what you want?
EDIT: Thinking about it, the JPanel's default color is transparent... You should just be able to add the JPanel the Canvas's parent, and lay it over it
Just started to getting familiar with graphics in Java.
What is the simplest way to draw primitives (lines, rectangles) in Java without OpenGL (JOGL)?
Looking for methods like putPixel, lineTo, etc.
UPD.
Where to paint? Canvas? Panel? Bitmap?
The built in interface is called "Graphics2D".
Here's a link to a Java Graphics2D Tutorial: http://java.sun.com/docs/books/tutorial/2d/index.html
You can get a Graphics/Graphics2D instance from any AWT/Swing component via the paint method. JPanel is probably best since it fits well with swing and is lightweight, meaning that only one native window is created - for the top level window. Swing components can also be double-buffered, meaning that the painting is done to an offscreen buffer first, before being transferred to the screen. This gives a smoother appearance and avoids flickering that can happen when painting directly to the screen, and is particularly important for smooth animation.
You can specifically draw to an offscreen buffer ("bitmap") that you can use afterwards, e.g. to draw an image for saving as a file later:
BufferedImage offImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Grapics2D g2 = offImg.createGraphics();
// .. optionally set attributes ..
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
My recent question about horizontal scrolling in Java includes a tiny little graphics example source code that you could use as a base to work from. There are both AWT and Swing implementations. The AWT doesn't support horizontal scrolling, so I'll be using swing.
Not recommending these as best practice or anything, they were a quick demonstration of my particular issue, but it might be enough to get you started.
Link is How to use my trackpad for horizontal mousewheel scrolling in a Java AWT ScrollPane
The original Java user interface classes are called AWT. These were "heavyweight" components, that sometimes acted differently on different systems (Windows, Mac, Unix). These components were difficult to use to make a GUI.
Sun developed Swing, which is a set of "lightweight" components that, to the maximum degree possible, work the same on different systems. These components made GUI development somewhat easier.
In order to have a canvas for graphics, you start with a javax.swing.JFrame. You add a child javax.swing.JPanel to the JFrame. You draw on the JPanel by overriding the paint method.
The JPanel paint method takes a java.awt.Graphics as input. You can cast Graphics to java.awt.Graphics2D. The methods of Graphics2D allow you to draw rectangles, images, text, lines, and arbitrary polygons.
You can find out more about Swing by reading Sun's Creating a GUI with JFC/Swing tutorial. You can find out more about 2D Graphics by reading Sun's 2D Graphics tutorial. More details on the Java classes I've mentioned can be found in the Javadoc.