draw and save an image - java

I'm coding the simple project to draw lines and save likes an image,but when I run, it shows an errors that I can't fix. Please help me.
Here is my code:
package image;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class paint extends JFrame{
private Point points[] = new Point[10000];
private Point pointends[] = new Point[10000];
private int pointCount = 0;
private JButton save_btn;
public paint()
{
panel paint2 = new panel();
add(paint2,BorderLayout.CENTER);
}
private class panel extends JPanel
{
public panel()
{
setBackground(Color.WHITE);
save_btn = new JButton();
save_btn.setText("123");
this.add(save_btn);
/* save btnhandler = new save();
save_btn.addActionListener(btnhandler);*/
MouseHandler handler = new MouseHandler();
this.addMouseMotionListener(handler);
this.addMouseListener(handler);
}
#Override
protected void paintComponent(Graphics g)
{
// TODO Auto-generated method stub
super.paintComponent(g);
for(int i = 0;i <pointCount;i++)
{
g.setColor(Color.RED);
g.drawLine(points[i].x, points[i].y, pointends[i].x, pointends[i].y);
}
}
}
private class MouseHandler extends MouseAdapter
{
#Override
public void mouseDragged(MouseEvent e)
{
// TODO Auto-generated method stub
pointends[ pointCount-1] = e.getPoint();
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
super.mousePressed(e);
//find point
if(pointCount < points.length)
{
points[ pointCount ] = e.getPoint();//find point
pointends[ pointCount ] = e.getPoint();
pointCount++;
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
super.mouseReleased(e);
/*pointends[pointCount]=e.getPoint();
repaint();
pointCount++;
*/
}
}
}
and the class of save event
package image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.Buffer;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
public class save implements ActionListener{
private paint paint1 = new paint();
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String str = JOptionPane.showInputDialog(null, "Enter file name: ");
//
BufferedImage bufImage = new BufferedImage(paint1.getWidth(), paint1.getHeight(),BufferedImage.TYPE_INT_RGB);
try {
ImageIO.write(bufImage, "jpg", new File(str + ".jpg"));
} catch (IOException ox) {
// TODO: handle exception
ox.printStackTrace();
}
}
}//end class

The Problem is that Your paint JFrame creates an instance of your save ActionListener, and your save ActionListener creates an instance of your paint JFrame. Thus you run into an infinite loop of constructors.
Instead of creating a new paint object, pass the current one in the constructor for save.
private paint paint1 = null;
public save(paint panel) {
this.paint1 = panel;
}
Now, in your panel constructor, pass a reference to the current instance to the ActionListener:
save btnhandler = new save(my_paint); // see Update below
save_btn.addActionListener(btnhandler);
This should fix your immediate problem. However, I recommend restructuring your code a bit, and you should also try to follow Java coding conventions, e.g., using CamelCase names for classes, and using correct indentation. This will make it much easier for others (and yourself) to read and undertand your code.
Update: I just realized that your object structure is a bit more complicated... your paint JFrame creates a panel JPanel, which creates a save ActionListener, which again creates a paint JFrame. The basic argument and solution remain the same, but instead of using new save(this) you have to either pass a reference to the JFrame containing the JPanel, or change the type of the field in your ActionListener.
Alternatively you could make bothe the JPanel and the ActionListener inner classes of the paint JFrame. This way you can access the JFrame directly from within the ActionListener and do not have to pass a reference at all, thus circumvent the problem entirely and giving a bit more structure to the code.

Related

Eclipse Java - Running FIle issues; Im new around here

I have the following code:
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.Renderer;
import javax.swing.Timer;
// All packages imported , ready for use... Add more if need be : +
#SuppressWarnings("unused")
public class main implements KeyListener, ActionListener
{
public boolean board_show =true;
public int AOB1 = 16;
public int AOB2 = 16;
public static int WOB = 640;
public static int HOB = 640;
public int GStat = 0;
// Defines when game is playing, toggle-able twice 0, 1, 2
// 0 = Menu, 1 = Paused, 2 = Game
// Might Become Redundant
// TODO Make this feature redundant!
public boolean click, space;
public int turn;
public Component renderer;
public void ScreenUp()
{
Timer timer = new Timer(20, this);
JFrame jframe = new JFrame("CHESS");
jframe.setSize(WOB, HOB);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.add(renderer);
jframe.addKeyListener(this);
timer.start();
}
public static void render(Graphics g)
{
g.setColor(Color.black);
g.fillRect(0, 0, WOB, HOB);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
And I want to know why Eclipse, my editor will not let me run this file, as a whole, even in other modes it comes up with errors. I am fairly new to Java, so I am trying to make a Game - Chess. For now I just want to know why the editor will not let me run it and how I can run it. And of course, since I am new to Java, I only know the basics of the language, so any detailed response would be greatly appreciated!
You expect that having a class named main is enough to define an entry point to run a Java application. Wrong.
You need a method with exactly this signature
public static void main(String[] args) {
in your class. That method defines what happens when you "run" the class/application.
And the real answer is: study those tutorials written for people ... that just "start" with Java, like the one from Oracle. Even when you are proficient in other languages - when you just assume how things work; chances are that you run into exactly this kind of problems.

The class for my keyListener wont allow me to implement the key listener

the problem is in the line public class keyPressed implements KeyListener{
it tells me to make it abstract but i know that is not needed. Please any advice to why this is so or how to properly make this work thanks
package GUI;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import Data.TileList;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class MainUI implements Runnable {
public JPanel gameGrid = new JPanel();
private JFrame gameBoard;
private int row = 4;
private int col = 1;
int boardSize = row * col;
public MainUI(){
}
#Override
public void run(){
gameBoard = new JFrame("BrickGame");
JButton st = new JButton("Start");
Font fontst0 = st.getFont();
Font fontst1 = fontst0.deriveFont(Font.BOLD, fontst0.getSize()*14);
st.setFont(fontst1);
gameBoard.add(gameGrid);
gameGrid.setLayout(new GridLayout(2,1));
st.addActionListener(new StartGame(this));
gameGrid.add(st);
JLabel txt = new JLabel();
txt.setText("<HTML><body><H1>Instructions</H1><p>Click the 'start' button to start the game" +
"<br>Type the letters in the bricks to make a bric dissapear. After all bricks are gone the game is over.<p></body></HTML>");
gameGrid.add(txt);
gameBoard.setVisible(true);
gameBoard.pack();
}
public void StartGame(){
gameGrid.removeAll();
gameGrid.setLayout(new GridLayout(row,col));
gameBoard.add(gameGrid);
for(int i = 0; i < boardSize; i++){
//String x = TileList.Letters[i] + "";
//JButton tile = new JButton(x);
JButton tile = new JButton(new TileList(TileList.Letters[i]).getLetter() + "");
tile.setBackground(Color.red);
gameGrid.add(tile);
}
gameBoard.setFocusable(true);
//here i am trying to addd the class of keypressed to the jframe.
gameBoard.addKeyListener(new keyPressed());
gameBoard.add(gameGrid);
gameBoard.pack();
}
}
package GUI;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
//the problem is in the implements line below it tells me to make it abstract but that is not needed.
public class keyPressed implements KeyListener{
public keyPressed(){
}
public void keyTyped(KeyEvent e) {
}
}
The compiler is telling you exactly what's wrong. You have a class implementing an interface, and you're not implementing all the interface methods. You need to fix this by adding the third method, keyReleased. The API would tell you which methods you need, and in the future you will want to have a look there when you have similar problems.
public class keyPressed implements KeyListener{
public keyPressed(){
}
public void keyTyped(KeyEvent e) {
}
}
KeyListener has three methods and you have implemented only 2 .Either implement the remaining methods or mark your class as abstract.
So if you want to use only 2 methods the you have to use keyAdapterhere:
public class adapter implements KeyAdapter{
#Override
public keyPressed(KeyEvent key){
//action...
}
#Override
public void keyTyped(KeyEvent key) {
//action
}
}
Note that:
The KeyListener is interface.
If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile.

How do I make a (keyPressed) KeyListener?

Im trying to write a very simple program that allows you to control a sprite with arrow keys and move around the screen. From what I understand, to do this I need a keyPressed() KeyListener. I believe Im doing this correctly based on the Java Doc but its not returning the correct output when I press the designated key. Can someone please tell me what is wrong with my code, and if possible, provide a simple example of the usage of this class? Thanks!
(Note, code is unfinished)
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Display extends JPanel implements ActionListener, KeyListener {
Display() {
// super();
loadImages();
initTimer();
this.addKeyListener(this);
}
BufferedImage sprite;
Timer timer;
int up = 0;
public void loadImages() {
File spriteImage = new File("Pacman_sprite.png");
try {
sprite = ImageIO.read(spriteImage);
} catch (IOException e) {
System.out.println("Sprite import failed");
}
}
public void initTimer() {
timer = new Timer(100, this);
timer.start();
this.addKeyListener(this);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
System.out.println("Key press registered"); //does not print this?
if (key == KeyEvent.VK_UP) {
System.out.println("sucess"); // does not print this?
up++;
repaint();
}
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("release");
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(sprite, 500, 500 + up, null);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
repaint();
}
}
EDIT:
May have found the answer here. I moved the key handling code to a new class called KeyHandler then added these two lines to the constructor:
addKeyListener(new KeyHandler());
setFocusable(true);
It now appears to be working just fine (sort of, at least it is detecting when the up key is hit. My graphics aren't.)
You are not adding the listener to the JPanel.
Note: I would suggest you to change your design. Right now, Display class is both a JPanel and a Listener (which doesn't make sense in my opinion).
But to add the listener in your code do something like,
this.addKeyListener(this); // This looks awkward right. That's why you should change the design.
in your constructor.

motion of rectangle by keyboard

I made the following code to move a rectangle using arrowkeys of keyboard. The "keyPressed" function does not seem to be working properly.Infact, i don't think it is even getting called when a key is pressed bcz when i tried to print some text when a key is pressed, it was not getting printed.All i see in the output window is a stationary rectangle fixed at the top left corner of the window.Here is my code....pls help me...i need it desperately
import javax.swing.JFrame;
public class Main
{
public static void main(String args[])
{
JFrame window=new JFrame();
window.setSize(600,400);
window.setTitle("window");
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingComponent DC=new drawingComponent();
window.add(DC);
}
}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComponent;
import javax.swing.Timer;
public class drawingComponent extends JComponent implements ActionListener,KeyListener
{
Timer t=new Timer(2000,this);//moving after 5 milliseconds
static int x=0;
static int y=0;
private static int velx=0;
private static int vely=0;
public drawingComponent()
{
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
System.out.println("tr1");
}
public void paintComponent(Graphics g)
{
Graphics2D g2=(Graphics2D) g;
Rectangle rect1=new Rectangle(x,y,50,30);
g2.setColor(Color.RED);
g2.fill(rect1);
System.out.println("tr2");
}
public void actionPerformed(ActionEvent e) //inbuilt fncn f actionListener(interface) which needs to be created
{
x+=velx; //changing values
y+=vely;
System.out.println("tr3");
repaint(); //inbuilt fncn to repeat the paintComponent method
}
public void keyPressed(KeyEvent e)
{
int code=e.getKeyCode();
if(code==KeyEvent.VK_UP)
{ velx=0; vely=-1;repaint(); }
if(code==KeyEvent.VK_DOWN)
{ velx=0; vely=1; repaint(); }
if(code==KeyEvent.VK_LEFT)
{vely=0; velx=-1; repaint(); }
if(code==KeyEvent.VK_RIGHT)
{vely=0; velx=1; repaint();}
}
public void keyTyped(KeyEvent e)
{}
public void keyReleased(KeyEvent e)
{}
}
Welcome to the wonderful world of KeyListeners...
While you have set the component focusable, you've not requested that the component be focused.
You could try calling requestFocusInWindow, but he this raises the question of when to call it.
You could call it within the constructor, but because the component doesn't belong to a valid visible component yet, the call may fail. You could override the components addNotify method and add the call to it, after you call super.addNotify, but the requestFocusInWindow method doesn't gurentee that focus will be given the component
Instead, you could simply avoid all this hassle and use the key bindings API instead, which will give you control over the level of focus require for key events to be triggered
As a side note, you should call setVisible on your frame after you've set up the UI completely

repaint not being called

Hi I have googled and can't figured out why my paintComp method isnt being called
I have the following code
package com.vf.zepto.view;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import com.vf.zepto.view.interfaces.ProcessorPanel;
public class CountryDetailsPanel extends JPanel implements ProcessorPanel, Runnable {
private GridBagConstraints c = new GridBagConstraints();
private String countryName;
private Properties prop = new Properties();
private BufferedImage image;
public CountryDetailsPanel() {
try {
prop.load(new FileInputStream("country.props"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//this.setLayout(new GridBagLayout());
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(5, 5, 5, 5);
this.setPreferredSize(new Dimension(200, 200));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
try {
if(countryName != null) {
String asset = prop.getProperty(countryName+".flag");
if(!asset.equals(null)) {
image = ImageIO.read(new File(asset));
g.drawImage(image, 0, 0, null);
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void updateDetails(Object o) {
countryName = (String)o;
SwingUtilities.invokeLater(this);
}
#Override
public void run() {
this.repaint();
}
}
and when calling this.repaint() expect the paintComponent method to be called but for love nor money it isnt.
Have tried to force it to use the EDT incase that was the issue but its not.
any ideas?
You should never call paintComponent() the repaint() method consolidates all requests to change the component (there may be several repaint requests between screen refreshes). It adds an update request to the GUI event queue so that the update will be properly coordinated with other GUI actions (Swing and AWT are not thread-safe). This update request, when processed, calls update(), which calls paint(), which calls your paintComponent()
Why have this:
#Override
public void run() {
this.repaint();
}
It does not seem of any use (creating a new thread to repaint once? Not to mention the thread is not on EDT rather call repaint() on the JPanel instance (if modified externally other than that you shouldnt even worry). However to start a thread which modifeis UI componets use s SwingTimer/SwingWorker or SwingUtilities#invokeXXX()
This might not be related but in your code I see this:
if(!asset.equals(null)) {
image = ImageIO.read(new File(asset));
g.drawImage(image, 0, 0, null);
}
dont use equals() to compare to a null value as this might throw a NullPointerException because you are attempting to
deference a null pointer, for example this code throws a NPE:
String s=null;
if(!s.equals(null)) {//throws NPE
System.out.println("Here");//is never printed
}
Also as mKorbel has said (+1 to him) dont do long running tasks in paintComponent() declare your Image globally, assign it in the constructor and then use it in paintComponent(). F.i
rather do:
public class TestPanel extends JPanel {
private Image image;
public TestPanel() {
image = ImageIO.read(new File(asset));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(asset!=null) {
g.drawImage(image, 0, 0, null);
}
}
}
Do not load image or another hard or long running code in paintComponent
Load this Object as a local variable and only one time
paintComponent() is called
implicitly, when JComponent requires repaint, or
explicitly, for example on every of mouse event if one were to invoke paintComponent() from a MouseMotionListener.
If there is animation, then to use Swing Timer and call repaint().

Categories