【问题标题】:slide effect with JPanelJPanel 的幻灯片效果
【发布时间】:2012-07-02 06:28:53
【问题描述】:

我尝试创建可以像这样滑动 JPanel 的简单类:

+----------+ +------+---+ +----------+
| | | | | | |
| JPanel1 | => |日语| JP| => | JPanel2 |
| | | | | | |
+----------+ +------+---+ +----------+

我创建了 javax.swing.Timer 并添加到类中

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);
    }
}

这是工作,但非常缓慢。我只有 2-3 fps,不知道如何加快这种方法。你能帮帮我吗?

【问题讨论】:

    标签: java swing


    【解决方案1】:

    也许将计时器的间隔从 50 更改为更小的数字。

    即,从此:

    timer = new Timer(50, this);
    

    到这里:

    timer = new Timer(10, this);
    

    注意:您应该避免在此处使用幻数。

    哎呀,有点像......

    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();
       }
    }
    

    【讨论】:

    • 不,50 正好是 20 fps,而不是 2 或 3。
    • 我更改了这个问题中的所有变量。在实际代码中,我避免使用幻数。我尝试了不同的时间/框架,但没有帮助。而这个实验是用空的JPanel进行的。
    • @pushistic:考虑发布一个演示您的问题的最小代码示例,SSCCE。这将使我们能够运行您的代码并对其进行修改,甚至可能更正它。请在回复之前阅读该链接,因为它提供了有关 SSCCE 要求的许多重要细节。
    • @hovercraft-full-of-eels 谢谢!当我尝试编写 SSCCE 时,我看到了您的示例并发现了我的问题。我使用 JPanel 而不是 JLayeredPane 作为父组件。如果内部有 2 个或更多 JPanel,我的构造在性能方面会遇到很大问题。
    • @Hovercraft Full Of Eels another question for your great idea
    猜你喜欢
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 2018-03-11
    相关资源
    最近更新 更多