I'm trying to make a paint editor with Java in which I have a toolbar with the objects that I would like to paste in the canvas. I'm using Swing components to make the GUI, but when I looked for the way of making the canvas, I only found the class canvas from AWT.
Is there any way to make something similar to canvas with Swing? (for example, JPanel?) I have read that using the class canvas from AWT with a GUI made with swing won't work correctly, is that true?
In order to make a custom 'Canvas' in swing you usually write a subclass of a JPanel. Then, you must overwrite the protected paintComponent(Graphics g) method of JPanel.
In the paint method, you can call methods on the Graphics object to actually draw on the JPanel.
As always, the Java Tutorials have a great reference on this to get you started.
You'll probably want to make a subclass of JPanel and implement your own way of painting components you want to draw onto the panel.
The basic approach will probably be along the line of assigning a MouseListener to the subclass of JPanel, then implement painting functionality.
The basic idea may be something along the line of:
class MyCanvas extends JPanel implements MouseListener
{
Image img; // Contains the image to draw on MyCanvas
public MyCanvas()
{
// Initialize img here.
this.addMouseListener(this);
}
public void paintComponent(Graphics g)
{
// Draws the image to the canvas
g.drawImage(img, 0, 0, null);
}
public void mouseClicked(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
Graphics g = img.getGraphics();
g.fillOval(x, y, 3, 3);
g.dispose();
}
// ... other MouseListener methods ... //
}
The above example is incomplete (and not tested -- it definitely won't compile), but it gives an idea about how to implement a MyCanvas class in which a user can click on and draw circles.
The img object is used to hold the image of the canvas. The paintComponent method is used to paint the img object to the canvas. In the mouseClicked method, the Graphics object associated with img is retrieved in order to fillOval onto the image.
Since one the requirements is to paste images onto the canvas, it may be a good idea to hold some Images that you want to paste into the canvas. Perhaps something along the line of:
Image[] myImages; // Used to store images to paint to screen.
Then, in the routine to paint the image onto img stored in MyCanvas:
g.drawImage(myImage[INDEX_OF_DESIRED_IMAGE], 0, 0, null);
By using the drawImage method of the Graphics object, other Images can be drawn onto Images.
As for the question on AWT and Swing, yes, it is true that you do not want to mix components from the AWT and Swing, as they differ in the way they render GUI components. AWT is based on heavyweight components, meaning they native windowing for painting the GUI, while Swing is based on lightweight components, meaning the GUI is drawn by Java itself without using native components.
A good guide on the difference of AWT and Swing is provided in Painting in AWT and Swing article from Sun.
Simply subclass JComponent.
JPanel is an inappropriate class. It is often suggested as it appears to have setOpaque(true) invoked on it automatically. It's actually the PL&F which does that, and whether or not it actually happens is implementation and vendor dependent.
Canvas is a heavyweight component. That is to say that it is controlled by the underlying windowing system. The result is that it will typically be drawn over the top of Swing components, without respect to z-order or clipping (putting it in a scroll pane will give odd behaviour).
You might want to look at the Minueto API. It is a very simple to use graphics api, and you can combine the Java event listening with it to provide your drawing capability.
http://minueto.cs.mcgill.ca/
Related
so when i try to create a paint method i.e.
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
}
my JFrame window will go completely black when I run my program. If I remove the paint method from the code, my normal images will appear in my JFrame window. I know FOR SURE that I am not using a .paint() method anywhere else in my code because I just added this method to my code now. Does anybody know why this is happening?
update, I am using eclipse
Start by taking a look at Performing Custom Painting and Painting in AWT and Swing to be better understand how painting works in Swing.
Basically, the paint subsystem is calling your paint method as required, when it decides that the component needs to be updated.
Because you've overridden it to basically do nothing, then nothing is painted.
As a general piece of advice, you should avoid overriding paint of top level containers like JFrame, because they are actually composite components. That is, they are actually made of a series of layers which the UI is built on
See How to use root panes for more details, but basically...
I am wondering whether I am able to use the paint method of Java's graphics class on something other than a JFrame--that is, no JFrames allowed. Is it possible?
Thanks in advance!
Graphics represents a graphic context, i.e. something you can draw on. In addition to GUI components like JFrame, JPanel etc. providing getGraphics() to access the visible gfx context, another common class that allows access to a gfx context is BufferedImage (or Image classes in general).
While painting on a visible GUI element immediately shows the results of the painting, using a BufferedImage allows you to perform the painting off screen into a buffer, and then painting the whole image at once (on a JFrame as you still need something visible) when you're ready to display the image. This is often used in animation and games when you need to avoid flickering for example.
I need some help with Java Swing components and its capabilities. I need to add a JPanel to a JFrame and paint an Ellipse2D on it. Onto the Ellipse2D I want to add another element, in my case it is a picture (right now I use an ImageIcon, maybe wrong). How can I achieve adding the Ellipse2D and the picture on the panel as shown in the image I attached?
The reason why I need the images separated is, because I need to change the filling color of the ellipse sometimes.
Thanks for any help.
What you need is to create a custom JPanel implementation and override paintComponent method.
Inside it, you just do:
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw ellipse here
// Draw your image here. It will be drawn on top of the ellipse.
}
This way, you can hold the ellipse fill color in the CustomPanel class, and just call repaint() method after you change the color.
your idea could be very good described (including code example) in the Oracles tutorial How to Decorate Components with the JLayer Class
notice JLayer is available only for Java7, but its based on (for Java6) JXLayer
you can use (I'm using) GlassPane too, with the same / similair output to the Swing GUI
EDIT
quite easy and nice output is by using OverlayLayout, there is possible to overlay J/Component(s) with Graphics e.g., a few examples
take the two images as image icons like
ImageIcon car=new ImageIcon("image path");
ImageIcon elipse=new ImageIcon("image path");
add those two image icons two label
JLabel carLabel=new JLabel(car);
JLabel ellipseLabel=new JLabel(ellipse);
and set the position of ellipse and car
carLabel.setBounds(0,0,50,50);
ellipseLabel.setBounds(10,10,50,50);
I'm trying to implement a simple window scale in java's swing library. The goal is simply to double the window height and width, and paint the window and each of its components in scale.
Here's an example of the code I'm using:
public class MyWindow extends JFrame {
...
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.scale(2,2);
super.paint(g);
}
}
The position and size for each my components in this window is set manually using setBounds with a null layout for the window.
When I actually run the program, what happens is that the first paint for the window seems successful-- everything is sized appropriately. Each subsequent repaint by the components, however, is neither twice the size, nor in the proper location. Here's what I mean:
As you can see, portions of the screen which have components that call repaint manually (the animating bits), don't seem to be using the Graphics2D scale of the JFrame. I looked in the source code, and tried overloading a few other methods (update and repaint, mostly), but all of them seemed to produce the same result. I further looked at the paint and repaint methods of the component and container classes, but they all seem to call a specified repaint of their parent. Shouldn't my Window be the "biggest" parent? If so, why haven't these repaint calls reached my Window?
My big question to you is, therefore: what repaint methods of the parent component do the child components call? Why aren't the calls properly routed to my JFrame's paint call? Is there any other (better) way that I can scale my window? Any and all help is appreciated!
As discussed in Painting in AWT and Swing: The Paint Methods, "Swing programs should override paintComponent() instead of overriding paint()." A common approach is to create a view by overriding paintComponent() in a JComponent (or subclass), as shown here. Let your view listen for changes to the game's model, as discussed here.
SwingUtilities.updateComponentTreeUI() should be used to change the Look & Feel, not update the view.
Use
javax.swing.SwingUtilities.updateComponentTreeUI(parentComponent);
when you need to make sure all of the parentComponents child component's look and feel are updated properly.
I'm writing a pretty simple game in Java, and I'm running into the issue of very serious flickering when I play the game as an applet in a browser. That is, all of my sprites, which are being painted on top of a background, are sometimes shown onscreen, but usually not - they repetitively flash onto the screen and then disappear. I've read that double buffering is probably the solution to this, but I'm having trouble implementing it correctly.
I'm using a JApplet as the container for a JPanel. This JPanel is the container onto which the sprites and game objects are painted - that is, in the JPanel's paintComonent method. In my JApplet, I'm using init, paint, and update override methods as follows:
Image offscreen;
Graphics bufferGraphics;
Dimension dim;
public void init(){
dim = getSize();
setBackground(Color.BLACK);
offscreen = createImage(dim.width,dim.height);
bufferGraphics = offscreen.getGraphics();
}
public void paint(Graphics g){
bufferGraphics.clearRect(0,0,dim.width,dim.height);
//here is my question - i"m not sure what I should print to bufferGraphics
g.drawImage(offscreen, 0, 0, this);
}
public void update(Graphics g){
paint(g);
}
The problem I'm running into is that, at the commented line, I'm unsure of what to do to get the current applet image printed to bufferGraphics. I read an example in which the sprite was painted straight to the JApplet, without using a JPanel. In light of that, my guess is that I'd need to paint the JPanel onto bufferGraphics at the commented line. Am I on the right track here? Any help is greatly appreciated; I just would like to know any way to do this properly.
Swing is double buffered by default, there is no need to do anything special.
Your problem is probably the painting code. The code you posted is used for AWT painting, NOT Swing painting.
Custom painting is done by overriding the paintComponent() method of a JPanel or JComponent. I suggest you start by reading the Swing tutorial on Custom Painting for a working example.