What is the use of Canvas in AWT? - java

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.

Related

You don't need a Canvas or JPanel to draw?

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

Difference between Canvas and JPanel

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.

Swing rendering... does it always have to be repaint() and paintComponent()?

In my program I am using Swing windows for my GUI, and I know that I'm supposed to use repaint and paintComponent methods to render swing components. I also have several custom class objects that need to be rendered inside the main window. For the sake of understanding, my program is a game that will have moving objects that need to be rendered 60 times per second.
In a game development tutorial I watched, the guy used a Jframe with Canvas, but he didn't use the paintComponent method. He simply made his own render() methods to draw all the graphics using graphics context he obtained from creating a bufferStrategy.
So if that works (which it does), why does everyone say to use the paintComponent methods and what exactly is the difference between them?
If I were to use the paintComponent way of doing things, how would I use bufferStrategy with that?
In a game development tutorial I watched, the guy used a Jframe with Canvas, but he didn't use the paintComponent method. He simply made his own render() methods to draw all the graphics using graphics context he obtained from creating a bufferStrategy.
Canvas is an AWT component, using a BufferStrategy, you take over the painting process and become responsible for update the Graphics context and scheduling it's push to the hardware/screen.
This is commonly known as "active painting", as you are constantly (one would assume at a constant frame rate), updating the buffer.
Swing uses a passive paint process, so you never know when a paint process might occur. Swing has it's own mechanisms for determining what should be repainted and when. Using repaint, you make a request to these mechanisms that your component be repainted, but there is no guarantee that a paint cycle will be initiated because of it.
If you use any Swing component for you painting, you MUST use repaint and paintComponent, as the Swing is responsible for providing the context onto which you can paint.
If you want to use Canvas, then you can use a BufferStrategy instead.
Essentially, they are different approaches to painting. Remember though, if you use a BufferStrategy, you lose ALL of the Swing API, you CAN NOT use Swing components with this approach, as they are not designed to work this way...

How to solve graphical glitching with JDialog, JPanel?

So the intial setup for this issue is that there's a JDialog, and inside that I've placed a JPanel that would house the rest of the components (since painting the JDialog itself is apparently a bad idea). This JPanel has an overriden paintComponent(Graphics g) method that only paints the background and adds a faint border for aesthetic purposes.
Now inside that is a series of JPanels that categorize the contained form components, and each JPanel has an overridden paintComponent(Graphics g) as well, painting a semi-transparent background.
Inside each of those JPanels is where I start to have some issues, presumably with transparency. I have JTextFields, JCheckBoxes, JLabels, JSliders, etc inside these panels, and when you interact with one (hover, click, etc), the background goes from transparent to opaque, with an occassional ghosted image from another field (which appears slightly random sometimes). I'm using a custom LAF called Web, but I tested with other built-in LAFs and the same thing happens.
Is this a glitch with Java or did I mess something up? If so, how can I patch this up? I can paste code fragments later if necessary, but I've used several custom classes and nine-patch style image stitching which may make the code fragments hard to follow. Thanks in advance!
If you are painting components with a transparent background it is very important that the component is marked as transparent (setOpaue(false)) so that the repaint manager knows that it must paint the components below it.
It is also very important that when you are performing custom painting that you call super.paintComponent first.
This is especially important in the case of transparent components, as this prepares the Graphics context for painting.
Graphics is a shared resource. All the components painted in your window will share the same Graphics object, meaning that if you don't allow paintComponent to first prepare it, then you will see what was previously painted on it.

Simplest way to draw primitives in Java (not OpenGL)

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.

Categories