-1

I have this inner class:

private class Plats extends JComponent{
    private String namn;
    Plats(int x, int y, String n){
        namn=n;
        setBounds(x-10, y-10, 150, 40);
        setPreferredSize(new Dimension(20, 20));
        setMinimumSize(new Dimension(20, 20));
        setMaximumSize(new Dimension(20, 20));
    }
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        g.fillOval(0, 0, 20, 20);
        g.setColor(Color.BLACK);
        g.setFont(font);
        g.drawString(namn, 0, 34);
    }
    public boolean contains(int x, int y){
        return x<20 && x>0 && y<20 && y>0;
    }
}

I want to set the bounds of the component to the width of the string that the constructor gets, but I can only get it to work if I do it inside the paintComponent method since I need the graphics object. It feels wrong to do it in the paintComponent method since every time the component has to be repainted it will set the bounds again and I only want to do it once when it is created.

Suggestions how I can solve this? Or should I just do it in the paintComponent anyway?, it works but I doesnt feel like a nice solution :( ?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • A component should not set it's own bounds! Leave it to the layout. – Andrew Thompson Apr 17 '12 at 16:03
  • *"I want to set the bounds of the component to the width of the string that the constructor gets"* As an aside. `JLabel` (with layouts) has that built in. Why are you trying to reinvent the lever? – Andrew Thompson Apr 17 '12 at 16:08

3 Answers3

2

Please don't use AbsoluteLayout, only if is there really important reason, use proper LayoutManager,

your JComponent should be returns PreferredSize (notice PreferredSize isnot accepted by all of standard or custom LayoutManagers) to its parent or container, for example

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ComponentEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class CustomComponent extends JFrame {

    private static final long serialVersionUID = 1L;

    public CustomComponent() {
        setTitle("Custom Component Graphics2D");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void display() {
        CustomComponents cc = new CustomComponents();
        /*cc.addComponentListener(new java.awt.event.ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent event) {
                setSize(Math.min(getPreferredSize().width, getWidth()),
                        Math.min(getPreferredSize().height, getHeight()));
            }
        });*/
        add(cc, BorderLayout.CENTER);

        CustomComponents cc1 = new CustomComponents();
        add(cc1, BorderLayout.EAST);

        pack();
        // enforces the minimum size of both frame and component
        setMinimumSize(getSize());
        //setMaximumSize(getMaximumSize());
        setVisible(true);

    }

    public static void main(String[] args) {
        CustomComponent main = new CustomComponent();
        main.display();
    }
}

class CustomComponents extends JComponent {

    private static final long serialVersionUID = 1L;

    @Override
    public Dimension getMinimumSize() {
        return new Dimension(100, 100);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 300);
    }

    @Override
    public Dimension getMaximumSize() {
        return new Dimension(800, 600);
    }

    @Override
    public void paintComponent(Graphics g) {
        int margin = 10;
        Dimension dim = getSize();
        super.paintComponent(g);
        g.setColor(Color.red);
        g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2);
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Im so sorry but I really have no idea what you're trying to tell me. I dont want a LayoutManager because I need to place them exactly where I click with my mouse –  Apr 17 '12 at 15:46
  • @Ceilingbat `I need to place them exactly where I click with my mouse` finally some clear info :-), please edit your question with this one and another if exists.... – mKorbel Apr 17 '12 at 15:55
  • *"I need to place them exactly where I click with my mouse"* Use a (custom) `WhereverIDropThisSh*t` ***layout.*** Positioning logic should not be inside a component, it is just the wrong place for it. – Andrew Thompson Apr 17 '12 at 16:05
  • I think that is a little too hard for me, Im currently taking my second programming course at university, but thanks for pointing that out –  Apr 17 '12 at 16:09
  • *"I think that is a little too hard for me"* What is? Programming - drop it; logic, drop university; communicating your point to people; become a hermit. – Andrew Thompson Apr 17 '12 at 16:37
1

Even without a graphics context, you can use either TextLayout or FontRenderContext to find the bounds; the two are compared here. Because you extend JComponent, your component should override the getXxxSize() methods, as shown in mKorbel's answer.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
0

You can use the Font#getStringBounds(String str, FontRenderContext frc) to get a bounding rectangle of the string in the form of the said Font. From there you can return the width and height.

Font Java 1.6 API

  • To do that I would need to get the graphics object and then get the FontRenderContext, I don't think I can get the graphics object outside of the paintComponent method –  Apr 17 '12 at 16:03