I want to generate an icon with an svg icon content. For example a yellow circle with a face (svg file) in it. At the moment I have this code.
The circle is in the right position but the svg is drawn all over the JPanel and if i resize the frame the svg is added all the time.
The svg is loaded with white background and in the wrong size.
Is there a way to make the background of the svg transparent and transform the svg to the circle size?
As information: The svg file has got a transparent background (seen in adobe illustrator) but in Java its loaded white...
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import org.apache.batik.swing.JSVGCanvas;
public class IconTest extends JPanel{
public IconTest(){
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
super.paintComponent(g2d);
this.setBackground(new Color(255,255,255));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// create icon body
Ellipse2D iconBody = new Ellipse2D.Double(0, 0, 100, 100);
g2d.setPaint(Color.YELLOW);
g2d.draw(iconBody);
g2d.fill(iconBody);
// icon content
JSVGCanvas svg = new JSVGCanvas();
svg.setURI("file:/C:/Users/Linda/Desktop/smile.svg");
add(svg);
}
public static void main(String[] args) throws Exception{
JFrame frame = new JFrame("IconTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,600);
frame.setVisible(true);
IconTest i = new IconTest();
frame.add(i);
}
}
edit:
bevor transforming the window size
after transforming the window size. The SVG is added all the time with white background and it's size depends on how fast i transform the window...
Edit: You can download the svg file here
The svg is loaded with white background and in the wrong size.
I'm not 100% sure 'cause I can't test atm, but you're adding a white background with:
this.setBackground(new Color(255,255,255)); //Remove this line
So, the background is white and that's why you're seeing the svg with white background. Or change it to another color and see what happens.
What do you mean with in the wrong size?
The circle is in the right position but the svg is drawn all over the JPanel and if i resize the frame the svg is added all the time.
Well, JFrame by default has a BorderLayout and the default position when you add something without specifying where in the BorderLayout you want it is BorderLayout.CENTER and you're not adding anything else to it anywhere, so it's using the 100% size of your JPanel. Maybe you'd want to try with a different Layout Manager for example a BoxLayout or FlowLayout or maybe a GridLayout.
Another thing I saw in your code is you're adding your IconTest panel AFTER you're showing your JFrame, instead you should change it like this, once you've chosen another Layout for your JFrame.
JFrame frame = new JFrame("IconTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
IconTest i = new IconTest();
frame.add(i);
frame.setSize(600,600);
frame.setVisible(true);
Related
I have no idea what the heck is going on while I'm trying to render an image on a JPanel in a JFrame. In fact I just want an image displayed in a fixed position on my JFrame.To achieve this I have a JPanel of a fixed size (min, max, pref size set) on my JFrame. On press of a button, I add another panel to mentioned panel, having the same size. The "child" panel has an overriden paint method to draw an image. So far so good, once I press the button and add that child panel, nothing happens at all. If I then click on the empty panel, the image is drawn as it should be, not overflowing the bounds of the child panel. However, all other components width increases drastically, stretching them out of the JFrames bounds. One would think that at least a scrollbar would appear, but no, the components are then out of reach. I'm attaching two screenshots displaying that very logic behavior.
The code is as follows:
void setPoster(BufferedImage poster) {
ImagePanel ip = new ImagePanel(poster);
ip.setSize(new Dimension(222, 327));
panelPoster.add(ip);
ip.setSize(new Dimension(222, 327));
}
Inside ImagePanel:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
System.out.println("Paiting imagepanel with size " + getSize());
}
Before screenshot:
After screenshot:
Could anyone enlighten me on what could possibly occur here?
I fixed the strange resizing by setting the layout to null on both the JFrame and the JPanel inside my tabbed pane.
setLayout(null);
jPanel4.setLayout(null);
Anyway, that's not needed when using the JLabel instead of the JPanel to hold the image.
However, my ImagePanel would not draw the image anymore, so I replaced it by a JLabel which draws the image just fine:
void setPoster(BufferedImage poster) {
JLabel imageLabel = new JLabel(new ImageIcon(poster));
panelPoster.add(imageLabel);
imageLabel.setSize(new Dimension(222, 327));
}
Note that without setting the size of the JLabel, it won't display anything.
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.
I am new to making GUIs so I decided to try the the windows builder for eclipse, and while great I do have some doubts. I have been searching but I cannot seen to find a good way to add a background image to my "menu". For example I tried this:
public Menu() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(50, 50, 300, 250); //Dimensiones
contentPane = new JPanel() { //Imagen de Fondo
public void paintComponent(Graphics g) {
Image img = Toolkit.getDefaultToolkit().getImage(
Menu.class.getResource("/imgs/rotom.jpg"));
g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
}
};
And adding the following classes:
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
But to no avail the window remains with its dull grey color, so far my code is just the standard one WindowsBuilder cooks for you plus 4 buttons but I doubt they're of importance here. Shouldn't the code I added override the paintComponent() method of the jPanel and draw the image in it?
The class for the menu is in a package within my project and the image is within a imgs package is within the same project as well.
Thanks a lot in advance.
A simple method, if you're not interested in resizing the background image or applying any effects is to use a JLabel...
BufferedImage bg = ImageIO.read(Menu.class.getResource("/imgs/rotom.jpg"));
JLabel label = new JLabel(new ImageIcon(bg));
setContentPane(label);
setLayout(...);
There are limitations to this approach (beyond scaling), in that the preferred size of the label will always be that of the image and never take into account it's content. This is both good and bad.
The other approach, which you seem to be using, is to use a specialised component
public class BackgroundPane extends JPanel {
private BufferedImage img;
public BackgroundPane(BufferedImage img) {
this.img = img;
}
#Override
public Dimension getPreferredSize() {
return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, this);
}
}
You should avoid trying to perform any task in the paintComponent method which may take time to complete as paintComponent may be called often and usually in quick succession....
Getting the image to scale when the component is resized is an entire question into of it self, for some ideas, you could take a look at...
Java: maintaining aspect ratio of JPanel background image
Java: JPanel background not scaling
Quality of Image after resize very low -- Java
Reading/Loading images
Oh, and, you should avoid extending directly from top level containers, like JFrame, they reduce the reusability for your components and lock you into a single container
I have created a custom JPanel class called ImagePanel. I override the paintComponent method like this...
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0,0, null);
}
The purpose of the custom panel is to simply draw an image.
In my JFrame, I create a ScollPane that is added to the JFrame. When I created the ScrollPane though, I pass in the instance of my imagePanel, like this...
ip = new ImagePanel();
JScrollPane jsp = new JScrollPane(ip);
this.add(jsp);
Now all I want as an easy to use way of using the scroll bars to scroll over my image. Right now the image is very large and scrollbars do not appear. I use the policy to make them visible, but the handles to the scrollbars are not there.
Does anyone know an easy way to do this?
Try with JPanel#setPreferredSize() that will force the JScrollPane to show the scroll bar if needed.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0,0, null);
// set the size of the panel based on image size
setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
}
EDIT
Setting setPreferredSize() inside overridden paintComponent() is not a good way.
You can do it in a simpler way using JLabel as suggested by #mKorbel. For more info have a look at the comments below.
BufferedImage image = ...
JLabel label = new JLabel(new ImageIcon(image)); // set the icon
JScrollPane jsp = new JScrollPane(label);
Screenshot:
i found this link.. LINK what i want is there's a JPanel that has a background and another JPanel with half the size of the first JPanel but with an image that is transparent and with a face or a ball at the middle.. :) just like the screenshot from the link.. is that possible to code in java? :) im just thinking it like for web programming. just a sort of DIV's to have that but i dont know in java.. :) sorry for bad english.. :D i have this as a background..
package waterKing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class Main extends JFrame {
MainData data = new MainData();
public static void main(String[] args) {
Main frmMain = new Main();
frmMain.setExtendedState(Frame.MAXIMIZED_BOTH);
frmMain.setVisible(true);
}
public Main() {
data.tk = getToolkit();
data.d = data.tk.getScreenSize();
data.jP = new JPanel() {
protected void paintComponent(Graphics g) {
data.e = getSize();
data.iI = new ImageIcon("images/mainBG.png").getImage();
g.drawImage(data.iI,0, 0, data.d.width, data.d.height, null);
super.paintComponent(g);
}
};
data.jP.setOpaque(false);
data.jSp = new JScrollPane(data.jP);
data.jB = new JButton("EXIT");
data.jB.setBounds(10,10,200,40);
data.jB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
data.jP.setLayout(null);
data.jP.add(data.jB);
this.setTitle("Water King Inventory System");
this.setUndecorated(true);
this.getContentPane();
this.add(data.jSp);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
}
}
i dont know how to add another JPanel to show in the middle with this background
i dont know how to add another JPanel to show in the middle with this background
Its just like adding components to a panel. You need to use a layout manager and then the component will be positioned properly based on the rules of the layout manager. In your case you can set the layout manager of the background panel to be a BorderLayout. Then you can add a JLabel with the appropriate Icon to the center of the BorderLayout.
You will need to set the preferred size (or override the getPreferredSize() method of your panel since you add it to a scroll pane. Scrollbars will only appear when the preferred size of the panel is greater than the size of the scroll pane.
You should not be reading the image in your paintComponent() method since this method is called multiple times.
You should not be using the "screen size" to determine the width/height of the image because the frame will contain a border. You need to use the size of the panel.
Get rid of all the setBounds() code. Learn to use layout managers.
For a general purpose background panel that takes into account most of the suggestions made here check out Background Panel.