我创建了一个8x8 GridLayout
的棋盘游戏,每个网格中都有一个不透明的按钮。我创建了以8x8表格的形式显示,当用户点击任何单元格时,它应该执行一些操作。现在,网格看起来像:
我希望它通过动画以一定的角度重新定位它,如下所示:
是否可以使用Swing
在repaint
中执行此操作?如果没有,是否有更好的工具包可以使用Swing
以外的其他工具包,以便我可以为此设置动画?
答案 0 :(得分: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的例子似乎已经从互联网的面孔消失了,令我们非常失望。
但是,您可以从here
获取副本添加,因为它很有趣......
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));
}
}
}
}
答案 1 :(得分: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之上破解这个功能。
答案 2 :(得分:0)
是否可以使用重绘在Swing中执行此操作?如果没有,是否有 更好的工具包可以使用除Swing之外的其他工具包以便我可以动画这个吗?
不,GridLayout
无法实现。将JPanel
上的图片与drawLine
一起使用,并使用Timer
设置动画。