"JSpinner" programmieren

Hallo!
Ich will mal einen etwas anderen JSpinner programmieren.
Und zwar will ich eine Art Dreh scheibe haben, die auf knopf druck nach links oder nach rechts zu einem bestimmten punkt weitergedreht wird,
und ein anderer Text zu sehen ist. (wie bei einer drehscheibe halt.)

Nun das Problem:

Wie soll ich den Text “rundherum” positionieren?
Klar ich kann das ganze mit einem einzigen Bild machen, aber geht das auch irgendwie mit java?
Ich müsste den Text ja sozusagen “als bogen schreiben” und das halt 5 mal am rand der scheibe.
Geht soetwas?

Vielen Dank!

Ich hatte mal eine Roulettescheibe gezeichnet, … es ist nicht genau das gleiche, geht aber so sehr in diese Richtung, dass ich es deswegen (und aus Prinzip) mal von “der anderen Seite” hier rüber rette:

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.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
 
 
class RouletteDrawTest
{
 
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                final RoulettePanel p = new RoulettePanel();
 
                Thread thread = new Thread(new Runnable()
                {
                    public void run()
                    {
                        double angle = 0;
                        while (true)
                        {
                            p.setRotationAngle(angle);
                            angle += 0.02;
 
                            try
                            {
                                Thread.sleep(20);
                            }
                            catch (InterruptedException e)
                            {
                                Thread.currentThread().interrupt();
                                return;
                            }
                        }
                    }
                });
                thread.start();
 
                f.getContentPane().add(p);
                f.setSize(600,600);
                f.setVisible(true);
            }
        });
    }
}
 
 
class RoulettePanel extends JPanel
{
    private static final int numbers[] = new int[]
    {
         0,32,15,19, 4,21, 2,25,17,34, 6,27,
        13,36,11,30, 8,23,10, 5,24,16,33, 1,
        20,14,31, 9,22,18,29, 7,28,12,35, 3,
        26
    };
 
    
    private double rotationAngleRad = 0.0;
    private Dimension currentSize = null;
    private Font currentFont = null;
    private Path2D currentSegment = null;
    
    public void setRotationAngle(double angleRad)
    {
        this.rotationAngleRad = angleRad;
        repaint();
    }
    
    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        double currentAngleRad = rotationAngleRad;
        
        int w = getWidth();
        int h = getHeight();
        Dimension size = getSize();
        
        g.setColor(Color.WHITE);
        g.fillRect(0,0,w,h);
 
        //g.setRenderingHint(
        //    RenderingHints.KEY_ANTIALIASING,
        //    RenderingHints.VALUE_ANTIALIAS_ON);
 
        int offsetX = 20;
        int offsetY = 20;
        int diameter = Math.min(w-2*offsetX,h-2*offsetY);
        int radius = diameter/2;
        int centerX = offsetX+radius;
        int centerY = offsetY+radius;
 
        if (!size.equals(currentSize))
        {
            int fontSize = (int)(radius * 0.1);
            currentFont = new Font("Serif", Font.BOLD, fontSize);
        }
        g.setFont(currentFont);
 
        double angleRadDelta = Math.PI * 2 / numbers.length;
        if (!size.equals(currentSize))
        {
            FontMetrics fontMetrics = g.getFontMetrics();
            int fontHeight = fontMetrics.getHeight();
            currentSegment = createSegment(
                centerX, centerY, radius-fontHeight,
                radius, -angleRadDelta/2, angleRadDelta/2);
        }
        FontRenderContext fontRenderContext = 
            new FontRenderContext(null, true, true);
        for (int i=0; i<numbers.length; i++)
        {
            double angleRad = currentAngleRad + i * angleRadDelta;
            if (i==0)
            {
                g.setColor(new Color(0,192,0));
            }
            else if ((i&1)==1)
            {
                g.setColor(Color.RED);
            }
            else
            {
                g.setColor(Color.DARK_GRAY);
            }
 
            AffineTransform rotationAT = 
                AffineTransform.getRotateInstance(angleRad, centerX, centerY);
            g.fill(rotationAT.createTransformedShape(currentSegment));

            g.setColor(Color.WHITE);
            String numberString = String.valueOf(numbers**);
            GlyphVector glyphVector = currentFont.createGlyphVector(
                fontRenderContext, numberString);
            Shape textShape = glyphVector.getOutline();
            AffineTransform textAT = new AffineTransform(rotationAT);
            Rectangle2D sBounds = currentSegment.getBounds2D();
            Rectangle2D tBounds = textShape.getBounds2D();
            double dx = sBounds.getCenterX() - tBounds.getCenterX();
            double dy = sBounds.getCenterY() - tBounds.getCenterY();
            
            textAT.concatenate(AffineTransform.getTranslateInstance(dx, dy));
            g.fill(textAT.createTransformedShape(textShape));
            
        }
    }
 
    private static Path2D createSegment(
        int centerX, int centerY, int innerRadius, int outerRadius,
        double angleRad0, double angleRad1)
    {
        Arc2D.Double arcInner = new Arc2D.Double(
            centerX-innerRadius, centerY-innerRadius,
            innerRadius*2, innerRadius*2,
            Math.toDegrees(angleRad0),
            Math.toDegrees(angleRad1-angleRad0), Arc2D.OPEN);
 
        Arc2D.Double arcOuter = new Arc2D.Double(
            centerX-outerRadius, centerY-outerRadius,
            outerRadius*2, outerRadius*2,
            Math.toDegrees(angleRad1),
            Math.toDegrees(angleRad0-angleRad1), Arc2D.OPEN);
 
        Path2D.Double path = new Path2D.Double();
        path.append(arcInner, true);
        path.append(arcOuter, true);
        path.closePath();
 
        AffineTransform at = AffineTransform.getRotateInstance(
            -Math.PI/2, centerX, centerY);
        path.transform(at);
 
        return path;
    }
 
}

Vielleicht hilft’s ja schon. Für weitere Aspekte der Spinner-Funktionalität (also alles, was über das reine Zeichnen hinausgeht) müßte man die Anforderungen noch genauer eingenzen und spezifizieren.

EDIT: Falls es darum geht, wirklich den TEXT “gebogen” zu schreiben, wie einen Halbkreis oben…


    L 
  A   L 
 H     O

… müßte man sich was anderes überlegen - meintest du sowas? (Da liegt auch schon ewig ein angefangenes Programm dafür auf meinem Desktop, aber da müßte noch etwas Arbeit reingesteckt werden…)

Hm vielen dank erstmal.
Dann könnte ich ja einfach bei einem “text” jeden einzelnen buchstaben einzeln drehen, oder? sodass der text dann an den rand passt… puh… gar nicht mal so einfach.
aber ich versuchs!

Btw: Deine “roulette” ruckelt bei mir fürchterlich :o)

Ja, genau darauf läuft es raus. Ich habe das Roulette-Ding mal etwas angepasst (das hatte ich damals nur innerhalb von einer Stunde hingehackt, nichts daran „gut“, „durchdacht“ oder „optimiert“ :o ). Erstens könnte es jetzt weniger ruckeln :wink: und zweitens wird dort auch das verwendet, was man bräuchte, um Text an einer Linie auszurichten: Man erzeugt für den Text einen GlyphVector, von dem man sich die Shapes jedes einzelnen Buchstaben abholen und entsprechend beliebig ausrichten kann.

Willst du den Text gebogen schreiben? Wenn ja warum? schreib Ihn ortogonal zum Mittelpunkt der Scheibe, so kenne ich das zumind. von den meisten die man so sieht. (Die Dinger im Shoppingcenter zBsp.).
Wenn du den Text biegen möchtest, dann musst du halt jeden Buchstaben einzeln durch Abstand und Ausrichtung zum Mittelpunkt zeichnen. Ist denke ich mal immer noch simpler als mit GlyphVector o.ä. rumzudoktorn.

Gruß Vanny

Hier mal ein paar Beispiele mit customized Strokes. Das Bsp. mit dem TextStroke nutzt GlyphVector. Der Code kann direkt verwendet werden um einen Text Text entlang einer Ellipse bzw. Arc zu zeichnen:
http://www.jhlabs.com/java/java2d/strokes/