# 7-Segment-Anzeige



## Leroy42 (27. Feb 2007)

Hallo,

Kennt einer von euch ein pluggable Java-Package, daß eine 
7-Segment-Anzeige visualisiert? Es sollte nicht nur die 10 Ziffern
anzeigen können, sondern die Segmente sollten separat ansteuerbar sein.

Auch wäre es gut, wenn die Anzeige in ihrer Größe skalierbar wäre.


Ich könnte das zwar selbst programmieren, dann müßte mein
Arbeitstag allerdings auf 20 h erweitert werden *und* ich könnte
in diesem Forum nicht mehr mein Unwesen treiben.


----------



## Wildcard (27. Feb 2007)

Nimm doch das als Basis:
http://www.addison-wesley.de/Service/Krueger/kap23002.htm


----------



## Chris_1980 (27. Feb 2007)

Find ich interessant, und dazu noch nützlich als Punkteanzeige in meinem Jcanoid-Projekt. 
Ich schreib mal eben eine.  :wink:


----------



## Chris_1980 (27. Feb 2007)

```
/**
 * SiebenSegmentAnzeige
 * by Christian Götz
 * 27.02.2007
 * 
 * 
 * Eine Siebensegmentanzeige in Form einer Swingkomponente  
 * Das ideale Größenverhältnis der Anzeige ist width/height = 12/20
 */




import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.geom.*;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;


public class SiebenSegmentAnzeige extends JPanel {
	
	public static final float MIN_WIDTH = 12, MIN_HEIGHT = 20;
	
	private static final boolean[] 
	              NUMBER_0 = new boolean[] {true, true, true, true, true, true, false},
	              NUMBER_1 = new boolean[] {false, true, true, false, false, false, false},
	              NUMBER_2 = new boolean[] {true, true, false, true, true, false, true},
	              NUMBER_3 = new boolean[] {true, true, true, true, false, false, true},
				  NUMBER_4 = new boolean[] {false, true, true, false, false, true, true},  
				  NUMBER_5 = new boolean[] {true, false, true, true, false, true, true},
				  NUMBER_6 = new boolean[] {true, false, true, true, true, true, true},
				  NUMBER_7 = new boolean[] {true, true, true, false, false, true, false},
				  NUMBER_8 = new boolean[] {true, true, true, true, true, true, true},
				  NUMBER_9 = new boolean[] {true, true, true, true, false, true, true};  
	          
	private boolean[] segment = NUMBER_0.clone();
	
	private boolean paintSegmentBorder = true;
	private Color borderColor = Color.GRAY;
	
	
	public SiebenSegmentAnzeige()
	{
		super();
		init();
	}

	public SiebenSegmentAnzeige(boolean isDoubleBuffered)
	{
		super(isDoubleBuffered);
		init();
	}

	public SiebenSegmentAnzeige(LayoutManager layout, boolean isDoubleBuffered)
	{
		super(layout, isDoubleBuffered);
		init();
	}

	public SiebenSegmentAnzeige(LayoutManager layout)
	{
		super(layout);
		init();
	}

	private void init()
	{
		setForeground(Color.RED);
		setSize((int)MIN_WIDTH, (int)MIN_HEIGHT);
		setPreferredSize(new Dimension((int)MIN_WIDTH*2, (int)MIN_HEIGHT*2));
		setMinimumSize(new Dimension((int)MIN_WIDTH, (int)MIN_HEIGHT));		
	}
	
	
	/**Malt einen Rahmen um die einzelnen Segmente. Die Farbe kann mit setSegmentBorderColor(Color c) eingestellt werden. 
	 * 
	 * @param b
	 */
	public void paintSegmentBorder(boolean b)
	{
		paintSegmentBorder = b;
	}
	
	
	/** gibt true zurück wenn ein Rahmen um die Segmente gezeichnet wird. 
	 * 
	 * @return
	 */
	public boolean isPaintingSegmentBorder()
	{
		return paintSegmentBorder;
	}
	
	
	/** gibt die Farbe des Segmentrahmen zurück.
	 * 
	 * @return  die Farbe des Segmentrahmen.
	 */ 
	public Color getSegmentBorderColor()
	{
		return borderColor;
	}
	
	/** setzt die Farbe des Segmentrahmen.
	 * 
	 * @param c  die Farbe des Segmentrahmen.
	 */
	public void setSegmentBorderColor(Color c)
	{
		borderColor = c;		
		repaint();
	}
	
	/** läßt die Anzeige eine Zahl zwischen 0 und 9 anzeigen. 
	 * 
	 * @param num
	 */
	public void showNumber(int num)
	{
		if(num < 0) num = 0;
		else if(num > 9) num = 9;
		
		switch(num)
		{
			case 0:
				segment = NUMBER_0.clone();
			break;
			
			case 1:
				segment = NUMBER_1.clone();
			break;
				
			case 2:
				segment = NUMBER_2.clone();
			break;
				
			case 3:
				segment = NUMBER_3.clone();
			break;
				
			case 4:
				segment = NUMBER_4.clone();
			break;
				
			case 5:
				segment = NUMBER_5.clone();	
			break;
					
			case 6:
				segment = NUMBER_6.clone();
			break;

			case 7:
				segment = NUMBER_7.clone();
			break;

			case 8:
				segment = NUMBER_8.clone();
			break;

			case 9:
				segment = NUMBER_9.clone();
			break;				
		}		
		repaint();
	}
	
	
	
	
	/** schaltet ein einzelnes Segment (0-6) ein oder aus
	 * 
	 * @param segment  das Segment das geschaltet werden soll
	 * @param state  true schaltet das Segment ein, false aus.
	 */	 
	public void setSegment(int segment, boolean state)
	{
		if(segment < 0) segment = 0;
		else if(segment > 6) segment = 6;
		
		this.segment[segment] = state;
		
		repaint();
	}
	
	/** schaltet alle 7 Segmente an oder aus.
	 * 
	 * @param state  true schaltet die Segmente ein, false aus.
	 */
	public void setAllSegments(boolean state)
	{
		for (int i=0 ; i<7 ; i++)
		{
			segment[i] = state;
		}
		repaint();
	}
	
	
	/** zeigt eine Counteranimation. Es wird von der Zahl from 
	 * bis einschließlich der Zahl too gezählt. 
	 * 
	 * @param from  Die Zahl von der aus gezählt wird.
	 * @param to  Die Zahl bis zu der einschließlich gezählt wird.
	 * @param delayInMilliSeconds   Die Zeit die zwischen den einzelnen Zählschritten gewartet 
	 * 								wird in Millisekunden.  
	 * @param extraThread  wenn true wird der Counter in einem eigenen Thread gestarted.
	 */
	public void showCounter(int from, int to, final int delayInMilliSeconds, boolean extraThread)
	{
		if(from < 0) from = 0;
		else if(from > 9) from = 9;
		
		if(to < 0) to = 0;
		else if(to > 9) to = 9;
		
		if(from != to)
		{
			int d;
			if(from < to) d = 1;
			else d = -1;
			
			final int f = from, t = to, direction = d;
			
			Thread thread = new Thread(new Runnable() 
			{
				public void run()
				{
					for(int num=f ; num != t+direction ; num += direction)
					{
						showNumber(num);
						
						try {Thread.sleep(delayInMilliSeconds);}catch(InterruptedException e) {}						
					}
				}
			});
			
			if(extraThread) thread.start();
			else thread.run();
		}
	}
	
	
	
	
	
	
	

	@Override
	public void paintComponent(Graphics gr)
	{
		super.paintComponent(gr);
		Graphics2D g = (Graphics2D) gr;		
		
		for(int i=0 ; i<segment.length ; i++)
		{
			if(segment[i]) paintSegment(g, i);
		}
		

	}
	
	private void paintSegment(Graphics2D g, int segment)
	{
		
		switch(segment)
		{			
//			Horizontale Segmente:
			case 0:	
				paintHorizontalSegment(g, 0);				
			break;	
			
			case 6:
				paintHorizontalSegment(g, 8);				
			break;	
				
			case 3:
				paintHorizontalSegment(g, 16);				
			break;	
			
//			Vertikale Segmente:	
			case 5:
				paintVerticalSegment(g, 0, 0);
			break;
				
			case 1:
				paintVerticalSegment(g, 0, 8);
			break;
				
			case 4:
				paintVerticalSegment(g, 8, 0);
			break;
				
			case 2:
				paintVerticalSegment(g, 8, 8);
			break;
		}
	}
	
	private void paintHorizontalSegment(Graphics2D g, int row)
	{
		float fieldWidth = (getWidth())/12f;
		float fieldHeight = (getHeight())/20f;		
		
		Path2D.Float polygon1 = new Path2D.Float();
		Path2D.Float polygon2 = new Path2D.Float();		
		Path2D.Float border = new Path2D.Float();		
		Rectangle2D.Float rect = new Rectangle2D.Float();
		
		polygon1.moveTo(fieldWidth*2, fieldHeight*2 + row*fieldHeight);
		polygon1.lineTo(fieldWidth*3, fieldHeight + row*fieldHeight);
		polygon1.lineTo(fieldWidth*3, fieldHeight*3 + row*fieldHeight);
		polygon1.lineTo(fieldWidth*2, fieldHeight*2 + row*fieldHeight);
				
		rect.setRect(fieldWidth*3, fieldHeight + row*fieldHeight, 
				fieldWidth*6, fieldHeight*2);	
		
		polygon2.moveTo(fieldWidth*9, fieldHeight + row*fieldHeight);
		polygon2.lineTo(fieldWidth*10, fieldHeight*2 + row*fieldHeight);
		polygon2.lineTo(fieldWidth*9, fieldHeight*3 + row*fieldHeight);
		polygon2.lineTo(fieldWidth*9, fieldHeight + row*fieldHeight);
		
		
		g.setPaint(getForeground());
		g.fill(polygon1);
		g.fill(rect);
		g.fill(polygon2);
		
		
		if(paintSegmentBorder)
		{
			border.moveTo(fieldWidth*2, fieldHeight*2 + row*fieldHeight);
			border.lineTo(fieldWidth*3, fieldHeight + row*fieldHeight);
			border.lineTo(fieldWidth*9, fieldHeight + row*fieldHeight);
			border.lineTo(fieldWidth*10, fieldHeight*2 + row*fieldHeight);
			border.lineTo(fieldWidth*9, fieldHeight*3 + row*fieldHeight);
			border.lineTo(fieldWidth*3, fieldHeight*3 + row*fieldHeight);
			border.lineTo(fieldWidth*2, fieldHeight*2 + row*fieldHeight);
			
			g.setPaint(borderColor);
			g.draw(border);
		}
	}
	
	private void paintVerticalSegment(Graphics2D g, int row, int column)
	{		
		float fieldWidth = (getWidth())/12f;
		float fieldHeight = (getHeight())/20f;		
		
		Path2D.Float polygon1 = new Path2D.Float();
		Path2D.Float polygon2 = new Path2D.Float();		
		Path2D.Float border = new Path2D.Float();		
		Rectangle2D.Float rect = new Rectangle2D.Float();
		
		
		polygon1.moveTo(fieldWidth*2 + column*fieldWidth, fieldHeight*2 + row*fieldHeight);
		polygon1.lineTo(fieldWidth*3 + column*fieldWidth, fieldHeight*3 + row*fieldHeight);
		polygon1.lineTo(fieldWidth + column*fieldWidth, fieldHeight*3 + row*fieldHeight);
		polygon1.lineTo(fieldWidth*2 + column*fieldWidth, fieldHeight*2 + row*fieldHeight);
				
		rect.setRect(fieldWidth + column*fieldWidth, fieldHeight*3 + row*fieldHeight, 
				fieldWidth*2, fieldHeight*6);	
		
		polygon2.moveTo(fieldWidth + column*fieldWidth, fieldHeight*9 + row*fieldHeight);
		polygon2.lineTo(fieldWidth*3 + column*fieldWidth, fieldHeight*9 + row*fieldHeight);
		polygon2.lineTo(fieldWidth*2 + column*fieldWidth, fieldHeight*10 + row*fieldHeight);
		polygon2.lineTo(fieldWidth + column*fieldWidth, fieldHeight*9 + row*fieldHeight);
		
		
		g.setPaint(getForeground());
		g.fill(polygon1);
		g.fill(rect);
		g.fill(polygon2);
		
		
		
		if(paintSegmentBorder)
		{
			border.moveTo(fieldWidth*2 + column*fieldWidth, fieldHeight*2 + row*fieldHeight);
			border.lineTo(fieldWidth*3 + column*fieldWidth, fieldHeight*3 + row*fieldHeight);
			border.lineTo(fieldWidth*3 + column*fieldWidth, fieldHeight*9 + row*fieldHeight);
			border.lineTo(fieldWidth*2 + column*fieldWidth, fieldHeight*10 + row*fieldHeight);
			border.lineTo(fieldWidth + column*fieldWidth, fieldHeight*9 + row*fieldHeight);
			border.lineTo(fieldWidth + column*fieldWidth, fieldHeight*3 + row*fieldHeight);
			border.lineTo(fieldWidth*2 + column*fieldWidth, fieldHeight*2 + row*fieldHeight);
			
			g.setPaint(borderColor);
			g.draw(border);			
		}

	}
	
	
	
	/* Testing... ;-) */
	public static void main(String[] args)
	{
		JFrame frame = new JFrame("7-Segment");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(300, 300);
		
		JPanel cp = (JPanel) frame.getContentPane();
		cp.setLayout(null);
		
		SiebenSegmentAnzeige anz = new SiebenSegmentAnzeige();
		anz.setSize(anz.getPreferredSize());
		anz.setBorder(new LineBorder(Color.BLACK));
//		anz.setSize(120, 200);
		anz.setLocation(50, 50);
		cp.add(anz);		

		anz.setAllSegments(false);
		anz.setForeground(Color.CYAN);		
				
		frame.setVisible(true);
		
		
		for(int j = 0 ; j < 3 ; j++)
		{
			for(int i = 0 ; i < 6 ; i++)
			{
				anz.setSegment(i, true);
				if (i > 0) anz.setSegment(i - 1, false);				

				try
				{
					Thread.sleep(100);
				}
				catch (InterruptedException e)
				{
				}
			}
			anz.setAllSegments(false);
			
			switch(j)
			{
				case 0:
					anz.setForeground(Color.BLUE);
				break;
				
				case 1:
					anz.setForeground(Color.YELLOW);
				break;				
			}			
		}
		
		
		anz.setForeground(Color.RED);
		
		anz.showCounter(9, 0, 600, false);
		
		anz.showNumber(0);
		
		anz.setForeground(Color.BLUE);
		anz.setSegmentBorderColor(Color.CYAN);

		
	}
}
```






*EDIT:* Hab nochmal ne Kleinigkeit verändert,
ist jetzt nicht mehr so gequetscht und der Segmentrahmen überall sichtbar.


----------



## André Uhres (28. Feb 2007)

So:
private boolean[] segment = new boolean[7];
kommt auch die Null.


----------



## Chris_1980 (28. Feb 2007)

wie meinen?  :bahnhof:


----------



## André Uhres (28. Feb 2007)

So wie's dasteht, einfach mal ausprobieren..

Achso, in meine natürlich, daß bei mir die Null nicht dargestellt, aber mit dieser Änderung kommt sie dann  :wink:


----------



## Chris_1980 (28. Feb 2007)

Du meinst wenn man Zeile 44 wie von dir beschrieben abändert, würde standardmäßig auch die Zahl null angezeigt werden?

Nein. Wieso sollte sie auch.  ???:L


----------



## Leroy42 (28. Feb 2007)

Danke!

Ich bin dann mal so frei und klaue bei Chris1980


----------



## Chris_1980 (28. Feb 2007)

klar, viel spaß damit!   

(Achso, hatte noch n kleinen Schönheitsfehler, es macht keinen Sinn die finalen boolArrays public zu machen.)


----------



## André Uhres (28. Feb 2007)

Chris_1980 hat gesagt.:
			
		

> Du meinst wenn man Zeile 44 wie von dir beschrieben abändert, würde standardmäßig auch die Zahl null angezeigt werden?
> 
> Nein. Wieso sollte sie auch.  ???:L


Du meinst mit showNumber(0) soll einfach nix angezeigt werden? Das find ich aber komisch  :shock:


----------



## Chris_1980 (28. Feb 2007)

Sorry, ich weiß echt nicht was du sagen möchtest. Es funzt doch alles einwandfrei.

[EDIT]
OK, tut es nicht.   
Ein Array ist kein primitiver Typ, auch wenns mit solchen gefüllt ist.  :roll: 
Habs also geändert. 
Danke für den Hinweis, auch wenn du´s kaum Rätselhafter hätst ausdrücken können, wodrauf du eigentlich hinaus willst.  


@Leroy42, tu mal bitte den Code den du hast austauschen, ich hab da nen dumm gebaut gehabt...  :wink: 
[/EDIT]


----------



## André Uhres (28. Feb 2007)

@Chris_1980: Warum nicht gleich, ging ja lediglich um die Sichtbarkeit der Null  :wink:


----------



## Chris_1980 (28. Feb 2007)

jaja, manchmal steh ich halt was auf der Leitung. :roll: 
Aber mal so neben bei, ich find das eigentlich ein Unding, dass das Wörtchen final Objekte in keinster Weise vor Veränderung schützt. Da bin ich schonmal drauf reingefallen. :roll:


----------



## Wildcard (28. Feb 2007)

Wieso Unding? Wie dir vielleicht auffällt steht dieses Keyword final nicht vor einem Objekt, sondern vor einer Variablen  :wink:


----------



## André Uhres (1. Mrz 2007)

Chris_1980 hat gesagt.:
			
		

> ..Da bin ich schonmal drauf reingefallen. :roll:


Man muss sich halt einprägen, daß eine als *final *deklarierte (nicht primitive) Variable zwar nur
auf ein einziges Objekt zeigen kann, aber *das Objekt nicht vor Veränderungen schützt*:

im vorliegenden Fall zeigt NUMBER_0 zwar immer auf das gleiche Array, 
was aber nicht bedeutet, daß auch der Arrayinhalt immer gleich bleiben muss!



			
				Chris_1980 hat gesagt.:
			
		

> ..@Leroy42, tu mal bitte den Code den du hast austauschen, ich hab da nen dumm gebaut gehabt...  :wink:


Da mach dir mal keine Sorgen: Leroy42 ist Spezialist im Codebügeln


----------



## Leroy42 (1. Mrz 2007)

André Uhres hat gesagt.:
			
		

> Chris_1980 hat gesagt.:
> 
> 
> 
> ...



Danke für die Lorbeeren!

Ich muß jedoch gestehen, daß ich mittlerweile doch lieber Guido gebügelt habe.


----------

