PDA

View Full Version : [Java SE] Display a 7 Segmenti,come?


Roran
27-03-2010, 10:17
Raga,ho cercato su una marea di siti sia italiani che inglesi ma non sono riuscito a trovare niente riguardo il display a 7 segmenti,sapete quale metodo permette di mostrarlo su una finestra grafica?che package va importato?

lupoxxx87
27-03-2010, 10:52
non fai prima a crearti 7 rettangoli e poi decidere quali far vedere e quali no ?

Roran
27-03-2010, 10:54
non fai prima a crearti 7 rettangoli e poi decidere quali far vedere e quali no ?ho iniziato il java da 2 settimane appena,quindi non sono molto esperto

PGI-Bis
27-03-2010, 17:14
E' un componente piuttosto specifico, devi crealo da solo. E' un questione elementare (nel senso che è fatta di tante piccole parti relativamente facili). Ad esempio questo:

http://www.tukano.it/ssd.png

è generato dalla combinazione di questi tre tipi in un Main:

SSDModelListener.java
package sevensegmentdisplay;

/**
* Ascoltatore di eventi generati dal modello di un display a sette segmenti.
*/
public interface SSDModelListener {

/**
* Gestisce una notifica di aggiornamento inviato da un modello
* @param model il modello che è stato aggiornato
*/
public void update(SSDModel model);
}

SSDModel.java
package sevensegmentdisplay;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import static sevensegmentdisplay.SSDModel.State.ON;
import static sevensegmentdisplay.SSDModel.State.OFF;

/**
* Modello di un component SevenSegmentDisplay.
*/
public class SSDModel {

/**
* Identificatori dei segmenti di un display a sette segmenti. Vedi
* http://en.wikipedia.org/wiki/File:7_segment_display_labeled.svg
*/
public static enum SSDSegment {
A, B, C, D, E, F, G, DP
}

/**
* Lo stato attivo-inattivo di un segmento.
*/
public static enum State {
ON, OFF
}

/**
* Utilità per la definizione dell'insieme di stati che creano una lettera o una
* cifra.
*/
private static class StatePack {
private State[] states;
StatePack(State...states) {
this.states = states;
}
void apply(Map<SSDSegment, State> map) {
for (int i = 0; i < SSDSegment.values().length; i++) {
SSDSegment seg = SSDSegment.values()[i];
map.put(seg, states[i]);
}
}
}

private Map<SSDSegment, State> states = new HashMap<SSDSegment, State>();
private List<SSDModelListener> listeners = new CopyOnWriteArrayList<SSDModelListener>();
private Map<String, StatePack> packs = new HashMap<String, StatePack>();

/**
* inizializza questo modello per display a sette segmenti.
*/
public SSDModel() {
for (SSDSegment s : SSDSegment.values()) {
states.put(s, State.OFF);
}
packs.put("a", new StatePack(ON, ON, ON, ON, ON, OFF, ON, OFF));
packs.put("b", new StatePack(ON, ON, ON, ON, ON, ON, OFF, OFF));
packs.put("c", new StatePack(ON, OFF, OFF, ON, ON, ON, OFF, OFF));
packs.put("d", new StatePack(OFF, ON, ON, ON, ON, OFF, ON, OFF));
packs.put("e", new StatePack(ON, OFF, OFF, ON, ON, ON, ON, OFF));
packs.put("1", new StatePack(OFF, ON, ON, OFF, OFF, OFF, OFF, OFF));
packs.put("2", new StatePack(ON, ON, OFF, ON, ON, OFF, ON, OFF));
packs.put("3", new StatePack(ON, ON, ON, ON, OFF, OFF, ON, OFF));
packs.put("4", new StatePack(OFF, ON, ON, OFF, OFF, ON, ON, OFF));
packs.put("5", new StatePack(ON, OFF, ON, ON, OFF, ON, ON, OFF));
packs.put("6", new StatePack(ON, OFF, ON, ON, ON, ON, ON, OFF));
packs.put("7", new StatePack(ON, ON, ON, OFF, OFF, OFF, OFF, OFF));
packs.put("8", new StatePack(ON, ON, ON, ON, ON, ON, ON, OFF));
packs.put("9", new StatePack(ON, ON, ON, ON, OFF, ON, ON, OFF));
packs.put("0", new StatePack(ON, ON, ON, ON, ON, ON, OFF, OFF));
packs.put(".", new StatePack(OFF, OFF, OFF, OFF, OFF, OFF, OFF, ON));
packs.put("err", new StatePack(ON, ON, ON, ON, ON, ON, ON, ON));
packs.put("off", new StatePack(OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF));
}

/**
* Imposta lo stato corrente del modello.
* @param c un carattere o una combinazione di caratteri. Se il carattere
* non è riconosciuto il modello mostra un errore (tutti i segmenti saranno
* attivati). La stringa "err" imposta il modello su errore, la stringa "off"
* imposta il modello su off.
*/
public void setState(String c) {
StatePack pack = packs.get(c);
if(pack != null) {
pack.apply(states);
} else {
packs.get("err").apply(states);
}
fireEvent();
}

/**
* Imposta lo stato di un singolo segmento
* @param s il segmento da impostare
* @param state lo stato di quel segmento
*/
public void setState(SSDSegment s, State state) {
states.put(s, state);
}

/**
* Restituisce lo stato di un segmento
* @param s il segmento richiesto
* @return lo stato del segmento richiesto
*/
public State getState(SSDSegment s) {
return states.get(s);
}

/**
* Notifica un evento update a tutti gli ascoltatori
*/
protected void fireEvent() {
for (SSDModelListener listener : listeners) {
listener.update(this);
}
}

/**
* Aggiunge un ascoltatore di eventi a questo modello
* @param listener l'ascoltatore di eventi da aggiungere
*/
public void addListener(SSDModelListener listener) {
listeners.add(listener);
}

/**
* Rimuove un ascoltatore di eventi da questo modello
* @param listener l'ascoltatore di eventi da rimuovere
*/
public void removeListener(SSDModelListener listener) {
listeners.remove(listener);
}
}

SevenSegmentDisplay.java
package sevensegmentdisplay;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JComponent;

/**
* Display a sette segmenti.
*/
public class SevenSegmentDisplay extends JComponent {
/**
* Creatore di istanze. Crea e restituisce un nuovo SevenSegmentDisplay
* @return un nuovo display a sette segmenti.
*/
public static SevenSegmentDisplay newInstance() {
final SevenSegmentDisplay d = new SevenSegmentDisplay();
d.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
d.model.addListener(new SSDModelListener() {

public void update(SSDModel model) {
d.repaint();
}
});
return d;
}

private Paint displayBackground = Color.BLACK;
private Paint off = Color.DARK_GRAY;
private Paint on = Color.RED;
private SSDModel model = new SSDModel();

/**
* Inizializzazione protetta: per creare un SevenSegmentDisplay usare il metodo
* SevenSegmentDisplay.newInstance
*/
protected SevenSegmentDisplay() {}

/**
* Imposta il colore di sfondo del display
* @param p il colore di sfondo del display
*/
public void setDisplayBackgroundPaint(Paint p) {
if(p != null) {
displayBackground = p;
} else {
Logger.getLogger(getClass().getName()).log(Level.INFO, "Display Background cannot be null.");
}
}

/**
* Imposta il colore usato per i segmenti attivi
* @param p il colore per i segmenti attivi
*/
public void setSegmentOnPaint(Paint p) {
if(p != null) {
on = p;
} else {
Logger.getLogger(getClass().getName()).log(Level.INFO, "Segment on paint cannot be null.");
}
}

/**
* Imposta il colore usato per i segmenti non attivi
* @param p il colore per i segmenti non attivi.
*/
public void setSegmentOffPaint(Paint p) {
if(p != null) {
off = p;
} else {
Logger.getLogger(getClass().getName()).log(Level.INFO, "Segment off paint cannot be null");
}
}

/**
* Restituisce la dimensione preferita di questo display. Se il display non
* ha una dimensione preferita impostata, restituisce una dimension predefinita.
* @return la dimensione preferita di questo display.
*/
@Override
public Dimension getPreferredSize() {
Insets ins = getInsets();
Dimension pref = super.getPreferredSize();
if(pref == null || pref.getWidth() <= 1 || pref.getHeight() <= 1) {
return new Dimension(100 + ins.left + ins.right, 84 + ins.top + ins.bottom);
} else {
System.out.println("PD: " + pref);
return pref;
}
}

/**
* Disegna il contenuto di questo componente
* @param graphics il contesto grafico da usare per il disegno
*/
@Override
protected void paintComponent(Graphics graphics) {
JComponent comp = this;
Insets ins = comp.getInsets();
double ch = comp.getHeight();
double cw = comp.getWidth();
double x0 = ins.left;
double y0 = ins.top;
double x1 = cw - ins.right;
double y1 = ch - ins.bottom;
double w = x1 - x0;
double h = y1 - y0;
double qw = w / 6;
double qh = h / 5;
double hqw = qw / 2;
double hqh = qh / 2;
double qw4 = 4 * qw;
Point2D a = pt(hqw + x0, hqh + y0);
Point2D b = pt(qw4 + x0, hqh + y0);
Point2D c = pt(hqw + x0, ch / 2);
Point2D d = pt(qw4 + x0, ch / 2);
Point2D e = pt(hqw + x0, y1 - hqh);
Point2D f = pt(qw4 + x0, y1 - hqh);
Point2D g = pt(w - hqw, y1 - hqh);
double segWidth = 8;
double segHeight = 8;
Shape dp = new Ellipse2D.Double(g.getX() - hqw, f.getY() - segHeight, 2 * segWidth, 2 * segHeight);
Shape segA = new SegmentShapeBuilder(a, b, segWidth, segHeight).getShape();
Shape segB = new SegmentShapeBuilder(b, d, segWidth, segHeight).getShape();
Shape segC = new SegmentShapeBuilder(d, f, segWidth, segHeight).getShape();
Shape segD = new SegmentShapeBuilder(f, e, segWidth, segHeight).getShape();
Shape segE = new SegmentShapeBuilder(e, c, segWidth, segHeight).getShape();
Shape segF = new SegmentShapeBuilder(c, a, segWidth, segHeight).getShape();
Shape segG = new SegmentShapeBuilder(c, d, segWidth, segHeight).getShape();
Graphics2D graphics2D = (Graphics2D) graphics;
graphics2D.setPaint(displayBackground);
graphics2D.fillRect(0, 0, getWidth(), getHeight());
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
setPaint(SSDModel.SSDSegment.A, graphics2D);
graphics2D.fill(segA);
setPaint(SSDModel.SSDSegment.B, graphics2D);
graphics2D.fill(segB);
setPaint(SSDModel.SSDSegment.C, graphics2D);
graphics2D.fill(segC);
setPaint(SSDModel.SSDSegment.D, graphics2D);
graphics2D.fill(segD);
setPaint(SSDModel.SSDSegment.E, graphics2D);
graphics2D.fill(segE);
setPaint(SSDModel.SSDSegment.F, graphics2D);
graphics2D.fill(segF);
setPaint(SSDModel.SSDSegment.G, graphics2D);
graphics2D.fill(segG);
setPaint(SSDModel.SSDSegment.DP, graphics2D);
graphics2D.fill(dp);
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT);
}

/**
* Restituisce il modello di questo display a sette segmenti
* @return il modello di questo display a sette segmenti
*/
public SSDModel getModel() {
return model;
}

/* metodo di appoggio, imposta un colore in base allo stato di un segmento */
private void setPaint(SSDModel.SSDSegment s, Graphics2D g) {
g.setPaint(paintForSegment(s));
}

/* metodo di appoggio, restituisce un colore in base allo stato di un segmento */
private Paint paintForSegment(SSDModel.SSDSegment s) {
return model.getState(s) == SSDModel.State.ON ? on : off;
}

/* metodo di appoggio, istanzia un Point2D.Double */
private static Point2D pt(double x, double y) {
return new Point2D.Double(x, y);
}
}

Main.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package sevensegmentdisplay;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;

/**
*
* @author pgi
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {
JFrame win = new JFrame("test");
win.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final SevenSegmentDisplay display = SevenSegmentDisplay.newInstance();
display.addMouseListener(new MouseAdapter() {
int number = 0;
String loop = "0123456789.";
public void mousePressed(MouseEvent e) {
number++;
if(number == loop.length()) number = 0;
display.getModel().setState(loop.substring(number, number + 1));
}
});
win.add(display);
win.pack();
win.setVisible(true);
display.getModel().setState("0");
}
});
}

}

PGI-Bis
27-03-2010, 18:57
Pardon, 4 tipi più un main (ne avevo dimenticato uno):

SegmentShapeBuilder.java
package sevensegmentdisplay;

import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;

/**
* Crea una figura corrispondente ad un segmento di un display a sette segmenti.
*/
public class SegmentShapeBuilder {

/**
* Utilita per il calcolo di direzioni e spostamenti
*/
private static class Vector2D extends Point2D {
private double x, y;
private double norm;

Vector2D(double x, double y) {
norm = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
this.x = x / norm;
this.y = y / norm;
}

Vector2D(Point2D a, Point2D b) {
this(b.getX() - a.getX(), b.getY() - a.getY());
}

/**
* Restituisce una nuova direzione ortogonale a quella espressa da questo vettore
* @return un vettore ortogonale a questo
*/
Vector2D ortho() {
return new Vector2D(-y, x);
}

@Override
public double getX() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public double getY() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public void setLocation(double x, double y) {
throw new UnsupportedOperationException("Not supported yet.");
}

/**
* Genera la traslazione di un punto lungo la direttrice espressa da questa
* direzione
* @param p il punto da traslare
* @param len la quantità di spostamento
* @return un punto p pari a p traslato di len nella direzione espressa da questo vettore
*/
public Point2D translate(Point2D p, double len) {
return new Point2D.Double(p.getX() + x * len, p.getY() + y * len);
}
}

/* figura geometrica generata da questo creatore di segmenti */
private final Path2D SHAPE;

/**
* Initializza questo generatore di segmenti
* @param a il punto da cui parte il segmento
* @param b il punto in cui termina il segmento
* @param sizeX l'ampiezza assiale della punta del segmento
* @param sizeY l'ampiezza ortogonale dell'estremita del segmento
*/
public SegmentShapeBuilder(Point2D a, Point2D b, double sizeX, double sizeY) {
Vector2D dir = new Vector2D(a, b);
Vector2D ortho = dir.ortho();
a = dir.translate(a, 2);
b = dir.translate(b, -2);
Point2D f0 = dir.translate(a, sizeX);
Point2D f1 = dir.translate(b, -sizeX);
Point2D p0 = a;
Point2D p1 = ortho.translate(f0, -sizeY);
Point2D p2 = ortho.translate(f1, -sizeY);
Point2D p3 = b;
Point2D p4 = ortho.translate(f1, sizeY);
Point2D p5 = ortho.translate(f0, sizeY);
Path2D.Double shape = new Path2D.Double();
shape.moveTo(p0.getX(), p0.getY());
shape.lineTo(p1.getX(), p1.getY());
shape.lineTo(p2.getX(), p2.getY());
shape.lineTo(p3.getX(), p3.getY());
shape.lineTo(p4.getX(), p4.getY());
shape.lineTo(p5.getX(), p5.getY());
shape.closePath();
SHAPE = shape;
}

/**
* Restituisce la figura geometrica generata da questo creatore di segmenti
* sulla base dei dati forniti in costruzione
* @return la figura di un segmento
*/
public Shape getShape() {
return SHAPE;
}
}

Roran
27-03-2010, 20:55
Grazie mille appena ho un attimo lo provo,una domanda: devo creare proprio un package?

PGI-Bis
27-03-2010, 21:00
Non è fisicamene obbligatorio ma di solito un progetto ha sempre un package di base per questioni organizzative e di identità dei tipi.

Roran
28-03-2010, 17:11
Ho provato il codice su eclipse,ha funzionato da subito,ora mi chiedevo: se voglio aggiungere un altro display affianco a quello che già c'è,oltre a scrivere
final SevenSegmentDisplay display2 = SevenSegmentDisplay.newInstance();
e
win.add(display2);
che metodo devo usare per spostare questo secondo display affianco al primo invece che dietro?

PGI-Bis
28-03-2010, 17:40
Puoi usare un contenitore intermedio. Tipo:

SevenSegmentDisplay d0 = ...
SevenSegmentDisplay d1 = ...
JPanel contenitore = new JPanel(new GridLayout(1, 2));//1 riga, 2 colonne
contenitore.add(d0);
contenitore.add(d1);
win.add(contenitore);

Magari sarebbe meglio creare una classe in grado di mostrare una sequenza di SevenSegmentDisplay, qualcosa che ti faccia dire:

MultiSSD d = new MultiSSD(2);//due SSD uno in fila all'altro
win.add(d);

anche perchè con più caratteri da mostrare sarebbe più immediato poter dire poi:

d.mostra("12536.25");

cioè passi a questo ipotetico MultiSSD una stringa e lui si occupa di affidare i caratteri ai singoli display di cui è composto.

Roran
28-03-2010, 17:54
credo che la seconda cosa sia un pò difficile per me al momento,all'uni non sono nemmeno arrivato a fare la grafica

PGI-Bis
28-03-2010, 17:55
Non era per un compito universitario, vero?

Roran
28-03-2010, 18:17
no assolutamente,poi la grafica ancora la deve spiegare il mio prof,sto chiedendo perchè volevo implementare un orologio che avevo fatto in C

PGI-Bis
29-03-2010, 01:35
La classe è in verità breve. Ovviamente all'inizio è sempre tutto un po' strano ma più o meno tutti i programmi java alla fine sono organizzati per piccoli blocci come quelli che abbiamo usato qui.

Nel nostro caso basta una nuova classe di 47 righe:

SSDPanel.java
package sevensegmentdisplay;

import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JPanel;

/**
* Una sequenza di SevenSegmentDisplay
*/
public class SSDPanel extends JPanel {
private SevenSegmentDisplay[] displays;
private int displayCount;

/**
* Inizializza un SSDPanel
* @param displayCount quanti display mostra il pannello
*/
public SSDPanel(int displayCount) {
super(new GridLayout(1, displayCount));//1 riga, display count colonne
//inizializzo l'array per ospitare displayCount componenti
displays = new SevenSegmentDisplay[displayCount];
//creo n SevenSegmentDisplay e li aggiungo a questo pannello, da sinistra a destra
for (int i = 0; i < displayCount; i++) {
SevenSegmentDisplay display = SevenSegmentDisplay.newInstance();
display.setSegmentOnPaint(Color.GREEN);
add(display);
displays[i] = display;
}
this.displayCount = displayCount;
}

/**
* Mostra del testo nel display. Il pannello mostra un numero di caratteri
* pari al numero di display presenti in questo pannello. Se ce ne sono
* in più, vengono ignorati.
* @param text il testo da mostrare.
*/
public void setText(String text) {
int max = Math.min(displayCount, text.length());
for(int i = 0; i < max; i++) {
String character = text.substring(i, i + 1);//prendo l'i-esimo carattere
displays[i].getModel().setState(character);
}
/* se ci sono meno caratteri che display bisogna azzerare quei display */
for(int i = max; i < displays.length; i++) {
displays[i].getModel().setState("off");
}
}
}

Si può testare con un timer:

Main.java
package sevensegmentdisplay;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.Timer;

/**
*
* @author pgi
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {
JFrame win = new JFrame("test");
win.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final SSDPanel display = new SSDPanel(5);
final Timer timer = new Timer(1000, new ActionListener() {
int now = 0;
public void actionPerformed(ActionEvent e) {
now += 1;
display.setText(String.valueOf(now));
}
});
win.addWindowListener(new WindowAdapter() {

@Override
public void windowOpened(WindowEvent e) {
timer.start();
}

@Override
public void windowClosing(WindowEvent e) {
timer.stop();
}
});
win.add(display);
win.pack();
win.setVisible(true);
}
});
}

}

Che genera:

http://www.tukano.it/ssdpanel.png

Per allineare i numeri a destra si può partire con l'assegnamento dei caratteri ai display non da 0 a max ma da displayCount - 1 a displayCount - max.

Roran
29-03-2010, 10:44
Grazie ancora,ma se volessi disegnare i due punti tra ogni coppia di numeri?cioè in questo modo ore:minuti:secondi è possibile?Bisognerebbe creare solo una classe con due cerchi riempiti e spostati sugli assi?

PGI-Bis
29-03-2010, 17:50
Alla fine sì. Praticamente in SSDPanel ogni due SevenSegmentDisplay metti un ColonDisplay (per dire un nome) dove ColonDisplay è una classe che estende JComponent e nel suo metodo "paintComponent" disegna due cerchi. In pseudocodice:

class ColonDisplay extends JComponent {

@Override
protected void paintComponent(Graphics graphics) {
Graphics2D g = (Graphics2D) graphics;
g.setPaint(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());//sfondo nero
Shape dot01 = new Ellipse2D.Double(x0, y0, w, h);
Shape dot02 = new Ellipse2D.Double(x1, y1, w, h);
g.setPaint(Color.GREEN);
g.fill(dot01);
g.fill(dot02);
}
}

In SSDPanel avrai una cosa tipo:

//costruttore, pseudo codice
public SSDPanel(int displayCount) {
super(new GridLayout(1, displayCount + (1 colonPanel ogni 2 displayCount)));
for(...il numero di display count) {
ogni due display aggiungi un nuovo ColonPanel
}
}

Per calcolare la posizione dei due punti in ColonDisplay devi fare due conti. Nel metodo paintComponent sai che getWidth() ti dice quanto è largo il componente in cui stai disegnando e getHeight() ti dice quanto è alto. Sai che il sistema di coordinate Java2D stabilisce che il punto (x = 0, y = 0) è in alto a sinistra. Il costruttore di un ellisse (Ellipse2D.Double(x, y, w, h)) vuole come argomento un rettangolo in cui sarà iscritta l'ellisse: x è l'ascissa del punto di partenza del rettangolo, y è l'ordinata, w indica quanto è lungo e h quanto è alto quel rettangolo. Il punto di partenza è il vertice in alto a sinistra.

Così se vuoi centrare i pallini sulle ascisse parti dicendo che:

double xm = getWidth() / 2;

è l'asse verticale che divide in due il componente in lunghezza. Se i pallini devono avere un diametro di, poniamo, 20 pixel, allora l'ascissa del quadrato in cui è iscritta l'ellisse di entrambi i pallini è:

double x0 = xm - (20 / 2);
double x1 = xm - (20 / 2);

per l'ordinata devi vedere dove vuoi metterli, sempre tenendo come riferimento le dimensioni del componente su cui stai disegnando. Ad esempio se vuoi metterli ad un terzo e due terzi dell'altezza:

double h = getHeight();
double y0 = h / 3.0 - (20 / 2);//sempre per via dell'iscrizione nel rettangolo
double y1 = 2.0 * h / 3.0 - (20 / 2);

Quindi avrai:

Shape dp0 = new Ellipse2D.Double(x0, y0, 20, 20);
Shape dp1 = new Ellipse2D.Double(x1, y1, 20, 20);

Puoi fare delle considerazioni di proporzionalità anche sulla largezza dei pallini. Diciamo che vuoi farli grandi un decimo delle dimensioni del componente. Dirai (sempre conti fatti nel paintComponent):

double w = getWidth() / 10.0;
double h = getHeight() ( 10.0;
double x0 = xm - (w/ 2);
double x1 = xm - (w/ 2);
double y0 = getWidth() / 3.0 - (w/ 2);
double y1 = 2.0 * getHeight() / 3.0 - (h/ 2);
Shape dp0 = new Ellipse2D.Double(x0, y0, w, h);
Shape dp 1 = new Ellipse2D.Double(x1, y1, w, h);

In definitiva devi fare un paio di conti e qualche prova.

Roscoe90
29-03-2010, 18:59
Io non saprei come aiutare Roran sto alle prima armi con java (allora che ho scritto a fare, bah il cervello umano è un oragano strano)