I have an arraylist of images, I am trying to have each image, slide through the screen repeatedly..
public class GraphicsT extends JPanel implements ActionListener {
Timer timer = new Timer(1, this);
Image image;
Image image2;
int x1;
int x2;
int y1;
int y2;
int num;
List<String> imageList1 = new ArrayList<String>();
GraphicsT() {
imageList1.add("image/java.jpeg");
imageList1.add("image/slide.jpg");
imageList1.add("image/giphy.gif");
x1 = 100;
y1 = 100;
x2 = 200;
y2 = 200;
num = 0;
}
public void paint(Graphics g) {
ImageIcon i2 = new ImageIcon("image/street.jpg");
image2 = i2.getImage();
g.drawImage(image2, 0, 0, null);
for (int i = 1; i < imageList1.size(); i++) {
ImageIcon im = new ImageIcon(imageList1.get(i));
image = im.getImage();
g.drawImage(image, x1, y1, x2, y2, 100, 120, 120, 240, null);
System.out.println(imageList1.get(i));
}
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
num++;
if (num % 100 == 0) {
x1 = x1 + 10;
x2 = x2 + 10;
}
if (x2 >= 570) {
// end reached
x1 = 0;
x2 = 100;
}
repaint();
}
}
public class GraphicsApp extends JFrame {
GraphicsT gt = new GraphicsT();
public GraphicsApp() {
this.setTitle("Multiple Slide");
this.setSize(450, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.add(gt);
}
public static void main(String[] args) {
new GraphicsApp();
}
}
my current code can only pick one image, but i want a situation whereby after the first images goes out of the screen, the second image can follow, then the third, and so on...
Please help will be much appreciated.
Several issues:
you should be overriding paintComponent() not paint() and you invoke super.paintComponent(...) to make sure the background is painted first.
a painting method is for painting only. You should NOT be doing I/O to read the images. The images should be read in the constructor of your class
You should NOT start the Timer in the painting method. The Timer is started in the constructor.
Your basic painting code is wrong. You should have a couple of instance variables, a) the "currentImage", b) "imageNumber". Then in the painting method you simply paint the currentImage at the x/y location.
In the ActionListener, when the image is off the screen you increment the "imageNumber" and copy the image from the ArrayList to the "currentImage". Then you reset the x/y location so the image is painted starting from the right.
When the "imageNumber" reaches the end of the ArrayList you reset it back to 0.
Related
nothing is showing up at all..
I have tried moving Random rand = new Random() to outside of the loop, but it still doesnt work at all.
Nor does the frame exit on close.
public class myMain {
public static void main(String args[]) {
Frame frame = new Frame();
}
}
public class Frame extends JFrame {
public Frame(){
super("Fancy Triangle");
setSize(1024, 768);
myPanel panel = new myPanel();
add(panel);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}
public class myPanel extends JPanel {
int x1 = 512;
int y1 = 109;
int x2 = 146;
int y2 = 654;
int x3 = 876;
int y3 = 654;
int x = 512;
int y = 382;
int dx, dy;
Random rand;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < 50000; i++) {
g.drawLine(x, y, x, y);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
rand = new Random();
int random = 1 + rand.nextInt(3);
if (random == 1) {
dx = x - x1;
dy = y - y1;
} else if (random == 2) {
dx = x - x2;
dy = y - y2;
} else {
dx = x - x3;
dy = y - y3;
}
x = x - (dx / 2);
y = y - (dy / 2);
}
}
}
This:
Thread.sleep(300);
is not doing what you intend it to do. I think that you're trying to draw with a delay, but that's not what this does. Instead you're calling sleep on the Swing event thread puts the whole application to sleep, since the thread cannot do what it needs to do, including drawing the application and interacting with the user. Even worse, you're doing this within a painting method, a method that is required to be extremely fast since often the perceived responsiveness of a Swing application is determined by painting speed.
Instead use a Swing Timer (Swing Timer tutorial) to change the state of fields of the class, and then call repaint. Have your paintComponent use those changed fields to decide what to draw and where. Since a Sierpinski triangle is composed of dots, consider creating an ArrayList<Point>, getting rid of the for loop inside your painting method, and using the Swing Timer to replace this for loop. Within the Timer's ActionListener, place the semi-random points into the ArrayList and call repaint. Then within paintComponent, iterate through the ArrayList, drawing each point that it contains.
Alternatively, you could draw the points onto a BufferedImage in your Swing Timer and then simply have your paintComponent display the BufferedImage via g.drawImage(...) method call. This would likely be more efficient.
I'm trying to make a hex board with hex images (720x835 GIF) on a scroll-able JPanel. I've overridden the paintComponent method to draw the tiles at different specific locations and used a timer to call repaint at each tick.
When repaint() is called, doDrawing is called. When doDrawing is called, choseTile is called to draw the tiles with drawImage.
For some reason, the tiles are not being drawn and I'm left with an empty black panel. Why are my images not being drawn? Is it because the images are too large? The panel is too large?
public class MapPanel extends JPanel {
// Images for the tiles
Image tile1;
Image tile2;
//etc
// measurements for the tiles
int tileX = 720;
int tileY = 835;
int dimensionX = 14760;
int dimensionY = 14613;
//Use this to keep track of which tiles goes where on a 20x20 board
public int[][] hexer;
/**
* Create the panel.
*/
public MapPanel(int[][] hexMap) {
hexer = hexMap;
setPreferredSize(new Dimension(dimensionX, dimensionY));
setBackground(Color.black);
setFocusable(true);
loadImages();
Timer timer = new Timer(140, animatorTask);
timer.start();
}
//getting the images for the tiles
private void loadImages() {
// Setting the images for the tiles
ImageIcon iid1 = new ImageIcon("/Images/tiles/tile1.gif");
tile1 = iid1.getImage();
ImageIcon iid2 = new ImageIcon("/Images/tiles/tile2.gif");
tile2 = iid2.getImage();
//etc
}
// Drawing tiles
private void choseTile(Graphics g, int x, int y, int id) {
switch (id) {
case 1:
g.drawImage(tile1, x, y, this);
break;
case 2:
g.drawImage(tile2, x, y, this);
break;
//etc
}
}
// repainting stuff
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
private void doDrawing(Graphics g) {
int actualX;
int actualY;
//set the painting coordinates and image ID then call the method to draw
for (int x = 0; x < 20; x++) {
for (int y = 0; y < 20; y++) {
if ((y + 1) % 2 == 0) {
actualX = x * tileX + 720;
} else {
actualX = x * tileX + 360;
}
if((x + 1) % 2 == 0){
actualY = (y/2) * 1253 + 418;
}else{
actualY = (y+1)/2 * 1253 + 1044;
}
if(hexer[x][y] != 0)
choseTile(g, actualX, actualY, hexer[x][y]);
}
}
}
private ActionListener animatorTask = new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
};
}
Edit: I've already checked to make sure the images aren't null.
Following Andrew Thompson's suggestion; I used ImageIO. I was able to figure out that the way I was accessing the image files was faulty thanks to thrown errors by ImageIO.
Hello I would like to prevent graphics drawing and drawing again but I don't know how to do, I just want my panel delete all painted graphics and restart with same code. I tried some methods posted here but no one does the job.
public class Main extends JPanel implements ActionListener {
Timer timer;
private double angle = 444;
private double scale = 1;
private double delta = 0.0001;
RoundRectangle2D.Float r = new RoundRectangle2D.Float();
int counter = 0;
public Main() {
timer = new Timer(55, this);
timer.start();
}
public void paint(Graphics g) {
counter++;
int h = getHeight();
int w = getWidth();
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(randomNumber(0, 155), randomNumber(0, 255),randomNumber(0, 155), randomNumber(0, 255)));
drawCircles(g2d, getWidth()/2, getHeight()/2, 250);
if(counter > 200){
g2d.clearRect (0, 0, getWidth(), getHeight());
super.paintComponent(g2d);
counter = 0;
}
}
public int randomNumber(int min, int max) {
int c = new Random().nextInt((max - min) + 1);
return c;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setUndecorated(true);
Dimension dim = new Dimension(Toolkit.getDefaultToolkit()
.getScreenSize().width, Toolkit.getDefaultToolkit()
.getScreenSize().height);
frame.setSize(dim);
frame.setLocation(0, 0);
frame.setBackground(new Color(0, 0, 0, 255));
frame.add(new Main());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
void drawCircles(Graphics graphics, int xMid, int yMid, int radius) {
// end recursion
if(radius < 5)
return;
// Draw circle
// start recursion
//left
drawCircles(graphics, xMid-radius, yMid, radius / 2);
((Graphics2D) graphics).rotate(angle);
graphics.drawOval(xMid - radius, yMid - radius, radius * 2, radius * 2);
//right
drawCircles(graphics, xMid+radius, yMid, radius / 2);
graphics.drawOval(xMid - radius, yMid - radius, radius * 2, radius * 2);
((Graphics2D) graphics).rotate(angle);
((Graphics2D) graphics).rotate(angle);
((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
}
public void actionPerformed(ActionEvent e) {
if (scale < 0.01)
delta = -delta;
else if (scale > 0.99)
delta = -delta;
scale += delta;
angle += 0.001;
repaint();
}
}
I am not sure I understand you fully, but you can use a JToggleButton (for example) where is the toggle button is down it prevents drawing. I can see something like this inside your drawCircles() method:
void drawCircles(Graphics graphics, int xMid, int yMid, int radius)
{
if(!toggleBtn.isSelected() // the toggle button is pressed
{
// draw something
}
}
In your example, you are drawing two circles and two ovals. If I understood you correctly, you want to be able to pause in the middle of the method, for example, and only draw the first circle. Then, at some point, you want to continue drawing the two ovals and the remaining circle. Unfortunately, you cannot do that. You cannot stop (or pause) a method in the middle of it.
Methods have to execute to completion (whether to the end, or an exception is thrown). However, you can create some kind of task to draw ONE shape (for example, a circle). If you create multiple tasks, you can draw many circles. To accomplish this, you will need to learn about Concurrency and probably about Java Tasks. You can have these tasks execute in some kind of order and because of concurrency, you could pause and resume these drawing tasks the way I think you would want.
I tried to create implementation DDA line drawing algorithm at Java. I created JFrame form and dda.java classes. There is just one Button action at JFrame for this moment. And I am not sure about implementation DDA at JFrame class. I think, that it might be problem with drawPixel method but I am not sure about implementation at JFrame at all. I appreciate your comments.
this is draw line method at dda.java
void drawLineDDA(Graphics2D g) {
dx=(double)(x2-x1);
dy=(double)(y2-y1);
double m=Math.abs(dy/dx);
double absx=Math.abs(dx);
double absy=Math.abs(dy);
double px = absx/p;
double py = absy/p;
int p=0;
float slope = 1;
if(y1==y2){
if(x1==x2) return; //it is not a line, nothing happened
slope = 0;
absx = 1;
absy = 0;
p=(int) (dx/absx); //p means number of steps
}
else if(x1==x2){
slope = 2;
absx = 0;
absy = 1;
p = (int) (dy/absy);
}
else{
slope = (float) (dy/dx);
absx=1;
absy=slope*absx;
p= (int) ((dy/absy > dx/absx) ? dy/absy : dx/absx);
}
for(int i = 0; i <=p;i++){
drawPixel(x1,y1,Color.BLACK);
x1 += absx;
y1 += absy;
}}
method draw Pixel at dda.java
private void drawPixel(int x1, int y1, Color BLACK) {
g.drawOval(x1, y1, x1+5, y1+5); //can be mistake right here?
}
part of JFrame class
public class NewJFrame extends javax.swing.JFrame {
int x1,x2,y1,y2;
Graphics2D g;
dda d;
public NewJFrame() {
this.d = new dda(20,30,20,50); //maybe this is not good?
initComponents();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
g = (Graphics2D) jPanel1.getGraphics();
d.drawLineDDA(g); // and I am definielly not sure about this
}
You should not use getGraphics() for custom painting, as it is a temporary buffer which is recycled on next repaint. Do you painting in paintComponent(). Override paintComponent() method of a JComponent or JPanel. See Performing Custom Painting for more information and examples. Also see Painting in AWT and Swing.
There is also an issue in drawPixel method, as the dimensions of the oval depend on the coordinates. Try using constant dimension. fillOval may suit better. Here is an example:
private void drawPixel(Graphics2D g, int x1, int y1) {
g.fillOval(x1, y1, 3, 3);
}
I am trying to display two rotating wheels with diameter 512untis at different rates but i am not able to remove the previous drawn image graphics and set the rotated graphics at the correct position.
For now i am doing a rotation with arbitrary angle.
I tried affineTransform and got the rotations but it was weird like all pixels spread away.
Im using a while loop with thread.sleep(). The following is the code :
//The drawSmallCircle and drawBigCircle return two images.
class MyFramePart2 extends JFrame
{
String name;
JPanel big_obj_panel,small_obj_panel;
JLabel bigLabel,smallLabel;BufferedImage imgRet,imgRetSmall;
static double radians,angle,rev,fps,smallAngle,smallRadians;
int numLines,i=0;
MyFramePart2(String frameName,int numStrokes,double revolutions,double frameps)
{
numLines=numStrokes;
smallAngle=smallRadians=angle=radians=Math.toRadians(360/numLines);
rev=revolutions;
fps=frameps;
setSize(1240,720);
setLocation(0,0);
setLayout(null);
getContentPane().setBackground(Color.WHITE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
big_obj_panel=new JPanel();
big_obj_panel.setLayout(null);
big_obj_panel.setSize(512,512);
big_obj_panel.setLocation(100,100);
big_obj_panel.setBackground(Color.white);
add(big_obj_panel);
imgRet=drawBigCircle();
bigLabel = new JLabel(new ImageIcon(imgRet));
bigLabel.setLayout(null);
bigLabel.setLocation(0,0);
bigLabel.setSize(512,512);
bigLabel.setOpaque(true);
bigLabel.setBackground(Color.white);
big_obj_panel.add(bigLabel);
small_obj_panel=new JPanel();
small_obj_panel.setLayout(null);
small_obj_panel.setSize(512,512);
small_obj_panel.setLocation(700,100);
small_obj_panel.setBackground(Color.white);
add(small_obj_panel);
imgRetSmall=drawSmallCircle();
smallLabel = new JLabel(new ImageIcon(imgRetSmall));
smallLabel.setLayout(null);
smallLabel.setLocation(0,0);
smallLabel.setSize(512,512);
smallLabel.setOpaque(true);
smallLabel.setBackground(Color.white);
small_obj_panel.add(smallLabel);
setVisible(true);
while(i!=5) // suppose to be while true, just checking
{
setVisible(true);
bigLabel.setIcon(new ImageIcon(imgRet));
smallLabel.setIcon(new ImageIcon(imgRetSmall));
try{
Thread.sleep(10);
}
catch(Exception e)
{}
i++;
}
}
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d=(Graphics2D)g;
g2d.translate(256,256);
g2d.rotate(Math.toRadians(20));
g2d.translate(-256,-256);
g2d.drawImage(imgRet,0,0,null);
g2d.dispose();
super.paint(g);
g2d=(Graphics2D)g;
g2d.translate(256,256);
g2d.rotate(Math.toRadians(30));
g2d.translate(-256,-256);
g2d.drawImage(imgRetSmall,0,0,null);
g2d.dispose();
}
public static BufferedImage drawBigCircle()
{
BufferedImage img=new BufferedImage(512,512,BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d=img.createGraphics();
g2d.setColor(Color.black);
g2d.drawOval(0,0,511,511);
Line2D l2d;
while(angle <= 2*Math.PI)
{
l2d=new Line2D.Double(256,256,256+256*Math.cos(angle),256+256*Math.sin(angle));
g2d.draw(l2d);
angle=angle+radians;
}
return img;
}
}
First rule of Swing. Don't block the Event Dispatching Thread. Doing so will make you application look like it's hung and prevent the EDT from processing any repaint requests.
This means, you need some way to schedule updates that doesn't block the EDT
Second rule of Swing. Don't create or modify any UI component from any thread other then the EDT.
Generally, you should avoid overriding the paint method of top level containers like JFrame, apart from everything else, they're not double buffered, meaning your painting will flicker as it's updated. Instead, you should use one of the Swing containers, like JPanel
There are lots of different ways to achieve this. Basically, here I've used three lists, but if I was serious, I would create an object that could maintain all the required information (image, angle an delta)
In order to achieve the actual animation, I've used a javax.swing.Timer. This will trigger an event at least every n periods, but more importantly, it does it within the context of the Event Dispatching Thread. This ensures that all the changes made to the angles are done in way that will prevent any possibility of painting occurring while we're updating the values...
This example rotates the three images at different (random) speeds...
public class TestRotation {
public static void main(String[] args) {
new TestRotation();
}
public TestRotation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private List<BufferedImage> images;
private List<Double> angles;
private List<Double> speed;
public AnimationPane() {
images = new ArrayList<>(5);
images.add(createWheel(50, 4));
images.add(createWheel(50, 3));
images.add(createWheel(50, 6));
angles = new ArrayList<>();
speed = new ArrayList<>();
for (int index = 0; index < images.size(); index++) {
angles.add(0d);
speed.add(Math.random() * 5d);
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int index = 0; index < angles.size(); index++) {
double angle = angles.get(index);
double delta = speed.get(index);
angle += delta;
angles.set(index, angle);
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = 0;
int y = 0;
for (int index = 0; index < images.size(); index++) {
BufferedImage image = images.get(index);
double angle = angles.get(index);
// This is important. Basically we going to grab a isolated snap shot
// of the current graphics context. This means any changes we make
// will not affect the original graphics context (other then painting)
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), image.getWidth() / 2, image.getHeight() / 2);
g2d.setTransform(at);
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
x += image.getWidth();
}
}
}
protected Point2D calculateOutterPoint(int radius, double angel) {
int x = Math.round(radius / 2);
int y = Math.round(radius / 2);
double rads = Math.toRadians((angel + 90));
// This determins the length of tick as calculate from the center of
// the circle. The original code from which this derived allowed
// for a varible length line from the center of the cirlce, we
// actually want the opposite, so we calculate the outter limit first
double fullLength = (radius / 2d);
// Calculate the outter point of the line
double xPosy = (x + Math.cos(rads) * fullLength);
double yPosy = (y - Math.sin(rads) * fullLength);
return new Point2D.Double(xPosy, yPosy);
}
public BufferedImage createWheel(int radius, int spokes) {
BufferedImage img = new BufferedImage(radius, radius, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
g2d.drawOval(0, 0, radius - 1, radius - 1);
Point2D center = new Point2D.Double(radius / 2d, radius / 2d);
double angle = 360d / spokes;
for (int index = 0; index < spokes; index++) {
Point2D p = calculateOutterPoint(radius, index * angle);
g2d.draw(new Line2D.Double(center, p));
}
g2d.dispose();
return img;
}
}