1

我创建了一个 8x8 的棋盘游戏GridLayout,在每个网格中,都有一个不透明的按钮。我已经创建以 8x8 表格的形式显示,当用户单击任何单元格时,它应该执行一些操作。现在,网格看起来像:

在此处输入图像描述

我希望它通过动画以一个角度重新定位它,如下所示:

在此处输入图像描述

Swing在使用中可以做到这一点repaint吗?如果没有,是否有更好的工具包可以用来Swing制作动画?

4

3 回答 3

3

更改活动组件的状态需要的不仅仅是绘画......

例如,基于 Boann 的例子......

在此处输入图像描述

Swing 中的绘画是一个复杂且经过优化的过程,并不总是以线性方式完成。

话虽如此,有一种方法,但你需要为之努力。

在此处输入图像描述

这是基于 JXLayer API 和 pbjar 示例

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.demo.TransformUtils;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;

public class Twister02 {

    public static void main(String[] args) {
        new Twister02();
    }

    public Twister02() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ExamplePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ExamplePane extends JPanel {

        private JSlider slider;
        private FieldPane fieldPane;
        private DefaultTransformModel transformModel;

        public ExamplePane() {

            setLayout(new BorderLayout());

            slider = new JSlider(0, 360);
            slider.setValue(0);
            slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {

                    transformModel.setRotation(Math.toRadians(slider.getValue()));

                }
            });

            fieldPane = new FieldPane();

            transformModel = new DefaultTransformModel();
            transformModel.setRotation(Math.toRadians(0));
            transformModel.setScaleToPreferredSize(true);
            JXLayer<JComponent> rotatePane = TransformUtils.createTransformJXLayer(fieldPane, transformModel);

            add(slider, BorderLayout.NORTH);
            add(rotatePane);

        }
    }

    public class FieldPane extends JPanel {

        public FieldPane() {
            setLayout(new GridLayout(8, 8));
            for (int i = 0; i < 64; i++) {
                add(new JButton("" + i));
            }
        }

    }
}

现在,问题是,pbjar 示例似乎已经从互联网上消失了,这让我们非常失望。

但是,您可以从此处获取副本

添加,因为它很有趣...

在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.demo.TransformUtils;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;

public class Twister02 {

    public static void main(String[] args) {
        new Twister02();
    }

    public Twister02() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ExamplePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ExamplePane extends JPanel {

        private JSlider rotateSlider;
        private JSlider shearXSlider;
        private JSlider shearYSlider;
        private FieldPane fieldPane;
        private DefaultTransformModel transformModel;

        public ExamplePane() {

            setLayout(new BorderLayout());

            rotateSlider = new JSlider(0, 180);
            rotateSlider.setValue(0);
            rotateSlider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {

                    transformModel.setRotation(Math.toRadians(rotateSlider.getValue()));

                }
            });
            shearXSlider = new JSlider(-100, 100);
            shearXSlider.setValue(0);
            shearXSlider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {

                    double value = shearXSlider.getValue() / 200d;
                    transformModel.setShearX(value);

                }
            });
            shearYSlider = new JSlider(-100, 100);
            shearYSlider.setValue(0);
            shearYSlider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {

                    double value = shearYSlider.getValue() / 200d;
                    transformModel.setShearY(value);

                }
            });

            fieldPane = new FieldPane();

            transformModel = new DefaultTransformModel();
            transformModel.setRotation(Math.toRadians(0));
            transformModel.setScaleToPreferredSize(true);
            JXLayer<JComponent> rotatePane = TransformUtils.createTransformJXLayer(fieldPane, transformModel);

            JPanel sliders = new JPanel(new GridLayout(3, 0));
            sliders.add(rotateSlider);
            sliders.add(shearXSlider);
            sliders.add(shearYSlider);

            add(sliders, BorderLayout.NORTH);
            add(rotatePane);

        }
    }

    public class FieldPane extends JPanel {

        public FieldPane() {
            setLayout(new GridLayout(8, 8));
            for (int i = 0; i < 64; i++) {
                add(new JButton("" + i));
            }
        }

    }
}
于 2013-11-04T04:15:17.407 回答
1

覆盖容器的paintChildren方法以对 Graphics 对象应用变换,然后调用super.paintChildren它。将按钮网格围绕其中心旋转一点的简单示例:

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(8, 8)) {
    @Override
    public void paintChildren(Graphics g1) {
        Graphics2D g = (Graphics2D)g1;
        g.rotate(0.3, getWidth() / 2, getHeight() / 2);
        super.paintChildren(g);
    }
};
frame.add(panel);
for (int i = 0; i < 64; i++) panel.add(new JButton("" + i));

frame.pack();
frame.setVisible(true);

它的样子(之前/之后):

在此处输入图像描述

编辑:虽然它看起来很聪明,但您实际上不能在旋转位置单击这些按钮;可能可以使用 AffineTransform 对象来转换鼠标事件并将它们重定向到正确的子正确组件,但我还没有尝试过。重绘区域也可能存在问题。...也许绘制自己的网格(@Masud 的回答)可以避免尝试在 Swing 之上破解此功能。

于 2013-11-04T03:56:51.360 回答
0

是否可以在 Swing 中使用重绘来做到这一点?如果没有,除了 Swing 之外,还有更好的工具包可以用来制作动画吗?

不,这是不可能的GridLayoutJPanel在with上使用图形drawLine并用Timer.

于 2013-11-04T03:32:34.083 回答