Question

I'm happy with the output of my clock, however - I am not sure how to properly align my drawString for the numbers which should appear at the tip of each tick mark on the clock. I am hoping someone might be able show the proper method/formula for this.

    private void drawTickMarks(Graphics2D g2)
    {
     double radius = this.faceRadius;

     for (int secs = 0; secs <= 60; secs++)
     {
         double tickStart;

         if (secs % 5 == 0)
             tickStart = radius - 15;
          else
             tickStart = radius - 5;

         tick = drawRadii(secs / 60.0, tickStart, radius);

         if (secs % 5 == 0)
            {
             g2.setStroke(new BasicStroke(3));

                g2.drawString(""+(secs/5),(int)tick.getX1()+(int)(tick.getX1()-tick.getX2()),
                                                  (int)tick.getY1()+(int)(tick.getY1()-tick.getY2()));
            }
         else
             g2.setStroke(new BasicStroke(1));


         g2.setColor(Color.WHITE);
         g2.draw(tick);
     }
    }

Thanks to Thinhbk for a valid and correct solution with code and Jon W for the proper steps of coming to a solution.

Was it helpful?

Solution

As a supplemental to the solution provided by Jon W, I create a method that calculate the offset, and IMO, it looks fine. (@Jon W: sorry for not adding comment to your solution as it's rather long.)

 /**
     * Calculate the offset     * 
     * @param i
     * @return array: 
     * 0: x offset
     * 1: y offset
     */
    private int[] calculateOffSet(int i) {
        int[] val = new int[2];
        int deflt = -12;
        if(i == 12) {
            val[0] = -15;
            val[1] = 9;
        }else if (i > 6) {
            val[0] = deflt + i - 6 ;
            val[1] = i ;
        }else {
            val[0] = deflt + i ;
            val[1] = i + 6;         
        }
        return val;
    }

And in your code, just call this:

int xLocation = (int)tick.getX1()+(int)(tick.getX1()-tick.getX2());
int yLocation = (int)tick.getY1()+(int)(tick.getY1()-tick.getY2());
int[] offset = calculateOffSet((secs / 5));
g2.drawString(number, xLocation + offset[0], yLocation + offset[1]);

OTHER TIPS

If you imagine the String enclosed within a box, the x and y values you pass into drawString specify the lower left corner of the box.

I would modify the drawString line as such:

String number = ""+(secs/5);
int xLocation = (int)tick.getX1()+(int)(tick.getX1()-tick.getX2());
int yLocation = (int)tick.getY1()+(int)(tick.getY1()-tick.getY2());
int offsetX = /*Insert some value here to shift the position of all the strings
                along the x-axis. Make this an expression that contains number.length(),
                so that two-digit numbers are shifted more than one digit numbers. */
int offsetY = /*Insert some value here to shift the position of all the strings along
                the y-axis.*/
g2.drawString(number, xLocation + offsetX, yLocation + offsetY);

You'll have to play around with the specific values for offsetX and offsetY to make it look nice.

If you want to be even fancier and make it so that drawString will automatically adjust the location depending on what font is being used, take a look at this and the FontMetrics class. You'll want to make offsetX and offsetY vary depending on width and height of the characters being drawn and whatnot.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top