Given a JFrame I am drawing lines on it by handling MouseListener. Now I had added a button to choose a color from Color chooser . I want that after selecting a color all lines that i draw become of that choose color.
Here is my code I had tried adding code to ButtonListener but can't get any success.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class myJPanelstd extends JPanel implements MouseMotionListener
{
JButton bmessage;
JPanel p1;
JButton changeColor;
public myJPanelstd(){
setBackground(Color.pink);
setLayout(new BorderLayout());
p1 = new JPanel();
p1.setLayout(new GridLayout(3,3));
bmessage = new JButton();
changeColor= new JButton("CHANGE COLOR");
p1.add(bmessage);
p1.add(changeColor);
add(p1,"South");
changeColor.addActionListener(new ButtonListener());
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent evt)
{
Point pt = evt.getPoint();
String sx = "x = " + pt.getX();
String sy = "y = " + pt.getY();
bmessage.setText("you are doing fine");
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Color c = JColorChooser.showDialog(null, "Choose a Color", sampleText.getForeground());
//if (c != null)
//sampleText.setForeground(c);
}
}
public void mouseDragged(MouseEvent evt)
{
bmessage.setText("Nice Drawing!");
Point pt = evt.getPoint();
Graphics gg = getGraphics();
gg.setColor(Color.RED);
gg.fillRect(pt.x,pt.y,5,5);
getGraphics().setColor(Color.RED);
getGraphics().fillRect(pt.x,pt.y,5,5);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.blue);
Image myImage = Toolkit.getDefaultToolkit().getImage("images/fred.jpg");
g.drawImage(myImage, 0, 0, this);
g.setColor(Color.yellow);
g.drawString("Draw on Me", 250,150);
}
}
You need to store all painted elements and repaint them in paintComponent(), otherwise they will disappear when you minimalize/resize/cover window and uncover/ etc.
For example every line you are creating store in ArrayList and repaint them in a loop at the beginning of paintComponent(), then when you change color, all lines will be painted in new color.
Don't forget to repaint() after color change
Simple pseudo code - just to see the idea - it won't compile
class A extends JPanel
{
ArrayList<Shape> shapes;
public A()
{
shapes = new ArrayList<Shape>();
}
public void afterMouseRelease();
{
//paint the shape
shapes.add(yourNewShape); // store it for later
}
public void paintComponen(Graphics g)
{
super.paintComponent();
setColor()
for(Shape s : shapes)
{
// paint it again
}
// rest of painting
}
}
I used Shape class from java.awt.Shape, and Graphics2D in my app some time ago.
Use JColorChooser.showDailog(-,-); to choose color under your action listener
Refer sample color picker using Java swing
// ColorPicker.java
// A quick test of the JColorChooser dialog.
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ColorPicker extends JFrame {
public ColorPicker() {
super("JColorChooser Test Frame");
setSize(200, 100);
final Container contentPane = getContentPane();
final JButton go = new JButton("Show JColorChooser");
go.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Color c;
c = JColorChooser.showDialog(
((Component)e.getSource()).getParent(),
"Demo", Color.blue);
contentPane.setBackground(c);
}
});
contentPane.add(go, BorderLayout.SOUTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String args[]) {
ColorPicker cp = new ColorPicker();
cp.setVisible(true);
}
}
Related
So, I've been studying GUI's and event handling, and I make this code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class drawing extends JComponent {
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.draw(new Rectangle(100, 100, 100, 100));
}
}
class TwoButtons {
public static void main(String[] args) {
TwoButtons two = new TwoButtons();
two.go();
}
JButton button1 = new JButton("button 1");
JButton button2 = new JButton("button 2");
drawing D = new drawing();
JFrame frame = new JFrame("title");
void go() {
button1.addActionListener(new button1Action());
button2.addActionListener(new button2Action());
frame.add(BorderLayout.SOUTH, button1);
frame.add(BorderLayout.NORTH, button2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(900, 900);
frame.setVisible(true);
}
class button1Action implements ActionListener {
public void actionPerformed(ActionEvent ev) {
frame.add(D);
}
}
class button2Action implements ActionListener {
public void actionPerformed(ActionEvent ev) {
button2.setText("action 2");
}
}
}
So this code generates two buttons at SOUTH and another at NORTH of JFrame.
It should display a square as soon as user clicks button1, but it displays a Square after both button1 and button2 are clicked (first button1 and then button2).
Why is this happening? and how to fix it?
Swing is lazy. When dynamically updating the UI, you need to instruct it when you want it to perform and update pass, for example...
class button1Action implements ActionListener {
public void actionPerformed(ActionEvent ev) {
frame.add(D);
frame.revalidate();
frame.repaint();
}
}
This triggers a layout and paint pass after D is added to the frame
so this is my problem. I have an 8*8 grid of panels, all white. Then, when one of them is clicked, it's supposed to change to a random color. The only problem I have right now is that I don't know how to see if the user clicked their mouse in a specific panel. Here is the code I have so far (I'm going to implement the random element afterwards)
`
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GridOfPanels extends JPanel{
int x, y;
public GridOfPanels(){
JPanel content = new JPanel(new GridLayout(8,8));
for(int i = 0; i < 64; i++){
JPanel panel = new JPanel();
panel.setBackground(Color.white);
content.add(panel);
}
this.add(content);
}
public GridOfPanels(Color backColor){
setBackground(backColor);
addMouseListener(new PanelListener());
x = 200;
y = 200;
}
private class PanelListener extends MouseAdapter{
public void mousePressed(MouseEvent e){
x = e.getX();
y = e.getY();
repaint();
}
}
public static void main(String[] args){
JFrame theGUI = new JFrame();
theGUI.setTitle("Grid");
theGUI.setVisible(true);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theGUI.setSize(400,400);
Rectangle z = new Rectangle(x, y, 50, 50);
}
}
`
You have to add a listener to each clickable object. Here is a working example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestFrame extends JFrame{
public TestFrame(int size){
JPanel content = new JPanel(new GridLayout(size, size));
JPanel[] panel = new JPanel[size * size];
PanelListener listener = new PanelListener();
for(int i = 0; i < panel.length; i++){
panel[i] = new JPanel();
panel[i].setBackground(Color.white);
panel[i].addMouseListener(listener);
content.add(panel[i]);
}
this.add(content);
}
// MouseListener offers the method mouseClicked(MouseEvent e)
private class PanelListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent event) {
/* source is the object that got clicked
*
* If the source is actually a JPanel,
* then will the object be parsed to JPanel
* since we need the setBackground() method
*/
Object source = event.getSource();
if(source instanceof JPanel){
JPanel panelPressed = (JPanel) source;
panelPressed.setBackground(Color.blue);
}
}
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent arg0) {}
#Override
public void mouseReleased(MouseEvent arg0) {}
}
public static void main(String[] args){
TestFrame theGUI = new TestFrame(8);
theGUI.setTitle("Grid");
theGUI.setVisible(true);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theGUI.setSize(400,400);
}
}
You have to add MouseListener to one of the panels. Only one panel will react to click event. In the listener cast the source to JPanel and change the color.
I've got an applet with radio buttons to select the color of the line, but when I try to run it, I get this error:
java.lang.NullPointerException
This is what I have thus far. Any suggestions on making color selection work?
import java.awt.*;
import java.applet.*;
import javax.swing.*;
import java.awt.event.*;
public class ProjectPaint extends Applet {
private JRadioButton redButton = new JRadioButton("Red");
private JRadioButton blueButton = new JRadioButton("Blue");
private JRadioButton greenButton = new JRadioButton("Green");
private JRadioButton blackButton = new JRadioButton("Black");
Graphics g;
public void init() {
// Create a border layout design
setLayout(new BorderLayout());
// Make a new object of type DrawPanel
DrawPanel dp = new DrawPanel();
// Add a draw panel in the center
add("Center", dp);
// Add another draw panel for color selection on top
add("North",new DrawControls(dp));
}
int x1;
int y1;
class DrawPanel extends Panel
{
public boolean mouseDown(Event e, int x, int y)
{
// User has started a mouse drag.
// Remember where:
x1 = x;
y1 = y;
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
// User is continuing a mouse drag.
// Draw line from last point to this
// point:
g = getGraphics();
g.drawLine( x1,y1, x,y );
// Remember new "last point":
x1 = x;
y1 = y;
return true;
}
}
class DrawControls extends Panel
{
public DrawControls(DrawPanel target)
{
setLayout(new BorderLayout());
JPanel panel = new JPanel();
ButtonGroup radioButtonGroup = new ButtonGroup();
radioButtonGroup.add(redButton);
radioButtonGroup.add(blueButton);
radioButtonGroup.add(greenButton);
radioButtonGroup.add(blackButton);
panel.add(redButton);
panel.add(blueButton);
panel.add(greenButton);
panel.add(blackButton);
add(panel, BorderLayout.NORTH);
redButton.addActionListener(new RadioButtonListener());
blueButton.addActionListener(new RadioButtonListener());
greenButton.addActionListener(new RadioButtonListener());
blackButton.addActionListener(new RadioButtonListener());
blackButton.doClick();
}
}
private class RadioButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
int color = -1;
if(e.getSource() == redButton)
{
g.setColor(Color.red);
}
if(e.getSource() == blueButton)
{
g.setColor(Color.blue);
}
if(e.getSource() == greenButton)
{
g.setColor(Color.green);
}
if(e.getSource() == blackButton)
{
g.setColor(Color.black);
}
}
}
}
The Graphics reference has not been assigned hence the NPE.
Don't attempt any custom painting from an ActionListener or MouseListener. Instead use a Color class member variable to set the color. For Swing applications, all custom painting should be done in the paintComponent method. In this case DrawPanel will need to changed so as to extend JPanel so that it can override the method. Add the #Override annotation and make sure to invoke super.paintComponent(g).
JApplet has support for the JFC/Swing component architecture so use that also.
I have two JPanels. The first one contains JButtons and in the second simply we can draw on with the Mouse. The problem is when I click on the JButton and start drawing the JButton also draw in on the JPanel. Please do provide me, with some direction, as to where I am not looking at ?
main class
public class LabelDemo extends JFrame {
JPanel p1 = new JPanel();
painter p2 = new painter();
JButton red = new JButton("red");
JButton blue = new JButton(" blue ");
JLabel lbl = new JLabel("Label");
ImageIcon icon = new ImageIcon("image/YouTube.png");
public LabelDemo() {
setLayout(new BorderLayout());
p1.setBorder(new LineBorder(Color.gray));
//jbt1.setIcon(icon);
p1.add(red);
p1.add(blue);
lbl.setOpaque(true);
lbl.setBackground(Color.yellow);
p1.add(lbl);
p1.setBounds(20, 30, 40, 78);
add(p1,BorderLayout.EAST);
add(p2,BorderLayout.CENTER);
}
public static void main(String[] args){
LabelDemo frame = new LabelDemo();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700, 400);
frame.setLocationRelativeTo(null);
}
}
innr class
class painter extends JPanel {
int x , y;
boolean isPresed = false;
public void setPainter(int x , int y) {
this.x = x;
this.y = y;
}
public painter() {
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
isPresed = true;
setPainter(e.getX(),e.getY());
repaint();
}
});
}
protected void paintComponent(Graphics g){
Color randomColor = Color.getHSBColor( (float)Math.random(), 1.0F, 1.0F );
if(isPresed){
g.setColor(randomColor);
g.fillOval(x-5, y-5, 10, 10);
}
}
}//end of painter
Ok, as I understood you want to get rid of panel on east (p1 panel) when clicking red or blue button:
package stack;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class LabelDemo extends JFrame {
JPanel p1 = new JPanel();
Painter p2 = new Painter();
JButton red = new JButton("red");
JButton blue = new JButton(" blue ");
JLabel lbl = new JLabel("Label");
ImageIcon icon = new ImageIcon("image/YouTube.png");
public LabelDemo() {
setLayout(new BorderLayout());
p1.setBorder(new LineBorder(Color.gray));
// jbt1.setIcon(icon);
p2.setPreferredSize(new Dimension(600,400));
p1.add(red);
p1.add(blue);
lbl.setOpaque(true);
lbl.setBackground(Color.yellow);
p1.add(lbl);
p1.setBounds(20, 30, 40, 78);
add(p1,BorderLayout.EAST);
add(p2,BorderLayout.CENTER);
red.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
remove(p1);
repaint();
revalidate();
}
});
blue.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
remove(p1);
repaint();
revalidate();
}
});
}
public static void main(String[] args){
LabelDemo frame = new LabelDemo();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
class Painter extends JPanel {
int x , y;
boolean isPresed = false;
public void setPainter(int x , int y) {
this.x = x;
this.y = y;
}
public Painter() {
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
isPresed = true;
setPainter(e.getX(),e.getY());
repaint();
}
});
}
protected void paintComponent(Graphics g){
Color randomColor = Color.getHSBColor( (float)Math.random(), 1.0F, 1.0F );
if(isPresed){
g.setColor(randomColor);
g.fillOval(x-5, y-5, 10, 10);
}
}
}//end of painter
Also don't call setSize() method call pack() and setPreferredSize(), I was personaly criticized a few times because of that. Just an annotation.
In your painter pane's paintComponent method, you really should call super.paintComponent first.
Swing reuses the Graphics, so its possible to get old content still in its buffer. If you call super.paintComponent, this will clean it up for
protected void paintComponent(Graphics g){
// Must call super.paintComponent() so the Graphics is updated correctly...
super.paintComponent();
Color randomColor = Color.getHSBColor( (float)Math.random(), 1.0F, 1.0F );
if(isPresed){
g.setColor(randomColor);
g.fillOval(x-5, y-5, 10, 10);
}
}
I've hit a wall (in my brain) trying to update my board on button presses. Am I right in thinking that the GameBoard class is the one that needs to be repaint()ed?
GameBoard.java
public class GameBoard extends Panel {
static Compass compass = new Compass();
private static final long serialVersionUID = 1;
Graphics2D g2d;
static final Dimension WINDOW_SIZE = new Dimension(1150, 800);
public void boardMaker() throws Exception {
JFrame frame = new JFrame("Display image");
JPanel panel = new JPanel();
/* unimportant stuff
.....
*/
//
DieRoll roll = new DieRoll("Roll Dies");
roll.setC(compass);
roll.setG2D(g2d);
//
Button button = new Button("new");
button.setGameBoard(this);
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
buttonPanel.add(roll);
buttonPanel.setPreferredSize(new Dimension(200,100));
frame.getContentPane().add(buttonPanel, BorderLayout.NORTH);
//
frame.getContentPane().add(panel);
frame.setVisible(true);
}
public void paint(Graphics g) {
// not important I think
}
}
Button.java
public class Button extends JButton implements ActionListener {
private static final long serialVersionUID = 1L;
JPanel panel = new JPanel();
JFrame frame = new JFrame();
Compass c = new Compass();
GameBoard gb = new GameBoard();
Button(String text) {
this.setText(text);
this.addActionListener(this);
}
void setGameBoard(GameBoard gb) {
this.gb = gb;
}
#Override
public void actionPerformed(ActionEvent e) {
gb.g2d.setColor(Color.black);
gb.g2d.fillRect(100, 100, 100, 200);
gb.repaint();
}
}
This gives a null pointer exception. So any idea how to repaint my GameBoard? I'm not mad if I've to rewrite everything because of stupidity! ;)
Thanks
You have the wrong idea about how to draw in Java. Components like Panels draw themselves, and all drawing takes place on the UI thread.
Check out this tutorial: docs.oracle.com/javase/tutorial/2d/index.html
The article Painting in AWT and Swing may offer some perspective on application-triggered painting. The example below illustrates the principle. Note that setForeground() calls repaint() automatically because the foreground color is a bound property, but you can always call it yourself.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class SwingPaint {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
final GamePanel gp = new GamePanel();
f.add(gp);
f.add(new JButton(new AbstractAction("Update") {
#Override
public void actionPerformed(ActionEvent e) {
gp.update();
}
}), BorderLayout.SOUTH);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
private static class GamePanel extends JPanel {
private static final Random r = new Random();
public GamePanel() {
this.setForeground(new Color(r.nextInt()));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
public void update() {
this.setForeground(new Color(r.nextInt()));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = this.getSize();
int d = Math.min(size.width, size.height) - 10;
int x = (size.width - d) / 2;
int y = (size.height - d) / 2;
g.fillOval(x, y, d, d);
g.setColor(Color.blue);
g.drawOval(x, y, d, d);
}
}
}