0

I'm in my first year of computer engineering, learning Java as my first programming language. I wanted to create a 'Fast Wheel Raffle' application, but I encountered a few issues. First of all:

1- I'm creating the Arcs using the fillArc method and increasing the spinAngel by spinAngelMultiplier in the spin() method to perform the spinning operation. 2- The calculateAngel() method returns the angle for each Arc.

The problem I'm facing is that I'm unable to center each value from the 'inputs' list within the Arcs. What can I do to achieve this?

There is a drawWheel() method for creating Arcs.

    public void drawWheel(Graphics g){
        Graphics2D g2D = (Graphics2D) g;
        g2D.setColor(Color.BLACK);
        g2D.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2D.setStroke(new BasicStroke(4));
        g2D.drawOval(100,100,400,400);
        if(this.inputs.size() > 0){
            int extra = 0;
            for(int i = 0; i < this.inputs.size(); i++){
                g2D.setColor(colors[i]);
                int angel = calculateAngel();
                if ( ( i == this.inputs.size() - 1 )  && ( (angel + angel*i) != 360 ) ) {
                    extra = 360 - (angel+angel*i) ;
                }
                g2D.fillArc(100,100,400,400,angel*i+spinAngel, angel+extra);

                System.out.println(angel*i+spinAngel + " and " + (angel+extra));

                // I really confused on this part
 
                g2D.setFont(new Font("Ariel", Font.BOLD, 10));
                g2D.setColor(Color.black);
                int xMultiplier = -1;
                int yMultiplier = 1;
                if(angel*i+spinAngel >=0 && angel*i+spinAngel <180){
                    yMultiplier = -1;
                }if(angel*i+spinAngel >=270 && angel*i+spinAngel <90){
                    xMultiplier = 1;
                }
                int cosX = (int) ( Math.cos(angel+extra) );
                int sinY = (int) ( Math.cos(angel+extra) );
                int stringX = 300 + (xMultiplier * cosX);
                int stringY = 300 + (yMultiplier * sinY);
                g2D.drawString( inputs.get(i), stringX, stringY);

            }
        }
        g2D.setColor(Color.BLACK);
        g2D.fillOval(300,300,2,2);
    }

When the inputs are entered, the wheel appears like this. As it looks, I couldn't figure out how to center the Strings within the Arcs.

And spin() method for increasing spinAngel and reducing spinAngelMultiplier randomly.

    public void spin(){
        if(spinAngelMultiplier == 0){
            gameRunning = false;
            return;
        }

        if(spinAngelMultiplierReducer >= randomNumber){
            spinAngelMultiplierReducer = 0;
            spinAngelMultiplier--;
            minMaxSet();
        }

        spinAngelMultiplierReducer++;
        spinAngel += spinAngelMultiplier;

    }


    @Override
    public void actionPerformed(ActionEvent e) {
        spin();
        repaint();
    }

In this part of drawWheel() method;

                System.out.println(angel*i+spinAngel + " and " + (angel+extra));

                g2D.setFont(new Font("Ariel", Font.BOLD, 10));
                g2D.setColor(Color.black);
                int xMultiplier = -1;
                int yMultiplier = 1;
                if(angel*i+spinAngel >=0 && angel*i+spinAngel <180){
                    yMultiplier = -1;
                }if(angel*i+spinAngel >=270 && angel*i+spinAngel <90){
                    xMultiplier = 1;
                }
                int cosX = (int) ( Math.cos(angel+extra) );
                int sinY = (int) ( Math.cos(angel+extra) );
                int stringX = 300 + (xMultiplier * cosX);
                int stringY = 300 + (yMultiplier * sinY);
                g2D.drawString( inputs.get(i), stringX, stringY);

angel*i+spinAngel + " and " + (angel+extra)

What comes to mind when I look at these angle values is:

If the value of (angle * i + spinAngel) is greater than 0 and less than 180, I should set yMultiplier to -1. Because this means that the desired Arc is located on the upper side of the circle, and I need to write the String on the upper side of the circle.

I applied the same thought process to xMultiplier, but I couldn't achieve the desired result.

1 Answer 1

0

Ensure that the angle is split in half horizontally. Then just draw the string horizontally from the angle pivot. You can then rotate the graphics context and draw the next arc and string. This demo shows a single "wedge." The computations for positioning the String are in the comments.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class RotatingAndCentering extends JPanel {
    JFrame f = new JFrame();
    int width = 500;
    int height = 500;
    int i = 0;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new RotatingAndCentering().start());
    }

    public void start() {
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
       
        int inc = 1;
        Timer t = new Timer(0, (ae) -> {
            i += inc;
            if (i >= 360) {
                i -= 360;
            }
            f.repaint();
        });
        t.setDelay(25);
        t.start();
    }
    public Dimension getPreferredSize() {
        return new Dimension(width, height);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.RED);
        int startAngle = -36; // counter clockwise
        int extent = 72; // clockwise
        int w = width - 100;
        int h = height - 100;
        int xOrigin = 50;
        int yOrigin = 50;
        g2d.rotate(Math.toRadians(i), width/2, height/2);
        g2d.fillArc(xOrigin, yOrigin, w, h, startAngle, extent);

        String s = "This should be centered";
        g2d.setColor(Color.BLACK);
        Font f = new Font("Arial", Font.BOLD, 14);
        g2d.setFont(f);
        // fontmetrics is used to compute String width and height for help in centering.
        FontMetrics fm = g2d.getFontMetrics();
        // 250 is the width of the panel.
        // 200 is half length of the arc.
        // so 250 - (200 + s.length())/2 should be x for center
        // then slightly adjust the baseline by add half the string height.
        int strX = width / 2
                + (w/2  - SwingUtilities.computeStringWidth(fm, s))/2;
        int strY = height/2 + fm.getHeight()/2;
        
        g2d.drawString(s, strX, strY);
        
    }

}

Note: Instead of rotating what you're drawing, you can rotate the graphics context and then draw everything the same each time. Only the angle changes.

It's like rotating a white board x radians about a center, drawing a horizontal line from that center point, then rotating back to it's previous position. As x changes, the line seems to rotate about the center.

Also, most of the calculations should be done outside of paintComponent to keep processing on the EDT at a minimum.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.