在我的代码中,我在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();
}
}
}
}