I have a class MyPanel that extends JPanel.
MyPanel is a child panel: his size is dinamically calculated by the LayoutManager of his parent.
The problem is that I need MyPanel to be notified as soon as the LayoutManager of his parent calculates his size.
It needs to be notified because I need to initialize some variables according to the panel's size.
If I call getSize() in the MyPanel constructor i get (0,0) because the panel is not "ready".
When should i call getSize()?
I'd like to have something like this:
/** Lays out the panel and sets his size according to his layout */
#Override
public void onReady() {
System.out.println(getSize()); //output is (0,0);
super.onReady();
System.out.println(getSize()); //output is (600,500);
//here i can initialize my variables
}
Is there something similar? Maybe doLayout()?
The only way i could find is calling getSize() in the paintComponent() method... it surely works because the panel is surely displayed when paintComponent() is called but I can't do this because i need to initialize some variables as soon as i know the panel size... but only once! paintComponent() will be called several times...
It's ComponentListener.componentResized().
Best way is to use a ComponentListener.
See ComponentListener.componentResized(ComponentEvent)
Related
I need to have a JFrame where the upper part is a drawing made by paint() and the lower part is a panel composed of JLabel, JTextField and JButton components.
Is this possible? How am I supposed to do this?
I need to have a Jframe where the upper part is a drawing made by paint() and the lower part is a panel composed of JLabel, JTextField and JButtons.
There is no conflict on what you want to do. You can have a main JPanel with 2 sub panels. One on the top for your drawings, the other at the bottom for containing your JComponents such as JButtons:
The structure in code may look like this:
class MainPanel extends JPanel{
private DrawingSpace drawingSpace; //Customized JPanel for drawing
private JPanel subPanel;
public MainPanel(){
setPreferredSize(new Dimension(400, 400));
initComponents();
}
private void initComponents(){
drawingSpace = new DrawingSpace();
subPanel = new JPanel();
}
}
You can have a customized JPanel as follows (this is optional):
class DrawingSpace extends JPanel
{
public DrawingSpace(){
//Set size..etc
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//perform your drawings here..
}
}
After the implementations for the JPanels, you can just add an instance of MainPanel to the JFrame:
JFrame frame = new JFrame();
frame.add(new MainPanel());
//Other codes for JFrame not shown here
The soulution suggested by user3437460 (use a JPanel for the upper part, and override the painting methods in that JPanel) is the preferrable way to solve this.
However as you asked for a solution to directly paint the upper part (which is not advised, but there are solutions):
A (nasty) workaround for the question would be overriding the necessary paint method of JFrame, draw your upper part, translate the graphics context by some 100 pixels and call inherited paint methods to draw the bottom part. (Note that you'll have layout manager issues, as the layout manager won't see the 100px height of the upper part. However, if you're using an absolute layout, it could work. Hacks, hacks hacks :(
Another super-hack is to actually make the lower part big enough (if you use absolute layout, position your lower part at y=100px). Then add your own GlassPane and render the content for the upper part (or anywhere) on the glassPane.
Of course you can create a dedicated layout manager, which leaves the top 100 px part empty. Use that layout manager, and then you get some empty space on the top, which you can draw on.
I think now you can agree that the problem is rather "how to put a custom drawn component on the top of the window", which is solved by putting a custom drawn JPanel on the top of the window. Keep it easy! Peace!
ps: override paintComponent() instead of paint() of JPanel. See bottom of http://www.oracle.com/technetwork/java/painting-140037.html
For the painting portion, create a JPanel (or other paintable component) and override the paint method. Use a second JPanel and place all of your other components in that.
From there, check out how to do layout management at https://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#set
The simplest way to do this is to use GridLayout, with the painted panel on the top half and the components panel on the bottom half.
This is probably a very basic question, but I could't find anything about it online.
I'm working in Java swing and have a JPanel with a null Layout Manager (ie using absolute positioning). The JPanel is filling a space in the JFrame so that its size will change when the JFrame is resized. Within this JPanel, I have a number of other components that I have placed using Component.setBounds(). I would like one of these components to be set relative to the bottom of the JPanel, so that when the containing JPanel resizes, the smaller JComponent stays stuck to the bottom of the container.
I have tried to do this by overriding the getLocation() or getBounds() methods to reference the container height, but neither of these seemed to work the way overriding getPreferredSize() would, even after calling revalidate() and repaint(). Unfortunately, using another layout manager like BorderLayout is not an option here.
Is there a way to do something like this? Am I missing something obvious? If not, is there a way to listen for changes in the container's height and re-call .setBounds()?
Try listening to the resize event of the panel:
panel.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent arg0) {
component.setBounds(...);
}
});
You can reference panel.getBounds from withing this method and set your components bounds accordingly.
To do this you can add a component listener to your JFrame.
addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent e){
//Do stuff here
}
});
Inside the component listener you can change the sizes and locations of anything you would like to. To stick them to the bottom simply get the size of the JFrame and subtract a specific amount and set that as the y location for what you want stuck to the bottom.
I have a Panel which needs to know its size inside the constructor:
class Panneau extends JPanel {
public Panneau() {
super();
new Map(getSize());
}
}
Unfortunately, the size doesn’t seem to have been initialized yet and getSize() returns a Dimension with 0 for height and width. How to get the future Dimension notwithstanding?
If you want to work with the size of a component, you need to do so when the component is actually in use in a well-formed user interface.
One of the ways to do that, is to add a ComponentListener to the code and implement the componentResized method, which will be called whenever the component's size changes. There you can work with the latest accurate value for the component's size by using getSize().
I have a simple drawing program, I set my Jframe's size with the following code:
frame.setSize(900, 700);
However, when user change the size of the window, white area to draw, still remain same size therefore, user is not able to draw eventhough he enlarge the window.
http://forum.codecall.net/java-tutorials/31180-java-mini-paint-program.html this is where I start from. I extended class "PadDraw" and wrote most of my code to there, in my other java file, I only create a frame, then I create "PadDraw" object, I crated a container and then added object to the frame's container: content.add(drawPad, BorderLayout.CENTER);
I changed my code:
public class PadDraw extends JComponent implements ActionListener, ItemListener, ComponentListener{
public synchronized void addComponentListener(ComponentListener l) {};
.
.
.
.
And I added unimplemented methods, and the "componentResized" is:
public void componentResized(ComponentEvent arg0) {
System.out.println("Changed ????");
}
But when I changed the window's size, nothing happens.
One thougt: When I added componentlistener to my other file instead of drawPad, componentResized method flags, but because I have created drawPad object before this event occured, I can't change the size =/
Thanks
Hopefully you're not drawing directly on the JFrame but rather in a JPanel or JComponent that's been added to the JFrame's contentPane. If it has been added BorderLayout.CENTER, then it should expand and contract as the JFrame expands and contracts. Things get a little trickier if you're drawing on a BufferedImage as you'll have to use a ComponentListener to see when the component that holds the BufferedImage changes size, and when it does, change the size of the BufferedImage without losing the drawing that's already there.
If this answer is not helpful enough, consider giving us more specific information about your current problem and your current program.
In the program that you link to, you're drawing on an Image object whose size is set the first time paint is called. What you'll want to do is to add a ComponentListener to the PadDraw object in its own constructer, and in the ComponentListener's componentResized method, resize your image using the PadDraw's new height and width. I would only do this however if the new size is larger than the old size. You would also then want to redraw the old image on the new before setting the image variable = to the new image. Then call repaint.
I want my panel to fit the frame when I show/hide fields. How could I notify to the parent frame to revalidate?
I thought about pass the frame to my panel's constructor, but I think may have a way this is already done. I remember that there was a protected attribute in JPanel, but there isn't.. maybe i remembering the wrong component.
I need show/hide some fields of my
panel, and I want the panel to fit the
frame.
You mean like a summary/details view and you want the frame size to change? Then try:
SwingUtilities.windowForComponent(...).pack();
you could override the addNotify in the panel into something:
public void addNotify() {
getParent().revalidate();
repaint();
super.addNotify();
}
Not sure if that's what you mean though.
SwingUtilities.getRoot(this).invalidate();