Question:
I want to create animation in a frame that can be manipulated. Create class AnimatedComponent
:
class AnimatedComponent extends JComponent
{
private static final long serialVersionUID = 1L;
public AnimatedComponent()
{
Timer timer = new Timer( 30, action -> repaint() );
timer.start();
}
@Override public Dimension getPreferredSize()
{
return new Dimension( 300, 200 );
}
@Override public void paintComponent( Graphics g )
{
// animation
}
}
In the frame, I will inject an instance of the AnimatedComponent
class and other components that will affect how it is displayed:
class AnimatedFrame extends JFrame
{
private static final long serialVersionUID = 1L;
private AnimatedComponent animatedComponent = new AnimatedComponent();
private JCheckBox check1 = new JCheckBox("check1");
private JCheckBox check2 = new JCheckBox("check2");
private JSlider slider1 = new JSlider( 0, 200, 50 );
private JSlider slider2 = new JSlider( 0, 200, 50 );
private JSlider slider3 = new JSlider( 0, 200, 50 );
public AnimatedFrame()
{
setLayout( new GridBagLayout() );
add( animatedComponent, new GBC(0,0,1,5).setFill(GBC.BOTH).setWeight(0.5, 0.5) );
add( check1, new GBC(1,0,2,1).setAnchor(GBC.CENTER) );
add( check2, new GBC(1,1,2,1).setAnchor(GBC.CENTER) );
add( new JLabel("SLider1"), new GBC(1,2).setAnchor(GBC.EAST) );
add( slider1, new GBC(2,2).setFill(GBC.BOTH).setWeight(0.1, 0.5) );
add( new JLabel("Slider2"), new GBC(1,3).setAnchor(GBC.EAST) );
add( slider2, new GBC(2,3).setFill(GBC.BOTH).setWeight(0.1, 0.5) );
add( new JLabel("Slider3:"), new GBC(1,4).setAnchor(GBC.EAST) );
add( slider3, new GBC(2,4).setFill(GBC.BOTH).setWeight(0.1, 0.5) );
}
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable(){
@Override public void run()
{
AnimatedFrame frame = new AnimatedFrame();
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
GBC class code:
class GBC extends GridBagConstraints
{
private static final long serialVersionUID = 1L;
public GBC(int gridx, int gridy)
{
this.gridx = gridx;
this.gridy = gridy;
}
public GBC(int gridx, int gridy, int gridwidth, int gridheight)
{
this.gridx = gridx;
this.gridy = gridy;
this.gridwidth = gridwidth;
this.gridheight = gridheight;
}
public GBC setAnchor(int anchor)
{
this.anchor = anchor;
return this;
}
public GBC setFill(int fill)
{
this.fill = fill;
return this;
}
public GBC setWeight(double weightx, double weighty)
{
this.weightx = weightx;
this.weighty = weighty;
return this;
}
}
You can see for yourself that the program does not work correctly. Run the code for execution. Do not stretch the window vertically and stretch horizontally. Now try changing the state of JSliders or JCheckBoxes. They start to display incorrectly. If you then resize the frame again, the components will be redrawn correctly.
If you change the location of the components, then the problem will disappear:
public AnimatedFrame()
{
setLayout( new GridBagLayout() );
add( animatedComponent, new GBC(2,0,1,5).setFill(GBC.BOTH).setWeight(0.5, 0.5) );
add( check1, new GBC(0,0,2,1).setAnchor(GBC.CENTER) );
add( check2, new GBC(0,1,2,1).setAnchor(GBC.CENTER) );
add( new JLabel("SLider1"), new GBC(0,2).setAnchor(GBC.EAST) );
add( slider1, new GBC(1,2).setFill(GBC.BOTH).setWeight(0.1, 0.5) );
add( new JLabel("Slider2"), new GBC(0,3).setAnchor(GBC.EAST) );
add( slider2, new GBC(1,3).setFill(GBC.BOTH).setWeight(0.1, 0.5) );
add( new JLabel("Slider3:"), new GBC(0,4).setAnchor(GBC.EAST) );
add( slider3, new GBC(1,4).setFill(GBC.BOTH).setWeight(0.1, 0.5) );
}
It seems to me that it has something to do with the constant redrawing of the animatedComponent
. Please explain in detail why this is happening and how to properly work around this problem?
Answer:
Add the following code to the end of the AnimatedFrame()
constructor:
check1.setMinimumSize( check1.getPreferredSize() );
check2.setMinimumSize( check2.getPreferredSize() );
slider1.setMinimumSize( slider1.getPreferredSize() );
slider2.setMinimumSize( slider2.getPreferredSize() );
slider3.setMinimumSize( slider3.getPreferredSize() );
Components stop collapsing and resizing is pretty decent IMHO.