Update JFrame paintings - java

I want to update my rectangle when my key is pressed currently I have almost achieved that
package com.raggaer.frame;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class Elements extends JPanel {
private static int y = 250;
public Elements() {
this.getInputMap().put(KeyStroke.getKeyStroke("UP"), "up");
this.getActionMap().put("up", new Listener("up"));
this.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "down");
this.getActionMap().put("down", new Listener("down"));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(250, this.y, 10, 10);
}
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public static void setY(int cord) {
y += cord;
// Cant access repaint()
}
}
And this is my listener class
package com.raggaer.frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.AbstractAction;
public class Listener extends AbstractAction {
private String code;
//final Elements game = new Elements();
public Listener(String order) {
this.code = order;
}
public void actionPerformed(ActionEvent e) {
System.out.println(this.code);
Elements.setY(1);
}
}
Currently everything works except that I dont know how to update the y position of the rectangle, I tried using an static variable but then I cant call the repaint() method.

No,.... don't use static anything, neither methods nor fields because if you do this, you'll break object-oriented programming rules, leaving your code difficult to update and maintain. The exception of course would be your main method, and carefully chosen fields and methods who truly belong to the class. Instead give the class that needs to call the Element object's method a valid reference to the object whose state you wish to change, the drawing JPanel or Element object. This can be done by passing in a valid reference via a constructor parameter.
public class Listener extends AbstractAction {
private Elements elements;
public Listener(Elements elements) {
this.elements = elements;
}

Related

JFrame repaint() and revalidate() only updating when window is resized on Mac os

I use this class for my school app projects. It is how I set the application up and it extends JFrame and implements Runnable. Now whenever I use this in school on a Windows computer and everything works and the screen updates, but at home on a Mac it doesn't. I use Eclipse neon with JDK 1.8.0_101
Please help me out, I can't test any projects at home cause of this.
import java.awt.Graphics;
import javax.swing.JFrame;
public abstract class GUIApplication extends JFrame implements Runnable{
private Screen currentScreen;
//no main, cant instentiate an abstract class
public GUIApplication(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int x=40;
int y=40;
int width=1000;
int height=640;
setBounds(x,y,width,height);
initScreen();
setVisible(true);
}
//this is a method for creating the starting screen
protected abstract void initScreen();
public void setScreen(Screen screen){
//stop controls from previous screen
removeListeners();
setCurrentScreen(screen);
//add new controls
addListeners();
}
private void removeListeners(){
if(getCurrentScreen() != null){
if(getCurrentScreen().getMouseListener() != null) removeMouseListener(getCurrentScreen().getMouseListener());
if(getCurrentScreen().getMouseMotionListener() != null) removeMouseMotionListener(getCurrentScreen().getMouseMotionListener());
if(getCurrentScreen().getKeyListener() != null) removeKeyListener(getCurrentScreen().getKeyListener());
// if(currentScreen.getMouseWheelListener() != null) removeMouseWheelListener(currentScreen.getMouseWheelListener());
}
}
private void addListeners(){
if(getCurrentScreen() != null){
if(getCurrentScreen().getMouseListener() != null)addMouseListener(getCurrentScreen().getMouseListener());
if(getCurrentScreen().getMouseMotionListener() != null) addMouseMotionListener(getCurrentScreen().getMouseMotionListener());
if(getCurrentScreen().getKeyListener() != null){
addKeyListener(getCurrentScreen().getKeyListener());
}
// if(currentScreen.getMouseWheelListener() != null) addMouseWheelListener(currentScreen.getMouseWheelListener());
}
}
public void paint(Graphics g){
g.drawImage(getCurrentScreen().getImage(), 0, 0, null);
}
public void run(){
while(true){
getCurrentScreen().update();
repaint();
try {
Thread.sleep(30);
repaint();
revalidate();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public Screen getCurrentScreen() {
return currentScreen;
}
public void setCurrentScreen(Screen currentScreen) {
this.currentScreen = currentScreen;
}
}
This is how a game would start:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.JFrame;
import game.mainScreenTeam.Dragon;
import game.mainScreenTeam.HomeScreen;
import game.miniGameTeam.GameInstructions;
import game.miniGameTeam.GameScreen;
import game.miniGameTeam.HighScoreScreen;
import game.shopScreen.BuyScreenWendy;
import game.shopScreen.HomeShopScreen;
import game.shopScreen.SellShopZheng;
import guiPractice.GUIApplication;
import guiPractice.Screen;
import guiPractice.components.AnimatedComponent;
/**
* #author Kat
*
*/
public class DragonLand extends GUIApplication {
public static DragonLand game;
public static int coins = 1500;
public static HomeScreen homeScreen;
public static Screen shopMain; // shop 1
public static Screen sellScreen; // shop 2
public static Screen buyScreen; // shop 3
public static Screen highscoreScreen; // high score
public static GameScreen miniGameScreen; // minigame
public static Screen gameInstructionsScreen;
public static Screen HelpScreen;
public static Color NAVY;
public static Color BRIGHT_PINK;
public static Color LIGHT_PINK;
public static Color LIGHT_NUDE;
public static Color DARKER_NUDE;
/**
*
*/
// public static void addDragon(AnimatedComponent a){
// dragonList.add(a);
// }
public DragonLand() {
}
/* (non-Javadoc)
* #see guiPractice.GUIApplication#initScreen()
*/
#Override
protected void initScreen() {
initColors();
miniGameScreen = new GameScreen(getWidth(),getHeight());
shopMain = new HomeShopScreen(getWidth(),getHeight());
sellScreen = new SellShopZheng(getWidth(),getHeight());
homeScreen = new HomeScreen(getWidth(),getHeight());
buyScreen = new BuyScreenWendy(getWidth(),getHeight());
highscoreScreen = new HighScoreScreen(getWidth(),getHeight());
HomeScreen.jenCode = new game.mainScreenTeam.HomeJenniber();
gameInstructionsScreen = new GameInstructions(getWidth(), getHeight());
setScreen(homeScreen);
}
private void initColors() {
NAVY = new Color(62,74,99);
BRIGHT_PINK = new Color(224,102,102);
LIGHT_PINK = new Color(248,186,182);
LIGHT_NUDE = new Color(244,215,183);
DARKER_NUDE = new Color(230,195,147);
}
/**
* #param args
*/
public static void main(String[] args) {
game = new DragonLand();
Thread go = new Thread(game);
go.start();
}
//public coin getter + setter
public void setCoins(int x){
coins = x;
}
public int getCoins(){
return coins;
}
}
This is the home screen
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import game.DragonLand;
import guiPractice.ClickableScreen;
import guiPractice.components.Action;
import guiPractice.components.AnimatedComponent;
import guiPractice.components.Button;
import guiPractice.components.Graphic;
import guiPractice.components.TextLabel;
import guiPractice.components.Visible;
import guiPractice.sampleGames.MouseFollower;
/**
* #author Kat
* #author Jenniber
*
*/
public class HomeScreen extends ClickableScreen implements Runnable{
private Graphic background;
public static HomeJenniber jenCode;
public HomeScreen(int width, int height) {
super(width, height);
Thread play = new Thread(this);
play.start();
}
#Override
public void initAllObjects(ArrayList<Visible> viewObjects) {
background=new Graphic(0,0,getWidth(),getHeight(),"img/Grassland.png");
viewObjects.add(background);
HomeKat katCode=new HomeKat(viewObjects, getWidth(), getHeight());
}
#Override
public void run() {
}
}
katCode adds buttons to the screen and image annimations
public void paint(Graphics g){
g.drawImage(getCurrentScreen().getImage(), 0, 0, null);
}
Don't override paint() on a JFrame.
The proper way to do custom painting is to override paintComponent(...) on a JPanel (or JComponent) and then you can set the content pane of the frame to this panel. And don't forget to invoke super.paintComponent(...) as the first statement in the method. Read the section from the Swing tutorial on Custom Painting for more information and working examples.
However if you do get lazy, then at minimum you need to invoke super.paint(...) as the first statement in the paint(...) method.
Also, I doubt you need the revalidate(), since you don't appear to be adding/removing components from the frame.
But in general the order should be:
revalidate(); // to invoke the layout manager
repaint(); // paint components in new location.
I also don't know why you are invoking the update() method. That seems like old AWT code which you don't use in Swing. I suggest you take a look at the tutorial link I gave you and look at the table of contents for other Swing basics.

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.

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

Create a Swing component based on another but with different API

I would like to create a new Swing JComponent based on an existing one, but with a different API. In other words, I don't want to extend the existing component, because I don't want it's API to be accessible.
Here an example to clarify my needs:
A replacement of the JCheckBox which show two buttons ON/OFF. This could be based on a pre-configured JCommandButtonStrip (some info here) but exposing exactly the same API of JCheckBox. The configuration of the JCommandButtonStrip must not be altered.
What is the best approach for such a problem?
Clarifications:
As someone pointed out, what I wrote about API is not clear.
Of course JComponent have a number of public fields and methods which will be available for each sub-class. Then each sub-class of JComponent may add its own public fields and methods. For example, AbstractButton adds the isSelected() method, while JCommandButtonStrip adds the getButtonCount() method.
So, what I meant is: I want to create a new JComponent sub-class MyJComponent, which is based on an existing one ExistingJComponent. I don't want the public methods of ExistingJComponent, except those of JComponent, to be exposed by my class MyJComponent. Then I want to add some public methods to MyJComponent.
Please note that I'm not looking for an alternative to the JCommandButtonStrip/JCheckBox example. I'm interested in a general approach to such a problem.
You can create a new class which extends JComponent then inside the constructor insert a checkbox into itself.
public class MyCoolCheckbox extends JComponent{
private JCheckBox checkbox;
public MyCoolCheckbox(String label) {
checkbox= new JCheckBox(label);
this.setLayout(new BorderLayout());
this.add(checkbox, BorderLayout.CENTER);
}
}
This is obviously incomplete and you may need to delegate certain methods to the child. It might get messy. IDEs like IntelliJ IDEA will generate all this for you if you hit alt-ins (by default) then delegate, then select the checkbox member and pick the entries you want to delegate. For example:
public void setForeground(Color fg) {
checkbox.setForeground(fg);
}
public void setBackground(Color bg) {
checkbox.setBackground(bg);
}
public Color getForeground() {
return checkbox.getForeground();
}
public Color getBackground() {
return checkbox.getBackground();
}
Keep in mind that because the child is within the Swing component tree, other code will have access to the children even though they are marked private.
((JCheckBox)myCoolCheckbox.getComponents()[0]).setSelected(true);
As shown here, you can use two instances of JToggleButton in a ButtonGroup to "show two buttons ON / OFF." The ButtonGroup causes only one button in the group to be selected at a time. The following change is illustrated:
private final JLabel label = new JLabel(" \u2713 ");
Based on this picture of JCommandButtonStrip:
I think you are looking for JToggleButton as #trashgod suggested, but I'm not sure about buttons group given the current description of your "problem". If you need buttons group then use it.
Anyway my answer points to this line:
This could be based on a pre-configured JCommandButtonStrip (some info
here) but exposing exactly the same API of JCheckBox.
Once again it's not clear if you're trying to do a buttons bar such as JCommandButtonStrip or you want to do something else. However you can make your own component extending from JComponent and delegate only those methods that are needed from the outside. For example let's say you want to do a buttons bar such as JCommandButtonStrip. Then you can have:
One class extending from JComponent: your buttons bar.
Another one providing an API to add "commands" to the buttons bar.
Note: There's already a JToolBar component which can perfectly be used without reinvent the wheel. The example below is just to show you that you can control the API offered to the developers.
MyCommandBar.java
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.event.ChangeListener;
public class MyCommandBar extends JComponent {
private final JPanel content;
private final Map<String, CommandItem> map = new HashMap<>();
public MyCommandBar() {
super();
content = new JPanel(new GridLayout(1, 0));
content.setOpaque(false);
setLayout(new FlowLayout());
add(content);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics graphics = g.create();
graphics.setColor(getBackground());
graphics.fillRect(0, 0, getWidth(), getHeight());
graphics.dispose();
}
public void addCommandItem(String actionCommand, CommandItem commandItem) {
if(map.get(actionCommand) != null) {
removeCommandItem(actionCommand);
}
content.add(commandItem.getComponent());
map.put(actionCommand, commandItem);
}
public void removeCommandItem(String actionCommand) {
CommandItem commandItem = map.get(actionCommand);
if(commandItem != null) {
content.remove(commandItem.getComponent());
content.revalidate();
content.repaint();
map.remove(actionCommand);
}
}
public CommandItem getCommandItem(String actionCommand) {
return map.get(actionCommand);
}
public static class CommandItem {
public static final int TOGGLE_BUTTON_STYLE = 0;
public static final int CHECK_BOX_STYLE = 1;
public static final int DEFAULT_BUTTON_STYLE = 2;
private final AbstractButton component;
public CommandItem(String text, boolean state, Icon icon, int style) {
switch(style) {
case TOGGLE_BUTTON_STYLE : component = new JToggleButton(text, icon, state); break;
case CHECK_BOX_STYLE : component = new JCheckBox(text, icon, state); break;
default: component = new JButton(text, icon);
}
}
protected AbstractButton getComponent() {
return component;
}
public void addActionListener(ActionListener listener) {
component.addActionListener(listener);
}
public void addChangeListener(ChangeListener listener) {
component.addChangeListener(listener);
}
public void setAction(Action action) {
component.setAction(action);
}
}
}
Example of use
This code snippet shows how MyCommandBar class should be used:
MyCommandBar commandBar = new MyCommandBar();
commandBar.setBorder(BorderFactory.createLineBorder(Color.black, 1));
commandBar.addCommandItem("BOLD", new MyCommandBar.CommandItem("<html><b>Bold</b></html>", true, null, MyCommandBar.CommandItem.TOGGLE_BUTTON_STYLE));
commandBar.addCommandItem("ITALICS", new MyCommandBar.CommandItem("<html><i>Italics</i></html>", false, null, MyCommandBar.CommandItem.CHECK_BOX_STYLE));
commandBar.addCommandItem("UNDERLINE", new MyCommandBar.CommandItem("<html><u>Underline</u></html>", false, null, MyCommandBar.CommandItem.DEFAULT_BUTTON_STYLE));
And you'll see something like this:
You can create MyJComponent subclass of JComponent with a private field that references a forwarding class for ExistingComponent.
The interactions with ExistingComponent are done with the forwarding class through methods of MyJComponent, and you are free to add more methods to MyJComponent.
Please see Effective Java item 16, for the delegation pattern used with the forwarding class.

draw and save an image

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.

Categories