2015-04-19 5 views
2

Я работаю над проектом, и я подошел к столу. В настоящее время я создаю колесо стиля рулетки, которое будет вращаться, проблема, с которой я столкнулась, создает количество полигонов для колеса n. В конце концов, я хотел бы установить число n и использовать циклы for для создания точек полигонов. Я попытался использовать параметрическое уравнение этой определенной окружности, но значение y было неверным, поскольку пиксели обрабатываются по-разному. Вращение работает правильно с классом Rotateicon. Итак, простой вопрос: Как мне создать n 'количество полигонов из данного центра, прося x, y в конечном итоге с колесом?Создание рулеточного стиля Poly Wheel в Java

Кодекс

import java.awt.BasicStroke; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.Point; 
import java.awt.Polygon; 
import java.awt.RenderingHints; 
import java.awt.geom.Ellipse2D; 
import java.awt.image.BufferedImage; 
import java.util.Random; 

import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JSlider; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 




public class Wheel extends JPanel { 
    private JLabel label; 
    private Icon icon; 
    private Icon rotated; 
    private int degrees; 
    private static Point center; 

    public Wheel(Image image) 
    { 
     setPreferredSize(new Dimension(250, 250)); 
     center = new Point(250/2, 250/2); 

     icon = new ImageIcon(image); 
     label = new JLabel(icon); 
     label.setPreferredSize(label.getPreferredSize()); 
     add(label); 
     setDegrees(0); 
    } 

    public void setDegrees(int degrees) 
    { 
     this.degrees = degrees; 
     double radians = Math.toRadians(degrees); 
     rotated = new RotatedIcon(icon, degrees); 
     label.setIcon(rotated); 
    } 

    public static void main(String[] args) 
    { 
     EventQueue.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       Image bi = RotatableImage.getImage(250); 
       final Wheel r = new Wheel(bi); 

        final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0); 
        slider.addChangeListener(new ChangeListener() 
        { 
         public void stateChanged(ChangeEvent e) 
         { 
          int value = slider.getValue(); 
          r.setDegrees(value); 
         } 
        }); 

       JFrame f = new JFrame(); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.add(new JScrollPane(r)); 
       f.add(slider, BorderLayout.SOUTH); 
       f.pack(); 
       f.setLocationRelativeTo(null); 
       f.setVisible(true); 
      } 
     }); 
    } 
    static class RotatableImage 
    { 
     private static final Random r = new Random(); 

     static public Image getImage(int size) 
     { 
      BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); 
      Graphics2D g2d = bi.createGraphics(); 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1)); 
      g2d.setStroke(new BasicStroke(10.0f)); 

      Polygon flag = new Polygon(); 
      flag.addPoint(125, 125); 
      flag.addPoint(205, 250/2); 
      flag.addPoint(205, 250/2+10); 



      g2d.draw(flag); 

      g2d.setColor(Color.BLACK); 
      g2d.fillOval(120, 120, 10, 10); 

      g2d.dispose(); 
      return bi; 
     } 


    } 


} 

При необходимости значок вращения: http://pastebin.com/Sbb38ifU

Что я получаю:

enter image description here

Я пытаюсь закончить с :

enter image description here

+0

Это, скорее всего, поможет, если вы могли бы разместить изображения того, что вы хотите получить и то, что вы получаете взамен. – CandiedOrange

+0

Как колесо фортуны: http://fc05.deviantart.net/fs71/i/2011/202/2/8/blank_wheel_template_by_larry4009-d416r88.png –

+0

Я не вижу никаких овалов на этом изображении, поэтому я оставил недоумение, что означало 'g2d.fillOval()'. – CandiedOrange

ответ

2

Одним из способов решения этой проблемы является использование Arc2D сделать ваш пирог ломтиками. Ограничивающий прямоугольник для этой фигуры - это прямоугольник, который будет охватывать весь круг, из которого вырезается этот срез Arc. Затем вы можете построить свои разноцветные кусочки пирога в цикле for и нарисовать срезы на BufferedImage, который затем отображается в методе paintComponent JPanel. Это изображение можно повернуть, используя AffineTransform на объекте Graphics2D, который его рисует, но вы должны быть осторожны, так как вы не хотите преобразовывать объект Graphics, предоставленный вам JVM в качестве параметра paintComponent. По этой причине, вы хотите, чтобы сделать копию Graphics2D объекта, а затем преобразовать его:

protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2 = (Graphics2D) g.create(); // create a copy to rotate 
    if (image != null) { 
    if (af != null) { 
     g2.transform(af); 
    } 
    g2.drawImage(image, 0, 0, null); 
    } 
    g2.dispose(); // OK to do this as we created this object 
} 

Вы никогда не должны избавиться от объекта Graphics дал вам в JVM, но так как наш объект g2 является копией, все в порядке и на самом деле желают избавиться от него, поэтому у нас не хватает ресурсов. Например:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Arc2D; 
import java.awt.image.BufferedImage; 
import java.util.Arrays; 
import java.util.Collections; 
import java.util.List; 
import java.util.Random; 

import javax.swing.*; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

@SuppressWarnings("serial") 
public class FooArcs extends JPanel { 
    public static final int PREF_W = 500; 
    private PiePanel piePanel; 
    private JSlider slider = new JSlider(0, 260, 0); 

    public FooArcs(int imageWidth, int divisions) { 
     slider.setMinorTickSpacing(5); 
     slider.setMajorTickSpacing(20); 
     slider.setPaintLabels(true); 
     slider.setPaintTicks(true); 

     piePanel = new PiePanel(imageWidth, divisions); 

     slider.addChangeListener(new SliderListener()); 

     setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 
     setLayout(new BorderLayout(5, 5)); 
     add(piePanel, BorderLayout.CENTER); 
     add(slider, BorderLayout.PAGE_END); 
    } 

    private class SliderListener implements ChangeListener { 
     @Override 
     public void stateChanged(ChangeEvent e) { 
     int value = slider.getValue(); 
     piePanel.rotate(value); 
     } 
    } 

    private static void createAndShowGui() { 
     int imageWidth = PREF_W; 
     int divisions = 24; 
     FooArcs mainPanel = new FooArcs(imageWidth, divisions); 

     JFrame frame = new JFrame("FooArcs"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class PiePanel extends JPanel { 
    private BufferedImage image; 
    private Random random = new Random(); 
    private AffineTransform af; 
    private int imageWidth; 

    public PiePanel(int imageWidth, int divisions) { 
     this.imageWidth = imageWidth; 
     image = new BufferedImage(imageWidth, imageWidth, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = image.createGraphics(); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     for (int i = 0; i < divisions; i++) { 
     drawPie(g2, i, imageWidth, divisions); 
     } 
     g2.dispose(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g.create(); // create a copy to rotate 
     if (image != null) { 
     if (af != null) { 
      g2.transform(af); 
     } 
     g2.drawImage(image, 0, 0, null); 
     } 
     g2.dispose(); // OK to do this as we created this object 
    } 

    private void drawPie(Graphics2D g2, int i, int imageWidth2, int divisions) { 
     Color c = getRandomColor(); 
     double x = 1.0; 
     double y = x; 
     double w = imageWidth2 - 2; 
     double h = w; 
     double start = i * 360.0/divisions; // starting angle 
     double extent = 360.0/divisions; // size of slice in degrees 
     int type = Arc2D.PIE; 
     Arc2D arc = new Arc2D.Double(x, y, w, h, start, extent, type); 

     g2.setColor(c); 
     g2.fill(arc); 
     g2.setColor(Color.black); 
     g2.draw(arc); 
    } 

    private Color getRandomColor() { 
     Integer a = random.nextInt(128) + 128; 
     Integer b = random.nextInt(128) + (random.nextBoolean() ? 128 : 0); 
     Integer c = random.nextInt(128); 
     List<Integer> colors = Arrays.asList(new Integer[] {a, b, c}); 
     Collections.shuffle(colors); 
     Color color = new Color(colors.get(0), colors.get(1), colors.get(2)); 

     return color; 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
     return super.getPreferredSize(); 
     } 
     return new Dimension(imageWidth, imageWidth); 
    } 

    public void rotate(int degrees) { 
     double theta = Math.toRadians(degrees); 
     double anchorx = imageWidth/2.0; 
     double anchory = anchorx; 
     af = AffineTransform.getRotateInstance(theta, anchorx, anchory); 
     repaint(); 
    } 
} 

Это показывает, как:

enter image description here

+0

Редактировать: oops - Я должен был использовать 360, а не 260 для моего JSlider max! –

+0

Большое вам спасибо за это, это очень помогло. –

2

Вы создаете прямоугольный треугольник. То, что вы пытаетесь сделать, ближе к ряду повернутых равнобедренных треугольников.

Легкий способ получить равнобедренный будет придерживаться два прямых углов треугольника вместе:

 flag.addPoint(125, 125); 
//  flag.addPoint(205, 250/2); 
     flag.addPoint(205, 250/2+10); 
     flag.addPoint(205, 250/2-10); 

Это потребует некоторой более тонкой настройки. Окружность должна быть кругом, а не полигоном. Еще нужно сделать серию из них, и теперь есть отверстие для заполнения, так как вы пытаетесь заполнить треугольник, используя толщину линии. Но теперь по крайней мере углы верны.

enter image description here