2013-11-04 64 views
1

我创建了一个8x8 GridLayout棋盘游戏,其中每个网格中都有一个不透明的按钮。我创建了以8x8表格的形式显示,当用户点击任何单元格时,它应该执行一些操作。现在,网格的样子:在Swing中重新定位GridLayout

enter image description here

我希望它通过动画重新定位这一个角度看是这样的:

enter image description here

是否有可能做到这一点在Swing使用repaint?如果没有,是否有更好的工具包可以使用,除了Swing以便我可以制作动画?

+1

这样做现场组件上,不是真的,通过绘画做,绝对... – MadProgrammer

回答

3

更改直播组件的状态需要更多的则只是画...

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

enter image description here

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

话虽如此,有一种方法,但你需要为它工作。

enter image description here

这是基于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

抢副本添加,因为它的乐趣......

enter image description 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)); 
      } 
     } 

    } 
} 
+0

我没有注意到您的第一个gif中显示的问题,因为Nimbus L&F似乎没有受到它的影响(虽然它仍然不是*完全正确)。 +1,尽管如此,我很佩服你把它放在一起的速度。 – Boann

+0

@Boann有一些东西在铺设,玩弄想法 – MadProgrammer

+0

@MadProgrammer,从我看到这个问题的那一刻起,我正在桌子上敲着我的头,问“名字是什么,名字是什么,我在哪里看到这样的实现,它在java.net或swingxlab中的某处“但我记不起我近一年前看过的是哪一个:谢谢你再次提醒我:) +1 – Sage

0

是否有可能在Swing中使用repaint执行此操作?如果没有,是否有更好的工具包可以使用,而不是Swing,这样我就可以制作这个动画了?

不,这不可能与GridLayout。在JPanel上使用图形drawLine并使用Timer对其进行动画处理。

+0

谢谢!会试试看! – Mercenary

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

它(前/后)看起来像什么:

enter image description here

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

+0

有趣的做法。 +1 –

+0

现在做鼠标点击 – MadProgrammer

+0

并在屏幕上运行鼠标;) – MadProgrammer