I\'m trying to change current visible in card layout with slide effect. But I see a flick at the start of slide which I\'m not able to debug/solve. How can I avoid that flick?
The main problem is that you are stepping on CardLayout's toes. CardLayout both manages bounds (location and size) and visibility of your components, so your loop here:
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
label2.setLocation(label1.getX() + 10 - label1.getWidth(), label1.getY());
label1.setLocation(label1.getX() + 10, label1.getY());
label2.setVisible(true);
}
is conflicting with what CardLayout does. By default, CardLayout will automatically show the first component you added and hide all the others. It also sets up the bounds of all components to the same bounds.
At the end of the first iteration, the visibility of label2 changes (from false
to true
) which eventually triggers your CardLayout to reperform the layout of your components which sets the bounds of all the components to the same bounds which is why you are seeing the overlapping. CardLayout is not meant to have multiple components visible simultaneously.
Note that you are running all this off the EDT (Event Dispatching Thread) which is really a bad idea. It can cause deadlocks and unpredictable behaviour (such as the one you are seeing here).
a few comments and could be comments only
idea with Thread.sleep
is correct but started only from Runnable.Thread
for Swing GUI is there Swing Timer
,
Swing Timer
guarantee to move any of (without flickering with already) visible JComponents
layed by standard LayoutManager
but in this (my code example) case I'm again using Swing Timer nor that all events would be done on EDT, by invoking from Runnable living own life without impact to the rest of Swing events, GUI e.i.,
notice this issue is based on AWT nested / inherits, for example for JComboBoxes popup (resize and with doLayout()) doesn't works
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ShakingButtonDemo implements Runnable {
private JButton button;
private JRadioButton radioWholeButton;
private JRadioButton radioTextOnly;
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new ShakingButtonDemo());
}
@Override
public void run() {
radioWholeButton = new JRadioButton("The whole button");
radioTextOnly = new JRadioButton("Button text only");
radioWholeButton.setSelected(true);
ButtonGroup bg = new ButtonGroup();
bg.add(radioWholeButton);
bg.add(radioTextOnly);
button = new JButton(" Shake with this Button ");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
shakeButton(radioWholeButton.isSelected());
}
});
JPanel p1 = new JPanel();
p1.setBorder(BorderFactory.createTitledBorder("Shake Options"));
p1.setLayout(new GridLayout(0, 1));
p1.add(radioWholeButton);
p1.add(radioTextOnly);
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(0, 1));
p2.add(button);
JFrame frame = new JFrame();
frame.setTitle("Shaking Button Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(p1, BorderLayout.NORTH);
frame.add(p2, BorderLayout.SOUTH);
frame.setSize(240, 160);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void shakeButton(final boolean shakeWholeButton) {
final Point point = button.getLocation();
final Insets margin = button.getMargin();
final int delay = 75;
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
if (shakeWholeButton) {
moveButton(new Point(point.x + 5, point.y));
Thread.sleep(delay);
moveButton(point);
Thread.sleep(delay);
moveButton(new Point(point.x - 5, point.y));
Thread.sleep(delay);
moveButton(point);
Thread.sleep(delay);
} else {// text only
setButtonMargin(new Insets(margin.top, margin.left + 3, margin.bottom, margin.right - 2));
Thread.sleep(delay);
setButtonMargin(margin);
Thread.sleep(delay);
setButtonMargin(new Insets(margin.top, margin.left - 2, margin.bottom, margin.right + 3));
Thread.sleep(delay);
setButtonMargin(margin);
Thread.sleep(delay);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
Thread t = new Thread(r);
t.start();
}
private void moveButton(final Point p) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
button.setLocation(p);
}
});
}
private void setButtonMargin(final Insets margin) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
button.setMargin(margin);
}
});
}
}
May be this http://java-sl.com/tip_slider.html ?