im trying to code a swing gui where i can draw shapes at random places by pressing on two different JMenuItems, circle and a rectangle. I got it to work, but i used
Graphics2D gg = (Graphics2D) canvas.getGraphics();
I was advised to use and override paintComponent(). So i started trying that some hours ago :D I know that there are a lots of questions regarding this, but i really read a lot, tried and searched but i cant help myself..
Please have a look in my RandomDrawer Class, i figured out that i have to implement paintComponent() there (i hope so atleast). Further in the next method
public void actionPerformed(ActionEvent e)
im getting to know which action occures, can i or how can i tell him to draw afterwards? Or is my whole approach flawed?
Here is my code.
Thanks for bearing with me and thanks a lot.
package plotterpackage;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.border.BevelBorder;
import javax.swing.text.JTextComponent;
public class PlotterApp implements ComponentListener {
private JFrame frame;
private JPanel canvas;
private JPanel statusBar;
private JTextField status;
/**
* Public default constructor.
*/
public PlotterApp() {
initialize();
}
/**
* Start of the application.
* @param args command line arguments
*/
public static void main(String[] args) {
PlotterApp app = new PlotterApp();
app.start();
}
/**
* Initialize the application.
*/
protected void initialize() {
frame = new JFrame("Main");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setBounds(50,50, 50+640, 50+480);
frame.setBackground(Color.GREEN);
frame.setJMenuBar(createMenuBar());
frame.getContentPane().add(createContent(), BorderLayout.CENTER);
frame.getContentPane().add(createStatusBar(),BorderLayout.SOUTH);
}
/**
* Start the graphical user interface.
*/
public void start() {
// show the GUI
frame.setVisible(true);
status.setText("Application started");
}
/**-*
* Internal helper to create the main content.
* @return component with application content.
*/
protected JComponent createContent() {
canvas = new JPanel();
canvas.addMouseListener(new Painter());
canvas.addMouseMotionListener(new Painter());
canvas.addComponentListener(this);
canvas.setBackground(new Color(128,218,255));
canvas.setForeground(Color.RED);
canvas.setBorder(new BevelBorder(BevelBorder.LOWERED));
return canvas;
}
/**
* Internal helper to create the statusbar and -fields.
* @return component with status/bar.
*/
protected JComponent createStatusBar() {
FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
layout.setHgap(5);
statusBar = new JPanel(layout);
statusBar.add(new JLabel("Status: "));
status = new JTextField();
status.setPreferredSize(new Dimension(400,25));
status.setEditable(false);
status.setBorder(newBevelBorder(BevelBorder.RAISED,Color.MAGENTA,Color.LIGHT_GRAY));
status.getInsets().set(2, 10, 2, 10);
statusBar.add(status);
return statusBar;
}
/**
* Internal helper to create the frames menubar.
* @return menu bar
*/
protected JMenuBar createMenuBar() {
JMenuBar mb = new JMenuBar();
JMenuItem item;
JMenu menu;
// Action menu
menu = new JMenu("Actions");
mb.add(menu);
item = new JMenuItem("Draw RandomCircle");
item.addActionListener(new RandomDrawer());
menu.add(item);
item = new JMenuItem("Draw RandomRectangle");
item.addActionListener(new RandomDrawer());
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Exit");
item.addActionListener(new AppCloser());
menu.add(item);
// Color menu not used so far
menu = new JMenu("Colors");
mb.add(menu);
// Help menu not used so far
menu = new JMenu("Help");
mb.add(menu);
return mb;
}
class AppCloser implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("application finished, bye-bye... ");
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
}
class RandomDrawer extends JPanel implements ActionListener {
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.drawOval(100, 100, 100, 100);
}
@Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
int w;
if (e.getActionCommand()==("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//gg.setColor(Color.BLACK);
//gg.drawOval(x, y, generator.nextInt(x), generator.nextInt(y));
}
else if (e.getActionCommand()==("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//Graphics2D gg = (Graphics2D) canvas.getGraphics();
//gg.setColor(Color.BLACK);
//gg.drawRect(x, y, generator.nextInt(x), generator.nextInt(y));
}
}
}
class Painter extends MouseAdapter implements MouseMotionListener {
Point start, end;
int startX, startY, oldX, oldY, oldWidth, oldHeight;
public void mousePressed(MouseEvent e) {
start = e.getPoint();
oldX = startX;
oldY = startY;
startX = e.getX();
startY = e.getY();
status.setText(String.format("Mouse start: " + start));
}
public void mouseDragged(MouseEvent e) {
Graphics2D gc = (Graphics2D)canvas.getGraphics();
gc.setColor(new Color(128, 218, 255));
gc.drawOval(oldX, oldY, oldWidth, oldHeight);
System.out.printf("oldWidth ist = %3d, oldHeight ist = %3d\n", oldWidth, oldHeight);
oldWidth = e.getX();
oldHeight = e.getY();
gc.setColor(Color.BLACK);
gc.drawOval(startX, startY, e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
end = e.getPoint();
status.setText(String.format("Mouse end: " + end));
}
}
@Override
public void componentHidden(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentMoved(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentResized(ComponentEvent e) {
// TODO Auto-generated method stub
}
@Override
public void componentShown(ComponentEvent e) {
// TODO Auto-generated method stub
}
}
Don't do...
Graphics2D gg = (Graphics2D) canvas.getGraphics();
This is NOT how custom painting should be done. Swing will ask you when it wants something painted and you are expected to repaint the current state of the component.
Start by having a look at Painting in AWT and Swing and Performing Custom Painting for more details
Basically, you need to override the paintComponent
method of JPanel
(making sure to first call super.paintComponent
) and the paint the current state of the component.
You will need to store the state in whatever form is most useful to your (a List
or custom object or even a Image
)
You can request that the API update the UI by calling repaint
when you've changed the state