Adding Icon to JButton without changing its size - java

I am trying to add an Icon to the JButton
When I try to do this my Layout Manager (I use GridBagLayout) resizes the button and makes it larger by the size of the icon.
Is there a way to avoid this?

You could try JButton#setPreferedSize(...)
Or you could override the paintComponent method:
JButton testButton = new JButton() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
If you want to do this with multiple buttons, it would be better to make a class for it ofcourse, something like:
class ImageButton extends JButton {
private final Image image;
public ImageButton(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//drawing logic here
}
}

I had the same problem. Do these things:
Resize your image to fit the button with an image manipulating program.
use setMininumSize() and set the minimum size you want.
This will probably fix your problem.

Related

JInternalFrame repainting issue

Below code is my view where I get display a streaming camera. Controller handles sets the image and repaints the JInternalFrame. I have an issue with this because the camera image covers the whole JInternalFrame even the title bar. I tried using JPanel but I had problems getting the image on the JPanel because I extend JInternalFrame.
public class CameraView extends JInternalFrame{
private BufferedImage image;
public CameraView(){
super("Camera", false,false,false, false);
setSize(500,500);
setLocation(200,200);
}
#Override
public void paint(Graphics g){
g.drawImage(image, 0, 0, null);
}
public void setImage(BufferedImage image){
this.image = image;
}
}
This is what it looks like. No title bar.
You're overriding the paint method of the frame. This paint method is what draws the title bar.
You should create a second class that extends JComponent, override the paint method on that class, and then add an instance of it to your frame.
Something like:
public class CameraView extends JInternalFrame{
private BufferedImage image;
public CameraView(){
super("Camera", false,false,false, false);
setLocation(200,200);
add(new JComponent() {
{
setSize(500, 500); // size of the image
}
#Override
public void paint(Graphics g){
g.drawImage(image, 0, 0, null);
}
});
pack();
}
public void setImage(BufferedImage image){
this.image = image;
}
}
You could also have the paint method call super.paint(g); but the way you have it set up now, your image will overlay the title bar.
Also, calling super("Camera", false,false,false, false); is the same as calling super("Camera"). The defaults are false.

Drawing on JTextPane in concrete place

Let's say we have a JTextPane and its size is set to A4 paper format size. Orientation of the page is vertical. Let's divide our page into three equal parts. When I write something in one part (in random place) I want that inserted text would be drawn on two remaining parts of the page in such a place that if I fold my page on three, all three texts will be in the same place.
Is ther any way to achieve this?
This should look like this:
I'm not sure I understood what you want, so please correct me if I misunderstood. You can save the image of your textPane when displayed, and draw that image reverted or normally as needed. See below:
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame mainFrame = new JFrame("test");
mainFrame.setSize(300, 100);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//layout to make every part the same size
Container pane = mainFrame.getContentPane();
pane.setLayout(new GridLayout(3,1));
//create the elements
JTextPane source = new Source();
final JPanel copy = new Copy();
final JPanel revertedCopy = new RevertedCopy();
//add the elements
pane.add(source);
pane.add(revertedCopy);
pane.add(copy);
//This is just to display the splitting lines
source.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.BLACK));
//this is just to repaint the other panels when image changes
source.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals("drawing")) {
copy.repaint();
revertedCopy.repaint();
}
}
});
mainFrame.setVisible(true);
}
});
}
static BufferedImage image;
static class Source extends JTextPane {
#Override
public void paint(Graphics g) {
super.paint(g);
//we edit the image each time the textPane is repainted
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_3BYTE_BGR);
boolean caretVisible = getCaret().isVisible(), selectionVisible = getCaret().isSelectionVisible();
if(caretVisible) getCaret().setVisible(false);
if(selectionVisible) getCaret().setSelectionVisible(false);
super.paint(image.createGraphics());
if(caretVisible) getCaret().setVisible(true);
if(selectionVisible) getCaret().setSelectionVisible(true);
//we let the copies know about the changes
firePropertyChange("drawing", null, image);
}
}
static class Copy extends JPanel {
#Override
public void paint(Graphics g) {
super.paint(g);
//we just draw the image
if(image!=null) g.drawImage(image, 0, 0, this);
}
}
static class RevertedCopy extends JPanel {
#Override
public void paint(Graphics g) {
super.paint(g);
//we just draw the image reverted
if(image!=null) g.drawImage(image, 0, image.getHeight(), image.getWidth(), -image.getHeight(), this);
}
}
}
A DocumentListener is needed . On changeEvent the text should be copied (till the caret position) and appened adjusting line gaps (for overflow of text). CaretPositionshould be keep into the original position. What happens when text overflows the first part should be taken care of.
You should replace root view with your own one. View has method
public void paint(Graphics g, Shape allocation)
You override the method and call super.paint(g, allocation) 3 times translating Graphics vertically.
Also you should override getPreferredSpan() to triple original vertical span.

Getting wrong output in adding an image in JFrame

My problem is that when I create or draw an image in JFrame by using
public void paint(Graphics g)
{}
Method I am getting a black screen instead of the image the problem code snippet is
ImageIcon i=new ImageIcon("logo.png);
Image im=i.getImage();
public void paint(Graphics g)
{
g=getGraphics();
}
Please suggest me an alternative method or solution to my problem
Thanks in advance
Would you consider using a JPanel and overriding the paintComponent method? Something like this:
BufferedImage image = ... //i'll leave this blank since there are several ways to get a bufferedimage. I'll leave an eg: ImageIO.read(new File("/path/to/image"));
JPanel pane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}};
and then adding the panel to your frame. You can do the same with the container in the JFrame. The logic is simillar.

Having images as background of JPanel

I am new in Java and I am currently creating a game with graphics. I have this class that extends from JFrame. In this class, I have many JPanels that needs an image as background. As I know, to be able to paint images in the JPanel, I need to have a separate class that extends from JPanel and that class's paintComponent method will do the work. But I don't want to make separate classes for each JPanel, I have too many of them; and with the fact that I am only concerned with the background. How can I do this? is it with an anonymous inner class? How?
For better understanding I provided some code:
public GUI extends JFrame {
private JPanel x;
...
public GUI() {
x = new JPanel();
// put an image background to x
}
Why not make a single class that takes a Image??
public class ImagePane extends JPanel {
private Image image;
public ImagePane(Image image) {
this.image = image;
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(0, 0) : new Dimension(image.getWidth(this), image.getHeight(this));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
}
}
You would even provide hints about where it should be painted.
This way, you could simply create an instance when ever you needed it
Updated
The other question is, why?
You could just use a JLabel which will paint the icon for you without any additional work...
See How to use labels for more details...
This is actually a bad idea, as JLabel does NOT use it's child components when calculating it's preferred size, it only uses the size of the image and the text properties when determining it's preferred size, this can result in the component been sized incorrectly
You don't have to make another class for it? You could just do:
x = new JPanel(){
public void paintComponent(Graphics g){
super.paintComponent(g);
//draw background image
}
};
You can do this in single line:
panelInstance.add(new JLabel(new ImageIcon(ImageIO.read(new File("Image URL")))));
I hope it will work for you.

Overlay a JButton over JLabel in Java Swing?

Is it possible to overlay a Button over a Label in Swing?
For example, if have a JLabel with image and no text, and i want to overlay my button over this JLabel. Label is defined something like:
myLabel = new javax.swing.JLabel(new ImageIcon( myPicture ));
If not, then any ideas how can i realize this, thank you.
EDIT: Actually i read about adding JPanel to a JLabel, when i add a Panel with button layout, it compiles fine but nothing is visible, just the JLabel with image
UPDATE: As suggested by #paranoid-android, somehow i have solved my problem. However i still have to know how can i customize the positions of components overlayed on top of JLabel as i don't have much control (probably because normally i use netbeans for drawing layouts, and this would require hard coding).
Something Like this worked:
ImagePanel(Image image, int id) {
this.image = image;
this.tile = false;
JButton backButton = new JButton();
JButton nextButton = new JButton();
backButton.setText(" BACK ");
nextButton.setText(" NEXT ");
add(backButton);
add(nextButton);
};
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
You can do it using a JLayeredPane, although if I understand correctly, the absolute best way to do that would be to override paintComponent:
// as part of your JPanel
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(background, 0, 0, this);
}
Then you can add components to the panel as you like, without the need for the JLabel.
You can overlap the button and the label, but you would have to do this with a Fixed Layout. You might be able to pull if off with a gridBagLayout, but I doubt it.
Here is more on what you will need.
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
Thanks rtheunissen.
That did the trick for me.
I modified it a little.
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
try {
ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource("img/lake.jpeg"));
g.drawImage(icon.getImage(),0,0,this);
} catch (Exception ex) {
Logger.getLogger(InfoPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}

Categories