I am here making a menu for my game where I can press 'Start' button to navigate through the screens. I am trying to implement a seperate button for the class however the way I have laid out the CustomButtons class, it works in a way where I can only make one button which has a function, in order to tackle this issue I decided to make a separate 'Buttons' method which contains the parameters for the button. I have called this within the paint component to ensure that it is being displayed to the screen however only the text 'START' is being displayed to the screen. The background color of the button, the borders, the font etc. isn't being changed alongside the call.
public class CustomButton extends JButton implements MouseListener {
Dimension size = new Dimension(100, 50);
boolean hover = false;
boolean click = false;
boolean isMethodCalled = false;
String text = "";
public CustomButton(String text, Button bb) {
setVisible(true);
setFocusable(true);
setContentAreaFilled(false);
setBorderPainted(false);
this.text = text;
addMouseListener(this);
}
public void Button(Graphics g) {
g.setColor(new Color(255, 255, hover ? 180 : 102 ));
g.fillRect(0, 0, 250, 7);
g.fillRect(0, 0, 7, 150);
g.setColor(Color.ORANGE); // button background color
g.fillRect(14, 14, 222, 122);
g.setColor(Color.WHITE); // text color
g.setFont(Font.decode("arial-BOLD-24"));
FontMetrics metrics = g.getFontMetrics();
int width = metrics.stringWidth(text);
g.drawString(text, 17, 40);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Button menu = new Button();
}
public void setButtonText(String text) {
this.text = text;
}
public String getButtonText(String text) {
return text;
}
public void mouseEntered(MouseEvent e) {
hover = true;
}
public void mouseExited(MouseEvent e) {
hover = false;
}
public void mousePressed(MouseEvent e) {
click = true;
}
public void mouseReleased(MouseEvent e) {
click = false;
}
public void mouseClicked(MouseEvent e) {
}
}
Anyone have any idea how I can make it so the button once it is called from the 'Buttons' method works so it is displayed exactly as it should be if all the graphics settings were to be set within the paintComponent method?
This is not what is currently happening. I do not want this to happen:
This is what I want to happen to the button:
To have the custom appearance you need, it's better that your custom button extends JLabel. Below code demonstrates how we can write a custom button by extending JLabel.
This button supports click events. We can add ActionListeners to listen to click events. It changes the background color to brown when user hovers mouse over it.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
public class CustomButton extends JLabel implements MouseListener {
private List<ActionListener> actionListeners = new ArrayList<>();
public CustomButton(String text) {
super(text);
setOpaque(true);
setForeground(Color.white);
setBackground(Color.orange);
setFont(getFont().deriveFont(40.0f));
addMouseListener(this);
}
public void addActionListener(ActionListener listener) {
actionListeners.add(listener);
}
public void removeActionListener(ActionListener listener) {
actionListeners.remove(listener);
}
#Override
public void mouseClicked(MouseEvent e) {
for (ActionListener listener : actionListeners) {
listener.actionPerformed(new ActionEvent(this, 0, "click"));
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
setBackground(new Color(185, 122, 87));
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(Color.orange);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.darkGray);
frame.getContentPane().setLayout(new FlowLayout());
CustomButton customButton = new CustomButton("START");
customButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "Button clicked");
}
});
frame.getContentPane().add(customButton);
frame.setBounds(300, 200, 400, 300);
frame.setVisible(true);
}
}
Related
I'm struck in a what it seems to be a minor problem. I tried to add MouseListener to Line2D object but it's not working. Is the method or tried is invalid or I can do it another way. Help me figure out what I'm doing wrong here.
public class DrawingLines {
public static void main(String[] args){
LineFrame lf = new LineFrame();
lf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
lf.setVisible(true);
}
}
class LineFrame extends JFrame{
public LineFrame(){
setTitle("Line test");
setSize(500, 500);
LinesPanel lp = new LinesPanel();
Container contentpane = getContentPane();
contentpane.add(lp);
}
}
class LinesPanel extends JPanel{
public LinesPanel(){
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Line2D line = new Line2D.Double(105.5, 306.6, 350.8, 4.9);
g2.draw(line);
line.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Line Clicked !");
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
}
Add the MouseListener to the LinesPanel. And use the MouseEvent coordinates to check whether the click is close to the line.
See How to select a line
The Line component doesn't have a clickable area so a mouselistener won't work properly, what you might want to do is add an invisible square/rectangle/polygon over it to handle the mouse instead.
Im trying to make a function that receive a image and imageicon as parameter, darken it for 2 secs and turn it back to normal, but i cant make the timer works as planned.
public void blinkImage(Image e, ImageIcon f) {
ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent event){
Graphics2D g2 = (Graphics2D) e.getGraphics();
g2.setColor(new Color(0, 0, 0, 50));
g2.fillRect(0, 0, f.getIconWidth(), f.getIconHeight());
}
};
Timer displayTimer = new Timer(2000, listener);
displayTimer.start();
displayTimer.stop();
}
OBS: after this call will be a setIcon(f) in the main window, turning it back to normal. My question is: where should I put the start() and stop() calls? There is a better way to do it?
Thanks and sorry for bad english.
public void blinkImage(Image e, ImageIcon f)
Not sure why you have two parameters. Is the Image the Image in the Icon?
Painting onto the Image will be permanent. So if it is the same Image as the Icon you can't restore the Icon to its original state.
displayTimer.start();
displayTimer.stop();
You can't invoke stop() right after you start() the Timer because the Timer will never fire. So all you need is the start().
Since you only want the Timer to fire once you would just use:
timer.setRepeats( false );
then you don't have to worry about stopping the Timer.
One approach is create a custom Icon with two states. Then you can toggle the state of the Icon:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DarkIcon implements Icon
{
private Icon icon;
private Color color;
private boolean dark = false;
public DarkIcon(Icon icon, Color color)
{
this.icon = icon;
this.color = color;
}
public void setDark(boolean dark)
{
this.dark = dark;
}
#Override
public int getIconWidth()
{
return icon.getIconWidth();
}
#Override
public int getIconHeight()
{
return icon.getIconHeight();
}
#Override
public void paintIcon(Component c, Graphics g, int x, int y)
{
icon.paintIcon(c, g, x, y);
if (dark)
{
g.setColor(color);
g.fillRect(x, y, getIconWidth(), getIconHeight());
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
Icon icon = new ImageIcon("mong.jpg");
DarkIcon darkIcon = new DarkIcon(icon, new Color(0, 0, 0, 128));
JLabel label = new JLabel( darkIcon );
Action blink = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e2)
{
darkIcon.setDark( false );
label.repaint();
}
};
Timer timer = new Timer(2000, blink);
timer.setRepeats( false );
JButton button = new JButton("Blink Icon");
button.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
darkIcon.setDark(true);
label.repaint();
timer.restart();
}
});
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(label);
f.add(button, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo( null );
f.setVisible(true);
}
}
I'm Trying to choose a color from the JColorChooser via the MouseEventClicked and then set the color chosen to the penColor but for some reason it's not working. I think i have a problem in the MouseClicked function.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
#SuppressWarnings("serial")
public class Paint3<penColor> extends JFrame implements MouseMotionListener, MouseListener, ChangeListener {
int size = 2;
private Point pt = new Point();
private JSlider penSize = new JSlider(JSlider.VERTICAL,1,10,3);
JColorChooser jc = new JColorChooser();
public Color penColor = new Color(0,0,0);
public JPanel DrawingPanel = new JPanel(){
public void paint(Graphics g){
g.fillOval((int) pt.getX(), (int)pt.getY(), 5,5);
}
};
public Paint3(){
super("My Painter");
Label l1 = new Label("Drag Mouse To Draw");
JPanel jp2 = new JPanel();
this.add((DrawingPanel), BorderLayout.NORTH);
DrawingPanel.add((l1),BorderLayout.NORTH);
this.add((jp2),BorderLayout.SOUTH);
jp2.add(jc);
this.addMouseMotionListener(this);
this.addMouseListener(this);
this.add(penSize, BorderLayout.EAST);
penSize.addChangeListener((ChangeListener) this);
penSize.setMinorTickSpacing(1);
penSize.setPaintTicks(true);
setSize(700,700);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
#Override
public void mouseDragged(MouseEvent me){
Graphics2D g = (Graphics2D)getGraphics();
g.setStroke(new BasicStroke(size));
g.setColor(penColor);
g.drawLine(pt.x,pt.y, me.getX(), me.getY());
pt = me.getPoint();
}
#Override
public void mouseMoved(MouseEvent me){
pt = me.getPoint();
}
#Override
public void mouseClicked(MouseEvent me){
if(me.getModifiers()== MouseEvent.BUTTON3_MASK){
//penColor = jc; //(this, "Change Pen Color" , penColor);
//penColor = jc.getColor();
penColor = jc.getColor();
}
}
#Override
public void mouseEntered(MouseEvent me){}
#Override
public void mouseExited(MouseEvent me){}
#Override
public void mousePressed(MouseEvent me){}
#Override
public void mouseReleased(MouseEvent me){}
#Override
public void stateChanged(ChangeEvent me){
JSlider source = (JSlider)me.getSource();
if(!source.getValueIsAdjusting()){
size = (int)source.getValue();
}
}
public static void main(String[] args){
new Paint3();
}
}
Well, just try this code:
#Override
public void mousePressed(MouseEvent me){
penColor = jc.getColor();
}
You will modify the color in the mousePressed and not in the mouseClicked
I hope it will help you, best regards
This is not the way to do it. A MouseListener doesn't work on a javax.swing.JColorChooser the way you expect it to. Alteast not as the way you have mentioned in your post.
You need to import javax.swing.colorchooser.ColorSelectionModel and add a javax.swing.ChangeListener to it.
JColorChooser jc = new JColorChooser();
ColorSelectionModel model = jc.getSelectionModel();
model.addChangeListener(
#Override
public void stateChanged(ChangeEvent event) {
penColor = jc.getColor();
}
);
So I want to set my Rectangle's color to whatever the JColorChooser picks, but unfortunately, I don't think that it recognises it as it just stays black, unless I assign it a real color like Color.BLUE.
This is the rectangle which should get the color from the other class:
TestProjectJPanel jpp = new TestProjectJPanel();
public void paintComponent(Graphics g){
super.paintComponent(g);
Rectangle r = new Rectangle(500,300,250,400);
g.setColor(jpp.bodyColour);
g.fillRect((int)r.getX(),(int)r.getY(),(int)r.getHeight(),(int)r.getWidth());
g.setColor(Color.BLUE);
g.drawString("banana", 50, 60);
}
and this is the class which has the color itself
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestProjectJPanel extends JFrame {
public JButton b;
public JButton u;
public JButton l;
public JButton r;
public String s;
public Color color = (Color.WHITE);
public JPanel panel;
public Color bodyColour;
public Color doorColour;
public Color wheelColour;
public TestProjectJPanel(){
JFrame f = new JFrame();
panel = new JPanel();
panel.setBackground(color);
// bodyColour button
b = new JButton("Body Colour");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
bodyColour = JColorChooser.showDialog(null, "Pick the colour", bodyColour);
if (bodyColour == null)
bodyColour = Color.RED;
}
});
u = new JButton("Wheel Colour");
u.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
wheelColour = JColorChooser.showDialog(null, "Pick the colour", wheelColour);
if (wheelColour == null)
wheelColour = (Color.BLACK);
}
});
l = new JButton("Door Colour");
l.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
doorColour = JColorChooser.showDialog(null, "Pick the colour", doorColour);
if(doorColour==null)
doorColour = (Color.RED);
}
});
r = new JButton("Change Name");
r.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
s = JOptionPane.showInputDialog("What name do you want to change it to?");
}
});
}
}
This is the whole code, which the Rectangle is included in.
import javax.swing.*;
import java.util.*;
import java.awt.*;
public class TestProjectDialog extends JPanel {
TestProjectJPanel jpp = new TestProjectJPanel();
public void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle r = new Rectangle(500, 300, 250, 400);
g.setColor(jpp.bodyColour);
g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getHeight(), (int) r.getWidth());
g.setColor(Color.BLUE);
g.drawString("banana", 50, 60);
}
public static void main(String[] args){
TestProjectJPanel jpp = new TestProjectJPanel();
/* JOptionPane.showMessageDialog(null, "Just about to draw a REALLY GOOD 2D car \n just need input please.");
jpp.s = JOptionPane.showInputDialog("Imagine a car, what is it's name?");
if(jpp.s == null || (jpp.s != null && ("".equals(jpp.s))))
{
JOptionPane.showMessageDialog(null, "Invalid input/pressed cancel, closing program.");
System.exit(0);
}
JOptionPane.showMessageDialog(null, "Ah okay, so it's name is " + jpp.s); */
JFrame f = new JFrame("My 2D Car Drawing");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jpp.setBackground(Color.WHITE);
f.setSize(1440,900);
f.add(new TestProjectDialog(), BorderLayout.CENTER);
f.add(jpp.b, SpringLayout.SOUTH); // bodyColour
// f.add(jpp.u, SpringLayout. NORTH); // wheelColour
// f.add(jpp.l, SpringLayout.WEST); // doorColour
// f.add(jpp.r, SpringLayout.EAST); // changeName
f.setVisible(true);
}
}
Could anyone help me and give me a solution for why it's not recognising the color?
Without a runnable example that demonstrates your problem, it is impossible to 100% sure, but from the sounds of it, you have created two more instances of TestProjectJPanel and/or paint panel, so what you think you're drawing to isn't actually on the screen.
However, it also sounds like you're not adhering to basic OO design, ensuring that the object is self managed, but instead, allowing the object to ascertain it's state from the properties of another object.
Instead, your paint/rectangle pane should be self contained, that is, all the properties it needs should be managed by it (this could also include a model, but that's going beyond the problem at hand).
For example, the ControlPane manages the interactions between the user (choosing a color) and the setting of that color on the PaintPane, which deals only with painting the results...
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class ColorTest {
public static void main(String[] args) {
new ColorTest();
}
public ColorTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
PaintPane paintPane = new PaintPane();
ControlPane controlPane = new ControlPane(paintPane);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(paintPane);
frame.add(controlPane, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ControlPane extends JPanel {
public ControlPane(PaintPane paintPane) {
JButton colorButton = new JButton("Color");
add(colorButton);
colorButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Color color = JColorChooser.showDialog(ControlPane.this, "Background", paintPane.getFillColor());
if (color != null)
paintPane.setFillColor(color);
}
});
}
}
public class PaintPane extends JPanel {
private Color fillColor = Color.RED;
public PaintPane() {}
public Color getFillColor() {
return fillColor;
}
public void setFillColor(Color fillColor) {
this.fillColor = fillColor;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(fillColor);
g2d.fillRect(50, 50, 100, 100);
g2d.dispose();
}
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Main {
public static void main(String[]args){
#SuppressWarnings("unused")
Gui g = new Gui();
}
}
#SuppressWarnings("serial")
class Gui extends JFrame{
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
double width = screen.getWidth();
double height = screen.getHeight();
JPanel canvas = new JPanel();
Point mloc = new Point();
JButton br = new JButton("Red");
JButton bb = new JButton("Blue");
JButton bg = new JButton("Green");
JButton wipe = new JButton("Wipe");
JLabel brushwidth = new JLabel("Width = ",JLabel.CENTER);
public JSlider s = new JSlider();
JButton image = new JButton("Image");
Point start = null;
Point current = null;
boolean entered = false;
Color c = Color.red;
public double bwidth = 3;
Gui(){
super("PaintPot");
setSize((int)width/4,(int)height/2);
setVisible(true);
setResizable(false);
setLayout(null);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(s);
s.setSize(getWidth()-20, 20);
s.setLocation(10, 450);
s.setBackground(Color.gray);
s.setForeground(Color.orange);
s.setMajorTickSpacing(50);
s.setMinorTickSpacing(1);
s.setValue((int)bwidth);
s.addChangeListener(new ChangeListener(){
#Override
public void stateChanged(ChangeEvent e) {
bwidth = s.getValue();
brushwidth.setText("Width = "+s.getValue());
}
});
brushwidth.setText("Width = "+s.getValue());
add(brushwidth);
brushwidth.setSize(70,30);
brushwidth.setLocation(90,410);
brushwidth.setBackground(Color.gray);
brushwidth.setForeground(Color.orange);
brushwidth.setOpaque(true);
brushwidth.setVisible(true);
add(wipe);
wipe.setSize(70,30);
wipe.setLocation(10, 410);
wipe.setBackground(Color.gray);
wipe.setForeground(Color.orange);
wipe.setVisible(true);
add(br);
br.setSize(60,30);
br.setLocation(10, 10);
br.setBackground(Color.red);
br.setForeground(Color.white);
br.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
c = Color.red;
}
});
br.setVisible(true);
add(bb);
bb.setSize(60,30);
bb.setLocation(80, 10);
bb.setBackground(Color.blue);
bb.setForeground(Color.white);
bb.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
c = Color.blue;
}
});
bb.setVisible(true);
add(bg);
bg.setSize(70,30);
bg.setLocation(150, 10);
bg.setBackground(Color.green);
bg.setForeground(Color.white);
bg.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
c = Color.green;
}
});
bg.setVisible(true);
add(image);
image.setSize(70,30);
image.setLocation(230, 10);
image.setBackground(Color.gray);
image.setForeground(Color.orange);
wipe.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
}
});
image.setVisible(true);
canvas(this,canvas);
}
public void canvas(JFrame f, JPanel p){
p.setSize(425,350);
p.setBorder(BorderFactory.createLineBorder(Color.black, 3));
p.setLocation(10, 50);
p.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent arg0) {}
#Override
public void mouseEntered(MouseEvent arg0) {entered = true;}
#Override
public void mouseExited(MouseEvent arg0) {entered = false;}
#Override
public void mousePressed(MouseEvent arg0) {}
#Override
public void mouseReleased(MouseEvent arg0) {}
});
p.addMouseMotionListener(new MouseAdapter(){
public void mouseDragged(MouseEvent e){
mloc = e.getLocationOnScreen();
if(entered = true){
paintComponent(getGraphics());
}
}
});
f.add(p);
}
public void paintComponent(Graphics g){
g.drawOval(mloc.x, mloc.y, (int)bwidth, (int)bwidth);
}
}
I'm trying to get this app to paint inside the JPanel but I can't seem to get it to work,
I want it to draw a line whenever I move my mouse. It's just the public void paint bit I can't get to grips with nothing seem to work.
Thanks
JFrame does not have a paintComponent() method.
Custom painting is done by overriding the paintComponent() method of a JPanel (or JComponent) and then you add the panel to the JFrame.
Read the section from the Swing tutorial on Custom Painting for more information and examples. You will also need to override the getPreferredSize() method.
Also, don't use a null layout. Swing was designed to be used with layout managers.
This if(entered = true){ is an assigment operator not a conditional. Instead you want if(entered == true){
paintComponent is meant to be overriden and not called explicitly. Don't explicitly call paintComponent when what you mean to do is call repaint()
JFrame has no paintComponent method, so you aren't actually overriding any paint functionality. For JFrame you should override paint, though I'd advise against it, and paint with JPanel or JComponent
In a paintComponent or paint method you should also be calling super.paintComponent or super.paint, respectively, as to not break the paint chain.