I coded a program where you can insert coordinates and the size of an sqaure and draw it on a JPanel. I used:
panel.getGraphics().drawRect(x,y,h,b);
Now I want to add an color-chooser like that:
color Farbe = JColorChooser.showDialog(null, "Color-Chooser", null);
So now how do I draw the Square with color? I tried this but it doesn't work:
panel.getGraphics().drawRect(x,y,h,b, Farbe);
panel.getGraphics() is NOT how custom painting should be performed.
See Painting in AWT and Swing and Performing Custom Painting for more details
Start by creating a custom component that extends from something JPanel, override it's paintComponent method (and make sure you call super.paintComponent before you do any custom painting).
Place you "drawing" logic within it. This panel should provide a setter and getter which allows external classes to change the color of the rectangle been draw, this way, when paintComponent is called, you can change the color of the Graphics context accordingly.
Also, take a look at 2D Graphics for more details about how painting is done
Don't forget to call repaint when the color is changed to encourage the panel to be repainted
Related
I'm new to making GUIs in Java. As I understand, there's a class called Graphics which is in charge of drawing shapes in a JPanel. When my application starts, I call the paintComponent method, which draws the board of the game I'm programming, and the paintComponent method takes a Graphics g as input. However, later on, I want to update the board, so how do I tell the same g that drew the board at the start of the game to draw something else when the user does something like clicking?
I believe this should have a very simple answer.
Every JComponent (Swing component) has a repaint() method, just call it to tell the DrawingManager to redraw your component.
All your drawing code should be in paintComponent method, that means that you don't draw anything anywhere else (you draw only in the flow of invocation of paintComponent, you can have drawing code structured in methods of course).
This method needs to have access to the state that indicates what and where should be drawn. It is because the OS could request repainting, and then only the painting methods from JComponent are called.
When you invoke repaint() on your JComponent, then in short time the paintComponent() method of the component on which you requested repainting will be called by the drawing thread, and you should draw only in this drawing thread.
Try repaint() or revalidate(), it should work.
I call the paintComponent method
No, you should never call the paintComponent() method directly. Swing will call the method for you when the component needs to be repainted.
I want to update the board
Then you need a "setter" method. Think of other Swing components. They have methods like "setForeground(), setBackground(), setText()" etc.
So if you want to change your component then you need to create appropriate setter method to change the properties of your class. Then in the method you save the property and simply invoke repaint() and Swing will repaint your component. So now your paintComponent() method needs to check the property you just set to do the appropriate painting.
public void setSomeProperty(Obect someProperty)
{
this.someProperty = someProperty;
repaint();
}
....
protected void paintComponent(Graphics g)
{
super.paintComponent();
// paint the board
if (someProperty != null)
// paint the property
}
I want to re-draw my screen (JForm) on button click. Due to some logic its not possible to do with repaint. Is there any other way to do so ?
When i Will click Save Pattern button. Shape should be redrawn.
If any one want to know why i cant do with paint the see this question
Painting is done by overriding one of the paint methods of a component (preferably a component that extends from JComponent and by overriding paintComponent).
One possible solution is to render output to a BufferedImage, which allows you to do offscreen rendering and which you can control and when you want to, simply use Graphics#drawImage or even JLabel to render the BufferedImage to the screen
When I use JCheckboxes or JScrollPane (applied to the main component that holds all others in order to generate a scrollable window) together with components that use
component.setBackground(new Color(R, G, B, A));
to define their background color, I am getting some obnoxious repaint() issues. Hovering over JCheckboxes activates MouseListener and the background of the JCheckbox will suddenly display a random other part of the window. This remains even when taking the mouse off the JCheckbox.
The issue disappears when using
JCheckbox.setRollOverEnabled(false);
BUT will still occur when selecting the checkbox!
The scrollpane will also not properly repaint. ONLY the parts that are outside of the visible frame will be painted several times in a row in direction of scrolling when they come back into the frame. It looks similar to that error on Windows OS when a program crashes and you can "draw" with the window on the screen because it "generates" a new window every time you move it (http://i.stack.imgur.com/L5G5Q.png).
The most interesting part is that the issue completely disappears when I use
Color.grey (or any other pre-generated color)
It also disappears when not selecting a custom background color at all.
So is there an issue with revalidate() and repaint() hidden anywhere in this? Is the use of RGBA a problem, specifically the A (= opacity) part since Color.AnyColor works?
Is the use of RGBA a problem, specifically the A (= opacity) part
Yes, Swing does not support transparent backgrounds.
Swing expects a component to be either:
opaque - which implies the component will repaint the entire background with an opaque color first before doing custom painting, or
fully transparent - in which case Swing will first paint the background of the first opaque parent component before doing custom painting.
The setOpaque(...) method is used to control the opaque property of a component.
In either case this makes sure any painting artifacts are removed and custom painting can be done properly.
If you want to use tranparency, then you need to do custom painting yourself to make sure the background is cleared.
The custom painting for the panel would be:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
panel.setOpaque(false); // background of parent will be painted first
Similar code would be required for every component that uses transparency.
Or, you can check out Background With Transparency for custom class that can be used on any component that will do the above work for you.
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.
Is they a way of adding a watermark to a JTextArea?
I suspect that you'd need to subclass JTextArea and override the paintComponent() method, drawing your background image first and calling super.paintComponent() to render the text:
public void paintComponent (Graphics g) {
g.drawImage(watermark, 0, 0, this);
super.paintComponent(g);
}
edit: as pointed out by camickr, a JTextArea is opaque, so your subclass will need to change this by calling setOpaque(false).
I doubt the suggestion given above will work. A JTextArea is opaque, so the text will paint over top of the image. So at the very least you will need to make the text area non-opague and you will then need to play with the background colors of the viewport and/or scrollpane.
If you want a reusable solution try creating an ImageBorder. The order of painting is:
a) paintComponent
b) paintBorder
c) paintChildren
So if you add the border to the text area it will paint on top of the text in a fixed location.
Or if you add the border to the viewport it will paint below the text is a floating location.
You may also consider using JXLayer which can create quite complex visual effects