线程无法在所需的情况下工作

时间:2016-07-07 09:07:45

标签: java multithreading swing runnable

在我的代码中,我在Mouse Listener

中有以下语句
class CustomMouseListener extends MouseAdapter {
    Menu m;
    MenuDesign mD;
    SlideInLayout s;

    public CustomMouseListener(Menu m, MenuDesign mD, SlideInLayout s) {
        this.m = m;
        this.mD = mD;
        this.s = s;
    }

    public void mousePressed(MouseEvent mE) {       
        if(m != null && mD != null) {
            if(mE.getSource() == mD) {
                if(mD.getInOut()) {
                    mD.setFade(false);
                    Thread runSwap = new Thread(new Runnable() {
                        public void run() {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            s.show(m.getFirstPanel());
                        }
                    });
                    runSwap.start();
                    try {
                        runSwap.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    mD.setFade(true);
                    new Thread(new Runnable() {
                        public void run() {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            s.show(m.getOverlay());
                        }
                    }).start();
                }

                mD.fade();
                m.getMainWindow().validate();
                m.getMainWindow().repaint();
            }
        }
    }
}

理想情况下,我希望我的runnable动画与mD.fade();同时运行,所以为了做到这一点我会写

Thread runSwap = new Thread(new Runnable() {
    public void run() {
        s.show(m.getFirstPanel());
    }
});

而不是这个。

Thread runSwap = new Thread(new Runnable() {
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        s.show(m.getFirstPanel());
    }
});

然而,这会导致动画的最终结果立即发生。另一个问题是当我需要在结束时重新绘制屏幕,​​因为它最终会像下图中的第一帧而不是第二帧一样,但是使用repaint()validate()方法会导致动画在runnable中没有发生,最终结果再次出现,即使在线程使用.join()之后也是如此。

感谢您解决问题的任何帮助

完整代码(如果需要)

package menutest;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;

public class Menu {
    JFrame myMainWindow = new JFrame("Menu Slide Test");
    GridBagConstraints c;
    MyFirstPanel fP;
    MyOverlay oL;
    MyMenuButton mB;
    GridBagLayout baseLayout;
    GridBagLayout overlayLayout;
    SlideInLayout slideIn = new SlideInLayout();
    JPanel tempHold = new JPanel(slideIn);

    /* Height and Width */
    int height = 600;
    int width = 600;

    private void runGUI(Menu m) {
        myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myMainWindow.setLayout(new GridBagLayout());
        setContraints();
        createPanels(m);
        myMainWindow.getContentPane().add(tempHold, c);
        myMainWindow.getContentPane().add(mB, c, 0);
        slideIn.show(fP);
        myMainWindow.pack();
        myMainWindow.setVisible(true);
        myMainWindow.setLocationRelativeTo(null);
    }

    private void setContraints() {
        c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;
        c.weightx = 1;
        c.weighty = 1;
        c.fill = GridBagConstraints.BOTH;
    }

    private void createPanels(Menu m) {
        createFirstPanel(m);
        createOverlay(m);
        createMenuButton(m);

        tempHold.add(fP);
        tempHold.add(oL);
    }

    private void createFirstPanel(Menu m) {
        baseLayout = new GridBagLayout();
        fP = new MyFirstPanel(baseLayout, m);

    }

    private void createOverlay(Menu m) {
        overlayLayout = new GridBagLayout();
        oL = new MyOverlay(overlayLayout, m);

    }

    private void createMenuButton(Menu m) {
        mB = new MyMenuButton(m);
    }

    public static void main(String[] args) {
        Menu menu = new Menu();
        menu.runGUI(menu);
    }

    /* Getters and Setters */

    public JPanel getFirstPanel() {
        return fP;
    }

    public JPanel getOverlay() {
        return oL;
    }

    public JFrame getMainWindow() {
        return myMainWindow;
    }

    public int myGetHeight() {
        return height;
    }

    public int myGetWidth() {
        return width;
    }

    public SlideInLayout getSlide() {
        return slideIn;
    }
}

class MyFirstPanel extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = 2897488186622284953L;

    MyFirstPanel(GridBagLayout layout, Menu mM) {
        setLayout(layout);
        setBackground(Color.RED);
        setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
    }
}

class MyOverlay extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = 4595122972358754430L;

    MyOverlay(GridBagLayout layout, Menu mM) {
        setLayout(layout);
        setBackground(Color.GREEN);
        setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
    }
}

class MyMenuButton extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = -4986432081497113479L;

    MyMenuButton(Menu mM) {
        setLayout(null);
        setBackground(new Color(0, 0, 0, 0));
        setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
        add(new MenuDesign(15, 15, mM, mM.myGetWidth()));
    }


}

class MenuDesign extends JLabel {
    /**
     * 
     */
    private static final long serialVersionUID = 2255075501909089222L;
    boolean inOut = false; //true for fade out, false for fade in
                          //starts on false because it changes to true on first click on label
    float alpha = 1F;
    Timer timer;

    //Start Points
    double[] r1Points = {0, 6.67766953};
    double[] r2Points = {0, 16.67766953};
    double[] r3Points = {0, 26.67766953};

    //Current Points
    double[] curR1Points = {r1Points[0], r1Points[1]};
    double[] curR3Points = {r3Points[0], r3Points[1]};

    //End Points
    double[] endR1Points = {2.828427125, 0};
    double[] endR3Points = {0, 35.35533906};

    //Angles
    double ang1 = 0;
    double ang2 = 0;

    //Height and width of component to make it as efficient as possible
    int width = 50;
    int height = 40;

    MenuDesign(int x, int y, Menu m, int width) {
        setBounds(x, y, this.width, height);
        setCursor(new Cursor(Cursor.HAND_CURSOR));
        addMouseListener(new CustomMouseListener(m, this, m.getSlide()));
        timer = new Timer(5, new CustomActionListener(m, this, r1Points, r3Points, endR1Points, endR3Points, x, width - 60));
    }

    public void fade() {
        timer.start();
        System.out.println("Start");
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setColor(Color.WHITE);

        Rectangle2D r1 = new Rectangle2D.Double(curR1Points[0], curR1Points[1], width, 4);
        Rectangle2D r2 = new Rectangle2D.Double(r2Points[0], r2Points[1], width, 4);
        Rectangle2D r3 = new Rectangle2D.Double(curR3Points[0], curR3Points[1], width, 4);

        //r1
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1F));
        g2d.rotate(Math.toRadians(ang1), endR1Points[0], endR1Points[1]);
        g2d.fill(r1);

        //r3
        g2d.rotate(Math.toRadians(-ang1), endR1Points[0], endR1Points[1]);
        g2d.rotate(Math.toRadians(-ang2), endR3Points[0], endR3Points[1]);
        g2d.fill(r3);

        //r2
        g2d.rotate(Math.toRadians(ang2), endR3Points[0], endR3Points[1]);
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
        g2d.fill(r2);
    }

    public Timer getTimer() {
        return timer;
    }

    public float getAlpha() {
        return alpha;
    }

    public void setAplha(float a) {
        this.alpha = a;

        if(a < 0) {
            setAplha(0F);
        }

        if(a > 1) {
            setAplha(1F);
        }

        validate();
        repaint();
    }

    public boolean getInOut() {
        return inOut;
    }

    public void setFade(boolean b) {
        this.inOut = b;
    }

    public double[] getTransR1() {
        return curR1Points;
    }

    public double[] getTransR3() {
        return curR3Points;
    }

    public void setTransR1(double[] d) {
        this.curR1Points = d;
    }

    public void setTransR3(double[] d) {
        this.curR3Points = d;
    }

    public void setAng1(double d) {
        this.ang1 = d;
    }

    public void setAng2(double d) {
        this.ang2 = d;
    }

    public void stopTheTimer(int i) {
        if(i == 101) {
            timer.stop();
            System.out.println("stop");
        }
    }
}

class CustomActionListener implements ActionListener {
    Menu m;
    MenuDesign mD;
    MyFirstPanel mFP;
    double[] a, b, c, d;

    double incrementX1;
    double incrementY1;
    double incrementX2;
    double incrementY2;

    double incrementX3;
    double incrementY3;
    double incrementX4;
    double incrementY4;

    double angInc = 45.0 / 100.0;
    double moveInc;

    int i = 0;
    int startPoint;

    public CustomActionListener(Menu m, MyFirstPanel mFP) {
        this.m = m;
        this.mFP = mFP;
    }

    public CustomActionListener(Menu m, MenuDesign mD, double[] a, double[] b, double[] c, double[] d, int startPoint, int endPoint) {
        this.m = m;
        this.mD = mD;
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.startPoint = startPoint;

        //Increments
        int incTot = 100;

        //r1 increments
        incrementX1 = (c[0] - a[0]) / incTot;
        incrementY1 = (c[1] - a[1]) / incTot;
        incrementX2 = (a[0] - c[0]) / incTot;
        incrementY2 = (a[1] - c[1]) / incTot;

        //r2 increments
        incrementX3 = (d[0] - b[0]) / incTot;
        incrementY3 = (d[1] - b[1]) / incTot;
        incrementX4 = (b[0] - d[0]) / incTot;
        incrementY4 = (b[1] - d[1]) / incTot;

        //Movement
        moveInc = (endPoint - startPoint) / incTot;
    }

    public void actionPerformed(ActionEvent e) {
        if(m != null && mD != null) {
            if(e.getSource() == mD.getTimer()) {
                if(mD.getInOut()) { //Start of transform into x
                    //r1
                    mD.setTransR1(new double[] {a[0] + (i * incrementX1), a[1] + (i * incrementY1)});
                    mD.setAng1(i * angInc);

                    //r2
                    mD.setAplha(mD.getAlpha() - 0.02F);

                    //r3
                    mD.setTransR3(new double[] {b[0] + (i * incrementX3), b[1] + (i * incrementY3)});
                    mD.setAng2(i * angInc);

                    //Location
                    mD.setLocation((int) (startPoint + (i * moveInc)), startPoint);

                    i++;
                } else { //Start of transform into three lines
                    //r1
                    mD.setTransR1(new double[] {c[0] + (i * incrementX2), c[1] + (i * incrementY2)});
                    mD.setAng1((100 - i) * angInc);

                    //r2
                    if(i >= 50) {
                        mD.setAplha(mD.getAlpha() + 0.02F);
                    }

                    //r3
                    mD.setTransR3(new double[] {d[0] + (i * incrementX4), d[1] + (i * incrementY4)});
                    mD.setAng2((100 - i) * angInc);

                    //Location
                    mD.setLocation((int) (540 + (i * -moveInc)), 15);

                    i++;
                }

                if(i == 101) {
                    mD.stopTheTimer(i);
                    i = 0;
                }

                m.getMainWindow().validate();
                m.getMainWindow().repaint();
            }
        }
    }
}

class CustomMouseListener extends MouseAdapter {
    Menu m;
    MenuDesign mD;
    SlideInLayout s;

    public CustomMouseListener(Menu m, MenuDesign mD, SlideInLayout s) {
        this.m = m;
        this.mD = mD;
        this.s = s;
    }

    public void mousePressed(MouseEvent mE) {       
        if(m != null && mD != null) {
            if(mE.getSource() == mD) {
                if(mD.getInOut()) {
                    mD.setFade(false);
                    Thread runSwap = new Thread(new Runnable() {
                        public void run() {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            s.show(m.getFirstPanel());
                        }
                    });
                    runSwap.start();
                    try {
                        runSwap.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    mD.setFade(true);
                    new Thread(new Runnable() {
                        public void run() {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            s.show(m.getOverlay());
                        }
                    }).start();
                }

                mD.fade();
                m.getMainWindow().validate();
                m.getMainWindow().repaint();
            }
        }
    }
}

/////////////// Below here is not my code

class SlideInLayout implements LayoutManager {
    private Component focusedComponent;

    @Override
    public void addLayoutComponent(String name, Component comp) {}

    @Override
    public void removeLayoutComponent(Component comp) {}

    @Override
    public void layoutContainer(Container parent) {
        setSizes(parent);

        if (hasFocusedComponent()) {
            focusedComponent.setVisible(true);
        }
    }

    private void setSizes(Container parent) {
        Insets insets = parent.getInsets();
        int maxWidth = parent.getWidth() - (insets.left + insets.right);
        int maxHeight = parent.getHeight() - (insets.top + insets.bottom);

        for (Component component : parent.getComponents()) {
            component.setBounds(0, 0, maxWidth, maxHeight);
        }
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
        return new Dimension(0, 0);
    }

    @Override
    public Dimension preferredLayoutSize(Container parent) {
        Dimension preferredSize = new Dimension(0, 0);

        if (hasFocusedComponent()) {
            preferredSize = focusedComponent.getPreferredSize();
        }
        else if (parent.getComponentCount() > 0) {
            int maxWidth = 0;
            int maxHeight = 0;

            for (Component component : parent.getComponents()) {
                Dimension componentSize = component.getPreferredSize();
                maxWidth = Math.max(maxWidth, componentSize.width);
                maxHeight = Math.max(maxHeight, componentSize.height);
            }

            preferredSize = new Dimension(maxWidth, maxHeight);
        }

        return preferredSize;
    }

    private boolean hasFocusedComponent() {
        return focusedComponent != null;
    }

    public void show(Component component) {
        if (hasFocusedComponent())
            swap(focusedComponent, component);

        focusedComponent = component;
    }

    private void swap(Component transitionOut, Component transitionIn) {
        new SwapTimerAction(transitionOut, transitionIn).start();
    }

    private class SwapTimerAction implements ActionListener {
        private Timer timer;
        private Component transitionOut;
        private Component transitionIn;
        private static final int tick = 16; //16ms
        private static final int speed = 50;

        public SwapTimerAction(Component transitionOut, Component transitionIn) {
            this.transitionOut = transitionOut;
            this.transitionIn = transitionIn;
        }

        public void start() {
            Container container = transitionOut.getParent();
            container.setComponentZOrder(transitionOut, 1);
            container.setComponentZOrder(transitionIn, 0);
            transitionIn.setBounds(-transitionOut.getWidth(), 0, transitionOut.getWidth(), transitionOut.getHeight());
            timer = new Timer(tick, this);
            timer.start();
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            int newX = Math.min(transitionIn.getX() + speed, transitionOut.getX());
            transitionIn.setLocation(newX, 0);

            if (newX == transitionOut.getX()) {
                timer.stop();
            }
        }
    }
}

0 个答案:

没有答案