I would like to have a JPanel transparent or fully invisible (not like panel.setVisible(false) but more something like opacity = 0.0f) which will then be put into a JLayeredPane, to make the bottom layer visible.
You know ask why. I need this to use the build in Layouts like BorderLayout and so on because I dont want to make my own layout and so on.
What I then tried was first of all the Implementation of a transparent JPanel which was more or less easy by doing just this:
public class ClearPanel extends JPanel {
private static final long serialVersionUID = 706731555521208974L;
private float opacity = 0.0f;
private Shape shape = null;
public ClearPanel() {
setBackground(new Color(0,0,0,0));
setOpaque(false);
}
public ClearPanel(float opacity) {
setOpaque(false);
setOpacity(opacity);
}
public ClearPanel(float opacity, Shape shape) {
setOpaque(false);
setOpacity(opacity);
setShape(shape);
}
// Here usually are some random getters and setters
#Override
public void paintComponent(Graphics go) {
Graphics2D g = (Graphics2D) go;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if(shape == null) shape = g.getClipBounds();
g.setColor(new Color(getBackground().getRed(), getBackground().getGreen(), getBackground().getBlue(), 255*opacity));
g.fill(shape);
}
}
So what this does is usually creating a more or less transparent Version of the JPanel. And it also works if don't use a layout but fixed Positions and Sizes but when you program something bigger it would be way easier to use available solutions.
The problem comes now:
When I try to use this in a JLayeredPane with the possibility to see the bottom layer, nothing happens, although it definetly should I need this because I want a bottom panel with a background Image and then I want some stuff ABOVE that panel. And I thought, ok I know Layers from Gimp, maybe Java offers this, so thats why I think that JLayeredPane could help.
Do you know a possibility to make the bottomlayers shine trough an other layer although you use a fixed layout or do you think, I will need to make my own layout or use public void paint(Graphics g) of JFrame to paint them step by step ?
Thanks in advance
PS: Sry for my English but after one day of try and error I can't write anything "perfect" any more...
Related
I'm trying to make a simple application to draw shapes to a panel in a jFrame. The GUI is a NetBeans generated jFrame. The application has three panels. the first two hold button groups to select the shape and a color. There's a button to draw the shape to the third panel once the selections are made.
What the GUI looks like
Unfortunately I'm having no love and can't make it work. For now I just want to get the button to draw a shape then I'll add the button functionality. Here's the code I have so far.
private void btnDrawShapeActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Draw shape = new Draw();
pnlDrawPad.add(shape); //pnlDrawPad is the name of the jPanel
shape.drawing();
}
import javax.swing.*;
import java.awt.*;
public class Draw extends JPanel{
public Draw(){
super();
}
public void drawing(){
repaint();
}
//#Override <-- gives error "method does not override or implement a method from a supertype"
public void paintCompnent(Graphics g){
super.paintComponent(g);
g.setColor(Color.RED);
g.drawString("Hello World!",40,30);
}
}
When I click the "Draw Shape" button nothing happens. I've been searching for a couple days now and am not finding the answer. Actually, its making me more confused as to what to do.
How to deal with this?
Don't keep creating new panels for each shape.
Instead you need a single panel with an ArrayList of objects you want to paint. Then you customize the paintComponent(...) method of the panel to iterate through all the objects in the panel and paint them.
So you button will just add another object to the ArrayList and then invoke repaint() on the panel.
Check out Custom Painting Approaches. The DrawOnComponent example shows how to paint a Rectangle objects from an ArrayList to get you started.
I found that with NetBeans you don't need to Override the paintComponents() method. Since all the GUI stuff is done when you design it, you merely need to add the drawings to the panel or what ever you need to do. I found you that by declaring and instantiating a 2D graphics object then drawing it to the place you want.
private void btnDrawShapeActionPerformed(java.awt.event.ActionEvent evt) {
int centerX;
int centerY;
Graphics2D drawFx = (Graphics2D)pnlDrawPad.getGraphics();
drawFx.setColor(Color.ORANGE);
centerX = (int)(458*Math.random());
centerY = (int)(440*Math.random());
drawFx.fillOval(centerX-50, centerY-50, 100, 100);
drawFx.dispose();
}
Worked like a charm so now every time I push the draw shape button it draws a shape to the panel in a different location every time. I've since put in the radio button functionality to change shape color and fill and added a button to clear the screen.
Not sure if this is the ideal way to do it but for this stupid simple little program it works well enough and I'm done stressing over it.
The goal here is that I can click a color and shape, then two points on the figuresPanel. That colored shape is filled in on the figuresPanel, and I can add shapes on top of each other etc. I also need the current date to be displayed in the corner of the figuresPanel, on top of all the painted shapes. I am able to create shapes (though they always cover the date) no problem, but whenever I resize or minimize the window, all the painted shapes disappear. I've tried implementing quite a few different methods from Graphics (update, paint, redraw, etc.) and haven't found one that corrects this issue. I thought paintComponent() would take care of all that, but apparently not. Feel free to point out anything that could be implemented in a better way, always happy to learn something new.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawFigures();
figuresPanel.add(dateLabel, c);
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(800, 600));
}
private void addFigure(Figure figure) {
figureList.add(figure);
listArea.append(figure.toString() + "\n");
figure.fill(getGraphics());
}
private void drawFigures() {
for (Figure f : figureList) {
f.fill(getGraphics());
}
}
I would suggest a few things that might help you.
In your method drawFigures() instead of using getGraphics(), why don't you pass the instance of Graphics in paintComponentMethod as a parameter to the method and use it to draw the object. This will make sure that you are drawing on the same instance of the Graphics that you are using to paint.
In your method addFigure(Figure figure) I would suggest you remove the line figure.fill(getGraphics());, to draw the object completely. Instead in your mouseClicked(MouseEvent event) method after your switch statement insert:
revalidate();
repaint();
This should actually take care of the drawing of the objects are done exactly on the same Graphics object that is being used to display the components.
I hope that this shall be helpful.
I am currently trying to make it possible for a JPanel to be zoomed in. My idea is pretty much as follows :
I have a JPanel (custom with overriden paintComponent etc.) that I place inside my JScrollPane.
What I do to zoom in is to scale up my JPanel using the following code (overriding the paint method)
#Override
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
if (m_hasBeenScaled)
{
m_transform.scale(m_zoomValue, m_zoomValue);
g2.setTransform(m_transform);
m_transform = new AffineTransform();
}
super.paint(g);
}
This works well, however my JScrollPane doesn't display scrollbars as I scale to bigger dimensions. How do I make the JScrollPane respond to this scale up of my JPanel ?
Here's the code I use to create both my JPanel and JScrollPan (Grid is my class extending JPanel):
m_gridPanel = new Grid();
m_gridContainer = new JScrollPane(m_gridPanel);
m_gridContainer.setPreferredSize(new Dimension(605, 605));
The size of the component will be affected by the zoom factor as well, to that end, setting the preferredSize to a "static" value makes no sense, instead, you should be overriding the getPreferredSize and adjusting the size returned by applying the zoom factor to it as well.
Zooming a component is much more complex than changing the transform, you should be translating the mouse events as well, see How to add MouseListener to item on Java Swing Canvas for example.
Ok I'm wondering why the code below will not display the JLabel.
MyPanel is getting added correctly to a JFrame and everything because it all displays but will not draw the JLabel. Any help is appreciated.
public class MyPanel extends JPanel {
private Root root;
...
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
root.paint(g2);
}
}
class Root {
private Node1 node1;
...
public void paint(Graphics g) {
node1.paint(g);
}
}
class Node1 {
...
public void paint(Graphics g) {
JLabel jtp = new JLabel();
jtp.setLocation((int) x, (int) y);
jtp.setSize((int) width, (int) height);
jtp.setLocation(40, 40);
jtp.setSize(40, 40);
jtp.setText("Hello world");
//jtp.setVisible(true);
jtp.paint(g);
}
}
I suggest that you don't add Components to a Container in a paint method as 1) you do not have absolute control when or even if a paint method will be called and 2) paint and paintComponent have to be as blazing fast as possible, and this is not the time or place to update a GUI. 3) Since paint is often called many times, you will be adding components many times to your container, and all out of your direct control.
Also, while you're adding a component into Root (whatever Root is since it doesn't extend JComponent, JPanel, or similar) in the paint method, the Root object is never added to anything else that I can tell, and so it makes sense that nothing "added" to a component that is not added eventually to a top-level window will be visible.
Bottom line: I think you need a gui re-design as your solution. If you tell us more about it we can help you with it. Next we'll need to talk about use of layout managers and why setting absolute position and sizes of components is usually frowned on.
If anything I say is confusing, please ask for clarification, or if anything is wrong, please help me correct it!
You should not create your JLabel inside the paint method - instead, create it once when initializing your MyPanel. Your label is kind of a renderer component for your nodes, which in principle is a good thing. You may look how the renderers for JTable, JList, JTree work.
In your case, don't set the location of your label (it does not change anything, since it's paint-method expects its graphics object to be oriented by its own upper left corner), instead translate the Graphics-context:
Graphics copy = g.create((int)x, (int)y, (int)width, (int)height);
jtp.paint(copy);
(Graphics2D has some more fancy methods for shifting, rotating, scaling the context, too.)
Other than this, I don't see any problems. Make sure your Node1.paint() method gets actually called by putting some System.out.println() in there.
I need to make an image map using Swing that displays a background image, and then when the mouse hovers over (or clicks) specific hotspots, I need to pop up a 'zoomed-in' image and have it display.
I was thinking of extending JPanel to include an image reference and have that drawn thru the paintComponent(g) method. This part I have done so far, and here's the code:
public class ImagePanel extends JPanel
{
private static final long serialVersionUID = 1L;
private Image image;
public ImagePanel(Image image)
{
setImage(image);
}
public void setImage(Image newImage)
{
image = newImage;
}
#Override
public void paintComponent(Graphics g)
{
Dimension size = getSize();
g.drawImage(image, 0, 0, size.width, size.height, this);
}
Could anyone recommend how I might listen for / respond to mouse clicks over defined hot-spots? Could someone additionally recommend a method for displaying the pop-ups? My gut reaction was to extend JPopupMenu to have it display an image, similar to the above code.
Thanks for any help!
To listen to the mouse clicks implement the MouseListener interface, and add it to your panel. Then when the click is recieved you can use a JPopupMenu as you suggested, or you could even use a glass pane to show the zoomed in image.
I'm guessing you want to achieve something similar to this post by Joshua Marinacci, he has also posted the source here, I would take a look at that.
I would probably:
create some instance of Shape that represents each of your hotspots (could be a plain boring old Rectangle, or see GeneralPath if you need to create fancy shapes)
register a MouseListener which iterates through each of the Shapes and calls its contains() method to see if the clicked coordinate is inside the hotspot in question