4

I tried create simple class which can slide a JPanel like this:

+----------+    +------+---+    +----------+
|          |    |      |   |    |          |
| JPanel1  | => | JPane| JP| => | JPanel2  |
|          |    |      |   |    |          |
+----------+    +------+---+    +----------+

I created javax.swing.Timer and added in class

timer = new Timer(50, this);
timer.start();

static final int frames = 5;
int counter = 0;

actionPerformed(ActionEvent e) {
    if (counter >= frames) {
        timer.stop();
        counter = 0;
    } else {
        counter++;
        jPanel2.setBounds(800 - 800 * counter / frames, 0, 800, 600);
    }
}

This is work, but very slowly. I have only 2-3 fps and don't know how to speed up this method. May you help me?

pushistic
  • 3,406
  • 3
  • 21
  • 35

1 Answers1

12

Perhaps change the Timer's interval from 50 to some smaller number.

i.e., from this:

timer = new Timer(50, this);

to this:

timer = new Timer(10, this);

Note: you should avoid use of magic numbers here.

Heck, something like...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class SlideEg extends JPanel {
   private SlideContainer slideContainer = new SlideContainer();

   public SlideEg() {
      setLayout(new BorderLayout());
      add(slideContainer, BorderLayout.CENTER);

      JLabel helloLabel = new JLabel("Hello", SwingConstants.CENTER);
      slideContainer.add(helloLabel);

      Timer myTimer = new Timer(5000, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            JLabel goodbyeLabel = new JLabel("Goodbye", SwingConstants.CENTER);
            goodbyeLabel.setOpaque(true);
            goodbyeLabel.setBackground(Color.pink);
            slideContainer.add(goodbyeLabel);
         }
      });
      myTimer.setRepeats(false);
      myTimer.start();
   }

   private static void createAndShowGui() {
      SlideEg mainPanel = new SlideEg();

      JFrame frame = new JFrame("SlideEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class SlideContainer extends JLayeredPane {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private static final int SLIDE_DELAY = 20;
   protected static final int DELTA_X = 2;
   Component oldComponent;

   public SlideContainer() {
      setLayout(null);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   public Component add(Component comp) {
      Component[] comps = getComponents();
      if (comps.length > 0) {
         oldComponent = comps[0];
      }
      if (oldComponent == comp) {
         return super.add(comp);
      }
      if (oldComponent != null) {
         putLayer((JComponent) oldComponent, JLayeredPane.DEFAULT_LAYER);
      }
      Component returnResult = super.add(comp);
      putLayer((JComponent) comp, JLayeredPane.DRAG_LAYER);
      comp.setSize(getPreferredSize());
      comp.setVisible(true);
      comp.setLocation(getPreferredSize().width, 0);
      slideFromRight(comp, oldComponent);
      return returnResult;
   }

   private void slideFromRight(final Component comp,
         final Component oldComponent2) {
      new Timer(SLIDE_DELAY, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent aEvt) {
            int x = comp.getX();
            if (x <= 0) {
               comp.setLocation(0, 0);
               putLayer((JComponent) comp, JLayeredPane.DEFAULT_LAYER);
               if (oldComponent2 != null) {
                  remove(oldComponent2);
               }
               ((Timer) aEvt.getSource()).stop();
            } else {
               x -= DELTA_X;
               comp.setLocation(x, 0);
            }
            repaint();
         }
      }).start();
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 2
    No, 50 is exactly 20 fps, not 2 or 3. – 11684 Jul 01 '12 at 16:13
  • I changed all my variables in this question. In real code I avoid magic numbers. I tried different time/frame and it didn't help. And this experiment was taken with empty JPanel. – pushistic Jul 01 '12 at 16:18
  • 1
    @pushistic: Consider posting a minimal code example that demonstrates your problem, an [SSCCE](http://sscce.org). This will allow us to run your code and modify it and perhaps even correct it. Please read the link before replying as it supplies many important details on the SSCCE requirements. – Hovercraft Full Of Eels Jul 01 '12 at 16:21
  • @hovercraft-full-of-eels Thank you! When I was trying to write SSCCE I saw your example and found my problem. I was using JPanel instead of JLayeredPane for parent Component. My construction has a big trouble with performance if it has 2 and more JPanel inside. – pushistic Jul 01 '12 at 17:08
  • @Hovercraft Full Of Eels [another question for your great idea](http://stackoverflow.com/questions/14176225/java-slideshow-image-delay-using-paintcomponent) – mKorbel Jan 05 '13 at 20:51