I have a rectangle defined as coordinate system as shown below.I want to plot the point (-7.224,1002), but I am unable to create a formula with which I can plot corresponding to this value.I have provided a code for reference:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.DoubleSummaryStatistics;
import java.util.stream.Collectors;
import javax.swing.JComponent;
class PlotComponent extends JComponent {
private ArrayList<Point> points = new ArrayList<Point>();
int sum=0,count=0,count1=0;
int val=0,val1=0;
private Color gridColor=new Color(200,200,200,200);
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int x_start_point=(int)(getWidth()*0.1);
int x_end_point=(int)(getWidth()*0.8);
int y_start_point=(int)(getHeight()*0.1);
int y_end_point=(int)(getHeight()*0.8);
int y_line=y_end_point+y_start_point;
int x_line=x_end_point+x_start_point;
int div_x=(x_end_point-x_start_point)/13;
int div_y=(y_end_point-y_start_point)/13;
Rectangle shape=new Rectangle(x_start_point,y_start_point,x_end_point,y_end_point);
g2.setColor(Color.WHITE);
g2.fill(shape);
g2.setColor(Color.BLUE);
g2.drawRect(x_start_point,y_start_point,x_end_point,y_end_point);
int count=-2, count1=0;;
for(int i=0;i<15;i++)
{
g2.drawLine(x_start_point+(div_x*i),y_line,x_start_point+(div_x*i),(int)(y_line*1.02));
g2.drawString(Integer.toString(count), (int)(x_start_point+(div_x*i)-3.5),(int)(y_line*1.07));
count+=2;
g2.drawLine(x_start_point,y_line-(div_y*i),(int)(x_start_point*0.85),y_line-(div_y*i));
g2.drawString(Integer.toString(count1),7,(int)(y_line-(div_y*i)));
count1+=500;
}
}
public void addPoint(Point p) {
points.add(p);
}
}
Now here, I have defined a rectangle based on some offset values.So, in that case, the points would be plotted based on the offset and values taken from divisions, but i am unable to bring out a solution for the same.Kindly help
See the changes in your code and the comments explaining them :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class SwingTest extends JFrame {
public SwingTest() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(new PlotComponent());
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()-> new SwingTest());
}
}
class PlotComponent extends JComponent {
private final ArrayList<Point2D> points = new ArrayList<>();
//use constants for better readability
private static final int X_MARKS = 13, X_START = -8, X_INCREMENT = 2,Y_MARKS = 13,
Y_START = 0, Y_INCREMENT = 500, POINT_SIZE = 1;
public PlotComponent() {
setPreferredSize(new Dimension( 600, 500));
addPoint(new Point2D.Double(-7.224, 1002)); //add test point
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//you need to use doubles to avoid rounding error and have use non integer coordinates
double x_start_point = xStart();
double y_start_point = yStart();
double y_end_point = yEnd();
double width = xEnd() - xStart();
double hight = yEnd() - yStart();
double div_x= width/X_MARKS; //this is also the scale: number of pixles per
double div_y= hight/Y_MARKS; //mark. used to scale points when painting
double xOrigin = x_start_point - div_x *(X_START/X_INCREMENT); //location of
double yOrigin = y_end_point + div_y *(Y_START/Y_INCREMENT); // 0,0
Rectangle2D shape=new Rectangle2D.Double(x_start_point,y_start_point,width,hight);
g2.setColor(Color.WHITE);
g2.fill(shape);
g2.setColor(Color.BLUE);
g2.draw(shape);
int xMarkValue= X_START;
for(int i=0; i <= X_MARKS;i++){
Shape xMark = new Line2D.Double(x_start_point+div_x*i, y_end_point,
x_start_point+ div_x*i,y_end_point*1.02);
g2.draw(xMark);
g2.drawString(Integer.toString(xMarkValue), (float) (x_start_point+div_x*i-3.5),
(float)(y_end_point*1.07));
xMarkValue+=X_INCREMENT;
}
int yMarkValue=Y_START;
for(int i=0; i<= Y_MARKS;i++){
Shape yMark = new Line2D.Double(x_start_point,y_end_point-div_y*i,
x_start_point*0.85,y_end_point-div_y*i);
g2.draw(yMark);
g2.drawString(Integer.toString(yMarkValue),7,(float) (y_end_point-div_y*i));
yMarkValue+=Y_INCREMENT;
}
g2.translate(xOrigin, yOrigin); // move the canvas origin to 0,0
g2.setColor(Color.RED);
for( Point2D p : points){
//scale point coordinates. also change y direction
Shape point = new Ellipse2D.Double(p.getX()/div_x, - p.getY()/div_y, POINT_SIZE, POINT_SIZE);
g2.draw(point);
}
}
private double xStart() {
return (int)(getWidth()*0.1);
}
private double xEnd() {
return (int)(getWidth()*0.8);
}
private double yStart() {
return (int)(getHeight()*0.1);
}
private double yEnd() {
return (int)(getHeight()*0.8);
}
public void addPoint(Point2D p) {
points.add(p);
}
}
Related
Below is a minimal reproducible code example where you can use mouse wheel to zoom in and out relative to the position of the mouse. The JScrollPane also auto-adjusts its size as you zoom in and out.
package testpane;
import java.awt.event.MouseAdapter;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class TestPane
{
public static Drawing d;
public static double zoomFactor = 1;
public static void main(String[] args)
{
JFrame f = new JFrame("Tree Diagram");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TestPane().makeDiagram());
f.setSize(1600, 800);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public JComponent makeDiagram()
{
d = new Drawing();
MouseAdapter mouseAdapter = new TestPaneMouseListener();
d.addMouseListener(mouseAdapter);
d.addMouseMotionListener(mouseAdapter);
d.addMouseWheelListener(mouseAdapter);
return new JScrollPane(d);
}
}
package testpane;
import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import javax.swing.JComponent;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import static testpane.TestPane.d;
import static testpane.TestPane.zoomFactor;
public class TestPaneMouseListener extends MouseAdapter
{
private final Point origin = new Point();
#Override
public void mouseDragged(MouseEvent e)
{
Component c = e.getComponent();
Container p = SwingUtilities.getUnwrappedParent(c);
if (p instanceof JViewport)
{
JViewport viewport = (JViewport) p;
Point cp = SwingUtilities.convertPoint(c, e.getPoint(), viewport);
Point vp = viewport.getViewPosition();
vp.translate(origin.x - cp.x, origin.y - cp.y);
((JComponent) c).scrollRectToVisible(new Rectangle(vp, viewport.getSize()));
origin.setLocation(cp);
}
}
#Override
public void mousePressed(MouseEvent e)
{
Component c = e.getComponent();
Container p = SwingUtilities.getUnwrappedParent(c);
if(p instanceof JViewport)
{
JViewport viewport = (JViewport) p;
Point cp = SwingUtilities.convertPoint(c, e.getPoint(), viewport);
origin.setLocation(cp);
}
}
#Override
public void mouseWheelMoved(MouseWheelEvent e)
{
if(e.getWheelRotation()<0)
{
zoomFactor*=1.05;
d.setZoomFactor(1.05);
}
if(e.getWheelRotation()>0)
{
zoomFactor/=1.05;
d.setZoomFactor(1/1.05);
}
}
}
package testpane;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import javax.swing.JPanel;
public class Drawing extends JPanel
{
private final AffineTransform zoomTransform = new AffineTransform();
private final Rectangle rect = new Rectangle(1600, 800);
private double xOffset = 0;
private double yOffset = 0;
private double prevZoomFactor = 1;
public Drawing()
{
Font currentFont = getFont();
Font newFont = currentFont.deriveFont(currentFont.getSize() * 15F);
setFont(newFont);
setBackground(Color.WHITE);
}
public void setZoomFactor(double zoomFactor)
{
zoomTransform.scale(zoomFactor, zoomFactor);
revalidate();
repaint();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform scrollTransform = g2d.getTransform();
double xRel = MouseInfo.getPointerInfo().getLocation().getX() - getLocationOnScreen().getX();
double yRel = MouseInfo.getPointerInfo().getLocation().getY() - getLocationOnScreen().getY();
double zoomDiv = TestPane.zoomFactor / prevZoomFactor;
xOffset = (zoomDiv) * (xOffset) + (1 - zoomDiv) * xRel;
yOffset = (zoomDiv) * (yOffset) + (1 - zoomDiv) * yRel;
prevZoomFactor = TestPane.zoomFactor;
scrollTransform.translate(xOffset, yOffset);
scrollTransform.concatenate(zoomTransform);
g2d.setTransform(scrollTransform);
g2d.drawString("Example", 400, 400);
g2d.dispose();
}
#Override
public Dimension getPreferredSize()
{
Rectangle r = zoomTransform.createTransformedShape(rect).getBounds();
return new Dimension(r.width, r.height);
}
}
Here is my problem: the zooming works just fine, but when I zoom too close, part of the "Example" written on the JScrollPane goes out of bounds. I believe that the problem comes from the translation I've made inside of the "Drawing" java class in the "paintComponent" method. While this translation does help me zoom in properly, it also causes my text to go out of bounds if I zoom too close. Is there any way for me to fix this?
I have this Class That Draws a line between specified points or locations in the map And it works
!
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import org.jxmapviewer.JXMapKit;
import org.jxmapviewer.JXMapKit.DefaultProviders;
import org.jxmapviewer.JXMapViewer;
import org.jxmapviewer.painter.Painter;
import org.jxmapviewer.viewer.GeoPosition;
public class Starter {
public static void main(final String[] args) {
final JFrame f = new JFrame();
f.setSize(500, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JXMapKit jXMapKit1 = new JXMapKit();
jXMapKit1.setDefaultProvider(DefaultProviders.OpenStreetMaps);
jXMapKit1.setCenterPosition(new GeoPosition(5.41984, 100.33924));
jXMapKit1.setZoom(3);
final List<GeoPosition> region = new ArrayList<GeoPosition>();
region.add(new GeoPosition(5.42031, 100.34389));
region.add(new GeoPosition(5.41984, 100.33924));
region.add(new GeoPosition(5.42300, 100.33456));
final Painter<JXMapViewer> lineOverlay = new Painter<JXMapViewer>() {
#Override
public void paint(Graphics2D g, final JXMapViewer map, final int w, final int h) {
g = (Graphics2D) g.create();
// convert from viewport to world bitmap
final Rectangle rect = jXMapKit1.getMainMap().getViewportBounds();
g.translate(-rect.x, -rect.y);
// do the drawing
g.setColor(Color.RED);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setStroke(new BasicStroke(2));
int lastX = -1;
int lastY = -1;
for (final GeoPosition gp : region) {
// convert geo to world bitmap pixel
final Point2D pt = jXMapKit1.getMainMap().getTileFactory().geoToPixel(gp, jXMapKit1.getMainMap().getZoom());
if (lastX != -1 && lastY != -1) {
g.drawLine(lastX, lastY, (int) pt.getX(), (int) pt.getY());
}
lastX = (int) pt.getX();
lastY = (int) pt.getY();
}
g.dispose();
}
};
jXMapKit1.getMainMap().setOverlayPainter(lineOverlay);
f.setContentPane(jXMapKit1);
f.setVisible(true);
}
}
but I want to draw a route that can follow by car. Not just a straight line that cut across all the building !.
When I select two points on the map, I need to see a suggested path or path to reach, not just a line !
i need like this image
Any Help ?
I want to be able to scale my game for different resolutions, but I'm only allowed to work in the controller (I'm using MVC). I'm not sure how to make my game scale.
I haven't really tried anything yet since I'm not familiar with scaling games for different resolutions. Is there a special function for that?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;
import java.util.Collection;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import se.egy.game.resourses.Drawable;
import se.egy.game.resourses.GameCloseException;
public class GameScreen{
private int height, width;
private String title;
private boolean fullScreenMode = false;
private JFrame jf;
private GraphicsDevice device;
private BufferStrategy backBuffer;
private Graphics2D g;
private Color bgColor = Color.BLACK; // Svart, default som bakgrund
private Image bgImg = null;
private DisplayMode oldDM = null;
public GameScreen(String title, int width, int height, boolean fulScreenMode) {
this.width = width;
this.height = height;
this.title = title;
this.fullScreenMode = fulScreenMode;
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
createWindow();
}
});
}catch(Exception e) {}
clearScreen();
if(fullScreenMode) { // Ful lösning ;-)
jf.setBounds(0, 0, width, height);
try{ Thread.sleep(50);}catch(Exception e){}
}
}
public GameScreen(String title, int width, int height) {
this(title, width, height, false);
}
private void createWindow() {
jf = new JFrame(title);
if(fullScreenMode) {
DisplayMode dm = new DisplayMode(width, height, 32, 0);
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
device = env.getDefaultScreenDevice();
jf.setUndecorated(true);
jf.setBounds(0, 0, width, height);
oldDM = device.getDisplayMode();
device.setFullScreenWindow(jf);
device.setDisplayMode(dm);
}else {
jf.setSize(new Dimension(width, height));
jf.setResizable(false);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
jf.setIgnoreRepaint(true);
jf.setVisible(true);
jf.requestFocus();
jf.createBufferStrategy(2);
backBuffer = jf.getBufferStrategy();
}
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.ImageIcon;
import se.egy.game.model.Entity;
import se.egy.game.model.Sprite;
import se.egy.game.view.GameScreen;
import se.egy.game.view.TxtEntity;
public class GameController implements KeyListener{
private GameScreen gs;
private boolean gameRunning = true;
private int fps;
private Entity player;
private ArrayList<Entity> entityList = new ArrayList<>();
private HashMap<String, Boolean> keyDown = new HashMap<>();
public GameController(GameScreen gs, int fps) {
this.gs = gs;
this.gs.setKeyListener(this);
this.fps = fps;
resetkeyDown();
loadObjects();
}
public void runGame() {
long renderDelay = 1000000000/fps;
long lastUpdateTime = System.nanoTime();
while(gameRunning) {
long deltaTime = System.nanoTime() - lastUpdateTime;
if(deltaTime >= renderDelay) {
lastUpdateTime = System.nanoTime();
gs.render(entityList);
update(deltaTime);
}
}
}
I want the game to work for different resolutions. So that my "enemies", as well as the player, is on the same position for a 1920 x 1080 resolution as an 800 x 600 resolution. There is a bit more code to both the GameScreen(view) and to the GameController(controller), but I don't think it's necessary to show more. My model is only of the entities that I'm using for the game, such as the player and the enemies.
I would like to plot some points from a given wkt file, but because of their closeness I only can display a heap of ovals that are overlapped.
The points differ only in their decimal places:
POINT (3346349.958 5642197.806)
POINT (3346349.313 5642199.622)
POINT (3346349.237 5642201.918)
POINT (3346349.734 5642204.058)
POINT (3346351.746 5642205.777)
POINT (3346351.636 5642210.304)
POINT (3346349.335 5642216.518)
POINT (3346347.326 5642221.15)
POINT (3346347.365 5642223.671)
POINT (3346351.577 5642195.711)
etc...
First I tried to plot the points, but as I have mentioned all points are seemingly displayed at the same place.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import com.vividsolutions.jts.io.ParseException;
public class Display extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private int width;
private int height;
private WKTGrabsteine p = new WKTGrabsteine();
public Display() {
setLayout(null);
width = 0;
height = 0;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
g2.translate(height, width);
try {
for (int point = 0; point < p.geoCoordinates().size(); point++) {
Ellipse2D shape = new Ellipse2D.Double(p.geoCoordinates().get(point).getX() / 1000000 + 400,
p.geoCoordinates().get(point).getY() / 1000000 + 100, 5, 5);
g2.draw(shape);
}
} catch (IOException | ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
However I thought that the solution could lie in rescaling the coordinate system, which I tried to transform by Affinetransform and .scale()
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import com.vividsolutions.jts.io.ParseException;
public class Display extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private int width;
private int height;
private WKTGrabsteine p = new WKTGrabsteine();
public Display() {
setLayout(null);
width = 0;
height = 0;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
AffineTransform at = new AffineTransform();
g2.translate(height, width);
at.scale(6000000, 6000000);
try {
for (int point = 0; point < p.geoCoordinates().size(); point++) {
Ellipse2D shape = new Ellipse2D.Double(p.geoCoordinates().get(point).getX(),
p.geoCoordinates().get(point).getY(), 10, 10);
g2.transform(at);
g2.draw(shape);
}
} catch (IOException | ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
In fact I am quite new to this topic and have no clue how to make all points visible. Would be great if somebody could help me.
Many thanks
Use a combination of scaling and translating affine transforms.
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class PointPlotter {
Point2D.Double[] points = {
new Point2D.Double(3346349.958, 5642197.806),
new Point2D.Double(3346349.313, 5642199.622),
new Point2D.Double(3346349.237, 5642201.918),
new Point2D.Double(3346349.734, 5642204.058),
new Point2D.Double(3346351.746, 5642205.777),
new Point2D.Double(3346351.636, 5642210.304),
new Point2D.Double(3346349.335, 5642216.518),
new Point2D.Double(3346347.326, 5642221.15),
new Point2D.Double(3346347.365, 5642223.671),
new Point2D.Double(3346351.577, 5642195.711)
};
public static int SZ = 400;
BufferedImage image = new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB);
private JComponent ui = null;
PointPlotter() {
initUI();
}
private void drawImage() {
Graphics2D g = image.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.WHITE);
g.fillRect(0, 0, SZ, SZ);
Area area = new Area();
double r = 0.3;
for (Point2D.Double point : points) {
Ellipse2D.Double e = new Ellipse2D.Double(
point.getX() - r, point.getY() - r, 2*r, 2*r);
area.add(new Area(e));
}
Rectangle2D rect = area.getBounds2D();
double w = rect.getWidth();
double h = rect.getHeight();
double max = w>h ? w : h;
double s = SZ/max;
AffineTransform scale = AffineTransform.getScaleInstance(s, s);
double tX = -rect.getMinX();
double tY = -rect.getMinY();
AffineTransform translate = AffineTransform.getTranslateInstance(tX, tY);
AffineTransform transform = scale;
transform.concatenate(translate);
area = new Area(transform.createTransformedShape(area));
g.setColor(Color.RED);
g.draw(area);
g.dispose();
}
public void initUI() {
if (ui != null) {
return;
}
drawImage();
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(new JLabel(new ImageIcon(image)));
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
PointPlotter o = new PointPlotter();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
I dont know about you, but I tried so hard on how to create a news ticker. I found approaches that would append what was off the screen on to the back side of it. This caused the animation to jump by a whole character. Then I found methods that would not loop until the text was completely off the screen. After asking a ton of questions on this I thought it would be nice if I just posted my final solution for all the people wondering how to make it. Here you go.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Scroll2 extends JPanel implements ActionListener{
private int x;
private int x2;
private int y;
private int width;
private String textIV;
private Color textColorIV;
private Color bGColorIV;
private Font f=(new Font("SansSerif", Font.BOLD,34));
Timer t;
// TODO font size
public Scroll2(String text, Color textColor, Color bGColor)
{
x=Integer.MIN_VALUE;
x2=Integer.MIN_VALUE;
y=0;
textIV=text;
this.setVisible(true);
Timer refreshTimer = new javax.swing.Timer(1000/50, this);
refreshTimer.start();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setFont(f);
if ( x == Integer.MIN_VALUE ){
width=g.getFontMetrics().stringWidth(textIV);
x = 0;
y = (int) (getHeight()*.6);
}
if ( x2 == Integer.MIN_VALUE ){
x2 = g.getFontMetrics().stringWidth(textIV);
}
g.setColor(bGColorIV);
g.fillRect(this.getX(), this.getY(), (int)this.getBounds().getWidth(), (int)this.getBounds().getHeight());
g.setColor(textColorIV);
g.drawString(textIV, x, y);
g.drawString(textIV, x2, y);
}
public void refresh ()
{
if(x>=(-width)&&x2!=Integer.MIN_VALUE)
{
x=x-2;
x2=x2-2;
}
if(x2<=-width&&x!=Integer.MIN_VALUE)
{
x2=width;
}
if(x<-width&&x!=Integer.MIN_VALUE)
{
x=width;
}
repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
this.refresh();
}
}