I've started working on a project for my Java class - LAN gomoku/five in a row. The game board is represented by a 2-dimensional array filled with buttons (JButton). With the event handler (class clickHandler) I want to draw an oval on the button that I click (the parameter of a clickHandler object). My following code hasn't worked though (I don't know how to get rid of the null-value of variable g)... I'd appreciate any piece of advice. Thank You a lot.
class clickHandler implements ActionListener {
JButton button;
Dimension size;
Graphics g;
public clickHandler(JButton button) {
this.button = button;
this.size = this.button.getPreferredSize();
}
#Override
public void actionPerformed(ActionEvent ae) {
this.g.setColor(Color.BLUE);
this.g.fillOval(this.button.getHorizontalAlignment(), this.button.getVerticalAlignment(), this.size.width, this.size.height);
this.button.paint(this.g);
this.button.setEnabled(false);
}
}
(In a class that creates the GUI - the game board full of buttons - I assign each button a new Action Listener - an instance of clickHandler) this way:
gButton.addActionListener(new clickHandler(gButton));
You have to:
Extends the JButton class, and override the paintComponent(Graphics g) method.
Do override getPreferredSize() method, which will return on Dimension object and will help the Layout Manager in placing your JButton on the Container/Component, by providing it one appropriate size.
Make your circle code there.
add an onClickListener, and set a flag on the clicked button if it is clicked, and call it to repaint.
About the Graphics object: it's best to keep it in it's paintComponent method, and to use it only there. It will always get passed in on a repaint, and if you save it for other moments, strange things can happen (happy experimenting :) ).
A small Example :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonExample
{
private MyButton customButton;
private void displayGUI()
{
JFrame frame = new JFrame("Custom Button Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
customButton = new MyButton();
customButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
MyButton.isClicked = true;
customButton.repaint();
}
});
frame.getContentPane().add(customButton, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ButtonExample().displayGUI();
}
});
}
}
class MyButton extends JButton
{
public static boolean isClicked = false;
public Dimension getPreferredSize()
{
return (new Dimension(100, 40));
}
public void paintComponent(Graphics g)
{
if (!isClicked)
super.paintComponent(g);
else
{
g.setColor(Color.BLUE);
g.fillOval(getHorizontalAlignment(), getVerticalAlignment(), getWidth(), getHeight());
}
}
}
Related
I have written this code however I am having trouble with one aspect I wish to code into it. I want to make the green square change size when I press one of the three buttons I have so when I press the button 'small' the square changes size to small e.g. 100 and when I press the button 'medium' it changes size to medium e.g. 400. This is my code so far:
package Lab2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
FilledFrame frame = new FilledFrame();
frame.setVisible( true );
}
}
class FilledFrame extends JFrame {
int size = 400;
public FilledFrame()
{
JButton butSmall = new JButton("Small");
JButton butMedium = new JButton("Medium");
JButton butLarge = new JButton("Large");
JButton butMessage = new JButton("Say Hi");
SquarePanel panel = new SquarePanel(this);
JPanel butPanel = new JPanel();
butPanel.add(butSmall);
butPanel.add(butMedium);
butPanel.add(butLarge);
butPanel.add(butMessage);
add(butPanel, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
setSize( size+100, size+100 ); } }
class SquarePanel extends JPanel {
FilledFrame theApp;
SquarePanel(FilledFrame app)
{
theApp = app;
}
public void paintComponent ( Graphics g)
{
super.paintComponent(g);
g.setColor(Color.green);
g.fillRect(20, 20, theApp.size, theApp.size);
}
}
class buttonHandler implements ActionListener {
FilledFrame theApp;
int size;
public buttonHandler(FilledFrame app, int size) {
theApp = app;
this.size = size;
}
#Override
public void actionPerformed (ActionEvent e){
theApp.setSize(this.size, this.size);
}
}
As I don't see any event listeners for your buttons, I assume this is all the code you have. Your buttons will not do anything unless you tell them to do it. You need to add event listeners, and through that change the size and update the panel.
Example:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
theApp.size = 200;
frame.getContentPane().repaint();
//OR frame.repaint();
}
});
EDIT:
The problem with using the button handler class is you would need to find which buttton was pressed, instead its easier to use the way I showed above. I edited the code above, try copy pasting to one of the buttons.
I am getting a problem in java program for moving a circle. The program has 2 basic buttons:
START: used for moving the circle
STOP: used for exiting the program
My problem is that the circle appears before I press the start button. However I make the call to move only when START Button is pressed which makes the call to repaint and then the circle should appear. But it appears by default. I have no problem in moving the circle. Here is my source code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Moving extends JFrame implements ActionListener
{
JButton start,stop;Move mypanel;
Moving()
{
setTitle("Moving circle");
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800,600);
start=new JButton("START");
stop=new JButton("STOP");
start.addActionListener(this);stop.addActionListener(this);
JPanel p=new JPanel();
p.setLayout(new FlowLayout());
p.add(start);p.add(stop);
getContentPane().add(p,BorderLayout.SOUTH);
mypanel=new Move();
getContentPane().add(mypanel,BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent e)
{
String s=e.getActionCommand();
if(s.equals("STOP"))
System.exit(0);
else if(s.equals("START"))
mypanel.move();
}
public static void main(String []args)
{
Moving obj=new Moving();
obj.setVisible(true);
}
}
class Move extends JPanel
{ static int x=80, cv=0;
public void move()
{
repaint();
}
public void paintComponent(Graphics g)
{
setBackground(Color.green);
super.paintComponent(g);
g.setColor(Color.red);
if(x<500&&cv==0)
{g.fillOval(x, 80, 100, 100);this.inc();}
else if((x>=500||cv==1)&&x>=80)
{
cv=1;g.fillOval(x, 80, 100, 100);this.dec();
}
else cv=0;
}
public void inc()
{
x+=10;
}
public void dec()
{
x-=10;
}
}
By default setVisible would be true. So, if you don't won't to show panel on load then make it false on constructor.
And then make it visible when you hit Start.
See below:
class Move extends JPanel {
static int x = 80, cv = 0;
Move(){
setVisible(false); <-- Make it false here
}
public void move() {
this.setVisible(true); <----- make it visible here when you click start
repaint();
}
public void paintComponent(Graphics g) {
setBackground(Color.green);
..... REMAINING CODE
}
}
My suggestion is that if you do not want to show your circle before the pressing of the start button you have to remove drawing of the circle from the paintComponent method.
You can achieve the above by declaring a new method in your Move class say drawCircle like this:
public void drawCircle(Graphics g){
g.setColor(Color.red);
if(x<500&&cv==0)
{g.fillOval(x, 80, 100, 100);this.inc();}
else if((x>=500||cv==1)&&x>=80)
{
cv=1;g.fillOval(x, 80, 100, 100);this.dec();
}
else cv=0;
}
now in your Move class introduce a new boolean variable say circleShowing and intialise to false. This is declared so that the paintComponent method of the Move class can decide whether the circle should be drawn or not. You can do it like this:
public void paintComponent(Graphics g){
setBackground(Color.green);
super.paintComponent(g);
if(circleShowing){
drawCircle(g);
}
}
Now finally in the actionPerformed method of your Moving class you in the else if block you could write the following:
mypanel.circleShowing = true;
mypanel.move();
I hope if you make these changes this will work as you wish.
Ok so I have my main class which got some buttons one for a triangle and the other for an
oval and boxes.
And i got a button for ColorChooser I want to click on it and ColorChooser show up. I have
the class for the oval and triangles and ColorChooser and i set each one of them to a mode
in my main program.
So this is my main program with only the boxes and ColorChooser:
As you can see im using modes for each button and i set mode 4 for ColorChooser
If you want me to add the box class or the ColorChooser class i will if it is not making
sense. I just dont want it to be any longer.
This is my main program:
import java.awt.*;
import java.util.ArrayList;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
public class Kaleidescope extends JFrame implements MouseListener, ActionListener,
MouseMotionListener
{
Box b;
ArrayList<Box> boxes; // list of boxes
ColorChooser oo;
ColorChooser[] colors;
int colorCount;
// Buttons
JButton boxButton;
JButton ColorButton;
int x1, y1; // mousePressed
int w1, z1; // mouseEntered
int mode =1; // 1 = line, 2= boxes, 3 = oval, 4= text, 5 = SG, twoLines = 7.
public static void main( String[] args )
{
System.out.println("hi there.");
new Kaleidescope();
}
public Kaleidescope()
{
setDefaultCloseOperation( EXIT_ON_CLOSE );
addMouseListener(this);
addMouseMotionListener(this);
boxes = new ArrayList<Box>();
colors = new ColorChooser[20];
colorCount = 0;
setLayout( new FlowLayout() );
boxButton = new JButton("Boxes");
add(boxButton);
boxButton.addActionListener( this );
ColorButton = new JButton("Color Chooser");
add(ColorButton);
ColorButton.addActionListener( this);
setSize( new Dimension(500,500) );
setVisible(true);
}
// returns a random color
public Color randomColor()
{
int red = (int)(Math.random()*255);
int green = (int)(Math.random()*255);
int blue = (int)(Math.random()*255);
return new Color(red,green,blue);
}
public void mouseClicked( MouseEvent e )
{
// box
if ( mode == 2)
{
boxes.add(new Box(e.getX(), e.getY(), randomColor()));
}
repaint();
}
//action performed
public void actionPerformed( ActionEvent e )
{
if ( e.getSource()==TriangleButton ) { mode = 1;}
else if ( e.getSource()==boxButton ) { mode = 2;}
else if ( e.getSource()==ovalButton) { mode = 3;}
else if ( e.getSource()==ColorButton) { mode = 4;}
//clear all
else if (e.getSource() == clearButton)
{
boxes.clear();
triangles.clear();
ovals.clear();
}
repaint();
}
public void mouseEntered( MouseEvent e ) { }
public void mousePressed( MouseEvent e ) { }
public void mouseExited( MouseEvent e ) { }
public void mouseReleased( MouseEvent e ) {}
public void mouseMoved( MouseEvent e ) {}
public void mouseDragged( MouseEvent e ){ }
}
public void paint( Graphics g )
{
//draw/paint box triangle and oval
super.paint(g);
for (Box box : boxes)
{
box.drawMe(g);
}
}
}
here is my colorChooser class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
public class ColorChooser extends JPanel implements ChangeListener
{
public static final long serialVersionUID = 1L;
public JColorChooser tcc;
public JLabel banner;
public ColorChooser()
{
super(new BorderLayout());
banner = new JLabel("",JLabel.CENTER);
banner.setOpaque(true);
banner.setPreferredSize(new Dimension(100, 65));
JPanel bannerPanel = new JPanel(new BorderLayout());
bannerPanel.add(banner, BorderLayout.CENTER);
bannerPanel.setBorder(BorderFactory.createTitledBorder("Banner"));
//Set up color chooser for setting text color
tcc = new JColorChooser(banner.getForeground());
tcc.getSelectionModel().addChangeListener(this);
tcc.setBorder(BorderFactory.createTitledBorder("Choose Text Color"));
add(bannerPanel, BorderLayout.CENTER);
add(tcc, BorderLayout.PAGE_END);
}
public void stateChanged(ChangeEvent e)
{
Color newColor = tcc.getColor();
banner.setForeground(newColor);
}
private static void createAndShowGUI()
{
//Create and set up the window.
JFrame frame = new JFrame("ColorChooserDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new ColorChooser();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Start by taking a look at How to Write an Action Listener and How to Use Color Choosers
Basically, attach a ActionListener to the JButton you want to activate the JColorChooser and when the actionPerformed method is called, use inbuilt functionality to show the default chooser window, for example (from the linked tutorial)...
Color newColor = JColorChooser.showDialog(
ColorChooserDemo2.this,
"Choose Background Color",
banner.getBackground());
Updated
Start by adding a Color instance variable to Kaleidescope, this will allow you to maintain a reference to the last chossen color
private Color currentPaintColor = Color.BLACK;
Next, when the ColorButton is pressed, you will want to create some kind of dialog to show the chooser in, this will allow you to wait until the user chooses a color and get the resulting color...
} else if (e.getSource() == ColorButton) {
ColorChooser chooser = new ColorChooser();
int result = JOptionPane.showConfirmDialog(this, chooser, "Color Chooser", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
currentPaintColor = chooser.getChoosenColor();
}
} //clear all
You'll also want to change the stateChanged method in ColorChooser to make it more meaningful...
public void stateChanged(ChangeEvent e) {
Color newColor = tcc.getColor();
banner.setBackground(newColor);
}
Now, the question is, what do you want to do with this new color? Do you want to apply it to all the current shapes you are painting? If so you need to set the color before painting the shapes...
public void paint(Graphics g) {
//draw/paint box triangle and oval
super.paint(g);
g.setColor(currentPaintColor);
for (Box box : boxes)
{
box.drawMe(g);
}
}
Or do you only want to apply the color to new objects added after the change?
You should avoid overriding paint of top level containers, lots of reason, they aren't double buffered, which will cause flickering when they are updated and you will be painting over the top of everything else on the frame and you can potentially paint under the frame borders...
Instead you should use something JPanel and override it's paintComponent method, take a look at Performing Custom Painting for more details
You need to clarify just what you expect a mode = 4 will do with your program. I can understand using JButton presses to set shape modes (object state) that will alter the behavior of your MouseListener, but I don't see how a color chooser will fit into this model, and in fact believe that it likely won't. I don't have the rest of your code, nor do I have the specifics of your assignment, but I'm going to make some recommendations based on guesses, and thus these will necessarily be weak recommendations.
I'm guessing that you want to have a JColorChooser dialog displayed when the color button is pressed.
And that the user then can select a Color that will be the color of the drawn shapes.
If so, then likely you shouldn't have the color chooser button (which should be named colorChooserButton) set a numeric node. Rather, it should open your color choosing dialog, and after the user has selected a color, then you should set a Color field in your drawing class, not the mode value.
Rather the modes should only be used to select an appropriate shape that the MouseListener will use to determine what shape to draw.
Myself, I wouldn't use numeric modes but rather an enum to define this state, but that is probably something you'll learn later in your programming education.
If my assumptions are incorrect, then please clarify them.
As an aside, note that you should not draw in a paint(Graphics g) method, and should not draw directly in the JFrame. Rather you should draw in the paintComponent(Graphics g) method override of a JPanel or JComponent.
Here's a runnable example of how JColorChooser can be used to set the color for different tasks. Feel free to ask questions if you are unclear about anything.
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 javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ColorChooserPaintExample {
private Color color = Color.BLUE;
private ColorPanel colorPanel = new ColorPanel();
public ColorChooserPaintExample() {
final JFrame frame = new JFrame("My Color Chooser Demo");
JButton chooseColor = new JButton("Change Color of Panel");
chooseColor.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
color = JColorChooser.showDialog(frame, "Choose a Color for Panel", color);
colorPanel.repaint();
}
});
frame.add(colorPanel);
frame.add(chooseColor, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class ColorPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new ColorChooserPaintExample();
}
});
}
}
I am trying to get my hands on GUI programming in java and wanted to draw a rectangle in Jpanel. Code does not give any error but I cannot get rectangle in the GUI. Can somebody please tell me what I am missing in the following code. I am sure it is pretty simple so please be gentle.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class HelloWorldGUI2 {
private static class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
private static class RectDraw extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(230,80,10,10);
g.setColor(Color.RED);
g.fillRect(230,80,10,10);
}
}
public static void main(String[] args) {
JPanel content = new JPanel();
RectDraw newrect= new RectDraw();
JButton okButton= new JButton("OK");
JButton clearButton= new JButton("Clear");
ButtonHandler listener= new ButtonHandler();
okButton.addActionListener(listener);
clearButton.addActionListener(listener);
content.add(okButton);
content.add(clearButton);
content.add(newrect);
JFrame window = new JFrame("GUI Test");
window.setContentPane(content);
window.setSize(250,100);
window.setLocation(100,100);
window.setVisible(true);
}
}
Your newrect RectDraw's size is likely going to be quite small, probably [0, 0], since it has been added to a FlowLayout using JPanel and doesn't have a preferredSize set. Consider overriding its getPreferredSize() method and returning a suitable Dimension so that its drawing can be seen.
private static class RectDraw extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(230,80,10,10);
g.setColor(Color.RED);
g.fillRect(230,80,10,10);
}
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H); // appropriate constants
}
}
Also,
The paintComponent method should be protected, not public
Don't forget to use #Override before your method overrides.
Aim for much less code in the main method and more code in the "instance" world, not the static world.
Take care with your code formatting. Poor code formatting, especially misleading indentations, leads to silly errors.
I hope I can remember to include all my details so here it goes.
I'm working with Java and I'm creating my own interface with the main window being a JFrame, the background is attached to the JFrame with a Background image(as JLabel) that fits exactly with the window. Then I have an image that is attached to the background Jlabel to act as a "start" button. My problem is I'd like to create a custom class that will facilitate each buttons functions inside its own class.
so instead of having functions in the main class that will react to the buttons, I'd like to make a class that can be added to the background... here is my code maybe someone could give me an example and I can figure out the rest or point me in the right direction.
The following code contains the original, please provide an example of how you would change it to encapulate eventlisteners in its own class for the Jlabel button
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class pipboy{
public static void main(String[] args){
pipboy pipboy_os = new pipboy();
pipboy_os.runmain();
}
public void runmain(){
//Create and set up the window.
JFrame frame = new JFrame("PIPBOY Research v0.0.03");
//background
ImageIcon background = new ImageIcon("UI/background/default.png");
JLabel label=new JLabel(background);
//radiation animated
ImageIcon animated_loading = new ImageIcon("UI/icon/loading/loading.png");
JLabel animated_icon = new JLabel(animated_loading);
animated_icon.setSize(128, 128);
animated_icon.setLocation(300, 125);
//Buff arm guy icon
ImageIcon icon_loading = new ImageIcon("UI/icon/34.png");
JLabel icon = new JLabel(icon_loading);
icon.setSize(128, 128);
icon.setLocation(300, 50);
label.add(icon);
label.add(animated_icon);
frame.add(label);
//Display the window.
frame.pack();
frame.setVisible(true);
//Full screen
frame.setSize(800,480);
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
//Set default close operation for JFrame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//This is the handler class i made but i want it in its own class with the buff arm icon picure so it can do something specific when the image is pressed
HandlerClass handler = new HandlerClass();
frame.addMouseListener(handler);
frame.addMouseMotionListener(handler);
}
private static class HandlerClass implements MouseListener, MouseMotionListener{
public void mouseClicked(MouseEvent event){
System.out.println(String.format("Clicked at %d,%d", event.getX(), event.getY()));
}
public void mousePressed(MouseEvent event){
}
public void mouseReleased(MouseEvent event){
}
public void mouseEntered(MouseEvent event){
}
public void mouseExited(MouseEvent event){
}
public void mouseDragged(MouseEvent event){
}
public void mouseMoved(MouseEvent event){
}
}
}
Apparently I didn't know how polymorhpism worked in Java but here is my solution (with some names altered)
import javax.swing.*;
class GUItests{
public JFrame mainContainerFrame;
public static void main(String[] args){
GUItests mainController = new GUItests();
mainController.startGUI();
}
public void startGUI(){
mainContainerFrame = new JFrame("test Frame");
mainContainerFrame.setSize(800,480);
mainContainerFrame.pack();
mainContainerFrame.setVisible(true);
mainContainerFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel customButtonVar = customButton();
mainContainerFrame.getContentPane().add(customButtonVar);
}
public JLabel customButton(){
JLabel icon = new JLabel("testing");
icon.setSize(128, 128);
icon.setLocation(300, 50);
return icon;
}
}