I am writing a program where I need to do different actions for a separate class depending on which button is clicked.
public class NewJFrame{
public static JButton b1;
public static JButton b2;
public static JButton b3;
}
public class Slot{
int value;
JButton button;
Slot(int value, JButton button)
{
this.value=value;
this.button=button;
}
}
public class Game{
Slot[] slots=new Slot[3];
Game(){
slots[0]=new Slot(1,NewJFrame.b1);
slots[1]=new Slot(2,NewJFrame.b2);
slots[2]=new Slot(3,NewJFrame.b3);
}
public void actionPerformed(ActionEvent e) {
for(int i=0;i<3;i++){
if(e.getSource()==slots[i].button)
slots[i].button.setText(String.valueOf(value));
}
}
}
Something like this. Note that, I'm completely novice at GUI designing.
Use Action to encapsulate functionality for use elsewhere in your program, e.g. buttons, menus and toolbars. The BeaconPanel shown below exports several actions that make it easy to use them in a control panel. To limit the proliferation of instances, the actions themselves can be class members. As an exercise, change controls to a JToolBar or add the same actions to a menu.
JPanel controls = new JPanel();
controls.add(new JButton(beaconPanel.getFlashAction()));
controls.add(new JButton(beaconPanel.getOnAction()));
controls.add(new JButton(beaconPanel.getOffAction()));
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Timer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** #see http://stackoverflow.com/a/37063037/230513 */
public class Beacon {
private static class BeaconPanel extends JPanel {
private static final int N = 16;
private final Ellipse2D.Double ball = new Ellipse2D.Double();
private final Timer timer;
private final Color on;
private final Color off;
private final AbstractAction flashAction = new AbstractAction("Flash") {
#Override
public void actionPerformed(ActionEvent e) {
timer.restart();
}
};
private final AbstractAction onAction = new AbstractAction("On") {
#Override
public void actionPerformed(ActionEvent e) {
stop(on);
}
};
private final AbstractAction offAction = new AbstractAction("Off") {
#Override
public void actionPerformed(ActionEvent e) {
stop(off);
}
};
private Color currentColor;
public BeaconPanel(Color on, Color off) {
this.on = on;
this.off = off;
this.currentColor = on;
timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
changeColors();
}
});
}
public void start() {
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int x = getX() + N;
int y = getY() + N;
int w = getWidth() - 2 * N;
int h = getHeight() - 2 * N;
ball.setFrame(x, y, w, h);
g2.setColor(currentColor);
g2.fill(ball);
g2.setColor(Color.black);
g2.draw(ball);
}
private void changeColors() {
currentColor = currentColor == on ? off : on;
repaint();
}
private void stop(Color color) {
timer.stop();
currentColor = color;
repaint();
}
public Action getFlashAction() {
return flashAction;
}
public Action getOnAction() {
return onAction;
}
public Action getOffAction() {
return offAction;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(N * N, N * N);
}
}
public static void display() {
JFrame f = new JFrame("Beacon");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final BeaconPanel beaconPanel = new BeaconPanel(Color.orange, Color.orange.darker());
f.add(beaconPanel);
JPanel controls = new JPanel();
controls.add(new JButton(beaconPanel.getFlashAction()));
controls.add(new JButton(beaconPanel.getOnAction()));
controls.add(new JButton(beaconPanel.getOffAction()));
f.add(controls, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
beaconPanel.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Beacon.display();
}
});
}
}
Related
I've set a png image as jLabel Icon on a jFrame but I want to color some part of the picture.
What can I do?
Code Snippet (jLabel on a jFrame):
private javax.swing.JLabel jLabel2;
jLabel2 = new javax.swing.JLabel();
jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/planimavo/planimetrie/Planimetria AVO piano terra 2017-1.png"))); // NOI18N
jLabel2.setText("jLabel2");
jLabel2.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jLabel2MouseClicked(evt);
}
});
You need a special icon implementation. Here is an example, how to paint square at the mouse click point. (Left click - paint white rectangle at the mouse click point, right click - stop paint white rectangle).
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
/**
* <code>OverlayIconExample</code>.
*/
public class OverlayIconExample {
private static final int OVERPAINT_RECT_SIZE = 100;
private final Icon icon = new ImageIcon("C:\\Users\\Public\\Pictures\\Sample Pictures\\Koala.jpg");
private final OverpaintIcon overIcon = new OverpaintIcon(icon);
public static void main(String[] args) {
SwingUtilities.invokeLater(new OverlayIconExample()::startUp);
}
private void startUp() {
JFrame frm = new JFrame("Icon overpaint");
JLabel label = new JLabel(overIcon);
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
overIcon.setPoint(e.getPoint());
} else {
overIcon.setPoint(null);
}
label.repaint();
}
});
frm.add(label);
frm.pack();
frm.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
private static class OverpaintIcon implements Icon {
private final Icon backgroundIcon;
private Point point;
/**
* #param backgroundIcon
*/
public OverpaintIcon(Icon backgroundIcon) {
this.backgroundIcon = backgroundIcon;
}
#Override
public void paintIcon(Component c, Graphics g, int x, int y) {
backgroundIcon.paintIcon(c, g, x, y);
g.setColor(Color.WHITE);
if (point != null) {
g.fillRect(point.x, point.y, OVERPAINT_RECT_SIZE, OVERPAINT_RECT_SIZE);
}
}
#Override
public int getIconWidth() {
return backgroundIcon.getIconWidth();
}
#Override
public int getIconHeight() {
return backgroundIcon.getIconHeight();
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
}
}
I have a Jframe with two buttons: 'A' and 'B'. Clicking the button 'A' should display the capital letter A in the JPanel. On mouse hover only, any 'A' letter within the canvas should be displayed in red. When the mouse leaves, the text color should be back to black.
I've coded for this and it works only once. The letter 'A' changes to red but does not change back to black. Also, it does not work for multiple 'A's
Code for JFrame:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawFrame extends JFrame{
private final int WIDTH = 500;
private final int HEIGHT = 300;
private GUIModel model;
private JButton number1;
private JButton number2;
private JPanel numberPanel;
private DrawPanel graphicsPanel;
public DrawFrame()
{
this.model = new GUIModel(" ");
createSelectionPanel();
createGraphicsPanel();
this.setSize(WIDTH, HEIGHT);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
private void createSelectionPanel()
{
numberPanel = new JPanel();
ButtonListener listener = new ButtonListener();
number1 = new JButton("A");
number1.addActionListener(listener);
number2 = new JButton("B");
number2.addActionListener(listener);
numberPanel.setLayout(new GridLayout(2,2));
numberPanel.add(number1);
numberPanel.add(number2);
this.add(numberPanel, BorderLayout.WEST);
}
private void createGraphicsPanel()
{
//instantiate drawing panel
graphicsPanel = new DrawPanel(WIDTH, HEIGHT, model);
//add drawing panel to right
add(graphicsPanel);
}
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
model.setDisplayString(event.getActionCommand());
}
}
//creates a drawing frame
public static void main(String[] args)
{
DrawFrame draw = new DrawFrame();
}
}
Code for JPanel:
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
public class DrawPanel extends JPanel{
private static final long serialVersionUID = 3443814601865936618L;
private Font font = new Font("Default", Font.BOLD, 30);
private static final Color DEFAULT_TEXT_COLOR = Color.BLACK;
private static final Color HOVER_TEXT_COLOR = Color.RED;
private Color color = DEFAULT_TEXT_COLOR;
private List<GUIModel> numberList = new ArrayList<GUIModel>();
private GUIModel model;
boolean mouseHover = false;
public DrawPanel(int width, int height, GUIModel model){
this.setPreferredSize(new Dimension(width, height));
this.model = model;
//set white background for drawing panel
setBackground(Color.WHITE);
//add mouse listeners
MouseHandler mouseHandler = new MouseHandler();
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
void checkForHover(MouseEvent event) {
FontMetrics metrics = getFontMetrics(font);
Graphics g = getGraphics();
Rectangle textBounds = metrics.getStringBounds("A", g).getBounds();
g.dispose();
int index = 0;
while (index < numberList.size()) {
Double x = numberList.get(index).getCoordinate().getX();
Double y = numberList.get(index).getCoordinate().getY();
textBounds.translate(x.intValue(), y.intValue());
if (textBounds.contains(event.getPoint())) {
color = HOVER_TEXT_COLOR;
}
else {
color = DEFAULT_TEXT_COLOR;
}
index++;
}
repaint(textBounds);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setFont(font);
g.setColor(color);
int index = 0;
while (index < numberList.size()) {
Double x = numberList.get(index).getCoordinate().getX();
Double y = numberList.get(index).getCoordinate().getY();
String display = numberList.get(index).getDisplayString();
g.drawString(display, x.intValue(), y.intValue());
index++;
}
if (model.getCoordinate() != null) {
Point p = model.getCoordinate();
g.drawString(model.getDisplayString(), p.x, p.y);
GUIModel number = new GUIModel();
number.setCoordinate(p);
number.setDisplayString(model.getDisplayString());
numberList.add(number);
}
}
//class to handle all mouse events
private class MouseHandler extends MouseAdapter implements MouseMotionListener
{
#Override
public void mousePressed(MouseEvent event)
{
model.setCoordinate(event.getPoint());
}
#Override
public void mouseReleased(MouseEvent event)
{
DrawPanel.this.repaint();
}
#Override
public void mouseEntered(MouseEvent event) {
checkForHover(event);
}
#Override
public void mouseMoved(MouseEvent event) {
checkForHover(event);
}
}
}
Code for GUIModel:
import java.awt.Point;
public class GUIModel {
private String displayString;
private Point coordinate;
public GUIModel() {}
public GUIModel(String displayString) {
this.displayString = displayString;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
public String getDisplayString() {
return displayString;
}
public Point getCoordinate() {
return coordinate;
}
public void setCoordinate(int x, int y) {
this.coordinate = new Point(x, y);
}
public void setCoordinate(Point coordinate) {
this.coordinate = coordinate;
}
}
Any help would be much appreciated. Thanks!
There's several misconceptions.
Graphics#drawString doesn't paint the text at the x/y position, so that the x/y is the top left corner of the String, but instead, the x/y position is the baseline of the font, this means that much of the text is draw above the y position, see Font Concepts for more details. This means that when you try and calculate the the Rectangle of the text, it's actually lower then where you painting it. Instead, you need to use y + ascent to get the text to position properly.
paintComponent can be called at any time for any number of reasons, many of which you don't control. To this end, paintComponent should only be used to paint the current state of the component and should never update or modify the state of the component. So adding a new GUIModel within the method is the wrong thing to do, instead, it should be added in the mouseClicked event of the MouseListener.
You're relying to much on the GUIModel variables. You should create a model only when you actually need it
Conceptually, this example address most of the issues mentioned above
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawFrame extends JFrame {
private final int WIDTH = 500;
private final int HEIGHT = 300;
// private GUIModel model;
private JButton number1;
private JButton number2;
private JPanel numberPanel;
private DrawPanel graphicsPanel;
public DrawFrame() {
// this.model = new GUIModel(" ");
createSelectionPanel();
createGraphicsPanel();
this.setSize(WIDTH, HEIGHT);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
private void createSelectionPanel() {
numberPanel = new JPanel();
ButtonListener listener = new ButtonListener();
number1 = new JButton("A");
number1.addActionListener(listener);
number2 = new JButton("B");
number2.addActionListener(listener);
numberPanel.setLayout(new GridLayout(2, 2));
numberPanel.add(number1);
numberPanel.add(number2);
this.add(numberPanel, BorderLayout.WEST);
}
private void createGraphicsPanel() {
//instantiate drawing panel
graphicsPanel = new DrawPanel(WIDTH, HEIGHT);
//add drawing panel to right
add(graphicsPanel);
}
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
graphicsPanel.setDisplayString(event.getActionCommand());
}
}
//creates a drawing frame
public static void main(String[] args) {
DrawFrame draw = new DrawFrame();
}
public static class DrawPanel extends JPanel {
private static final long serialVersionUID = 3443814601865936618L;
private Font font = new Font("Default", Font.BOLD, 30);
private static final Color DEFAULT_TEXT_COLOR = Color.BLACK;
private static final Color HOVER_TEXT_COLOR = Color.RED;
private Color color = DEFAULT_TEXT_COLOR;
private List<GUIModel> numberList = new ArrayList<GUIModel>();
boolean mouseHover = false;
private String displayString;
private GUIModel hoverModel;
public DrawPanel(int width, int height) {
this.setPreferredSize(new Dimension(width, height));
//set white background for drawing panel
setBackground(Color.WHITE);
//add mouse listeners
MouseHandler mouseHandler = new MouseHandler();
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
protected Rectangle getBounds(GUIModel model) {
FontMetrics metrics = getFontMetrics(font);
Double x = model.getCoordinate().getX();
Double y = model.getCoordinate().getY();
Rectangle textBounds = new Rectangle(
x.intValue(),
y.intValue(),
metrics.stringWidth(model.getDisplayString()),
metrics.getHeight());
return textBounds;
}
void checkForHover(MouseEvent event) {
Rectangle textBounds = null;
if (hoverModel != null) {
textBounds = getBounds(hoverModel);
}
hoverModel = null;
if (textBounds != null) {
repaint(textBounds);
}
for (GUIModel model : numberList) {
textBounds = getBounds(model);
if (textBounds.contains(event.getPoint())) {
hoverModel = model;
repaint(textBounds);
break;
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
g.setColor(DEFAULT_TEXT_COLOR);
FontMetrics fm = g.getFontMetrics();
for (GUIModel model : numberList) {
if (model != hoverModel) {
Double x = model.getCoordinate().getX();
Double y = model.getCoordinate().getY();
String display = model.getDisplayString();
g.drawString(display, x.intValue(), y.intValue() + fm.getAscent());
}
}
if (hoverModel != null) {
g.setColor(HOVER_TEXT_COLOR);
Double x = hoverModel.getCoordinate().getX();
Double y = hoverModel.getCoordinate().getY();
String display = hoverModel.getDisplayString();
g.drawString(display, x.intValue(), y.intValue() + fm.getAscent());
}
// if (model.getCoordinate() != null) {
// Point p = model.getCoordinate();
// g.drawString(model.getDisplayString(), p.x, p.y);
//// GUIModel number = new GUIModel();
//// number.setCoordinate(p);
//// number.setDisplayString(model.getDisplayString());
//// numberList.add(number);
// }
}
public void setDisplayString(String text) {
displayString = text;
}
//class to handle all mouse events
private class MouseHandler extends MouseAdapter implements MouseMotionListener {
#Override
public void mouseClicked(MouseEvent e) {
GUIModel model = new GUIModel(displayString);
model.setCoordinate(e.getPoint());
numberList.add(model);
repaint();
}
#Override
public void mouseMoved(MouseEvent event) {
checkForHover(event);
}
}
}
public static class GUIModel {
private String displayString;
private Point coordinate;
public GUIModel() {
}
public GUIModel(String displayString) {
this.displayString = displayString;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
public String getDisplayString() {
return displayString;
}
public Point getCoordinate() {
return coordinate;
}
public void setCoordinate(int x, int y) {
this.coordinate = new Point(x, y);
}
public void setCoordinate(Point coordinate) {
this.coordinate = coordinate;
}
}
}
I'm making a dice rolling program in java using swing. I've got 4 classes:
Die
public class Die{
private int faceValue;
public Die(){
System.out.println("Creating new Dice Object");
setValue(roll());
}
public int roll() {
int val = (int) (6 * Math.random() + 1);
setValue(val);
return val;
}
public int getValue() {
return faceValue;
}
public void setValue(int spots) {
faceValue = spots;
}
}
DieFace
public class DieFace {
private int spotDiam,wOffset,hOffset,w,h;
public int faceValue;
public DieFace(){
Die die = new Die();
this.faceValue = die.getValue();
}
public void draw(Graphics g, int paneWidth, int paneHeight){
//draw information
}
}
DieFaceComponent
public class DieFaceComponent extends JComponent{
private static final long serialVersionUID = 1L;
DieFace face;
public DieFaceComponent(){
face = new DieFace();
System.out.println("DIEFACE" + face.faceValue);
repaint();
}
public void paintComponent(Graphics g){
revalidate();
face.draw(g,super.getWidth(),super.getHeight());
}
}
DieFaceViewer
public class DieFaceViewer{
static DieFaceComponent component;
static JFrame frame = new JFrame(); // Create a new JFrame object
public static void main(String[] args){
final int FRAME_WIDTH = 500;
final int FRAME_HEIGHT = 500;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); // Set initial size
frame.setTitle("Dice Simulator Version 1.0"); // Set title
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Set default close operation
component = new DieFaceComponent(); // Create a new DieFaceComponent object
frame.setLayout(new BorderLayout());
JButton btnRoll = new JButton("Roll!");
btnRoll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
component = new DieFaceComponent();
}
});
frame.add(component, BorderLayout.CENTER); // Add DieFaceComponent object to frame
frame.add(btnRoll, BorderLayout.SOUTH);
frame.setVisible(true); // Set frame to visible
}
}
My problem is that even though a new Die, DieFace and DieFaceComponent object is created every time I press my btnRoll, the value used to draw the component stays the same as the initial instance. Is there something I've done wrong? Thanks in advance
You create a new instance of DieFaceComponent in your ActionListener but do nothing with it, it's never added to anything, so it's never visible. A better solution would allow you to trigger a change to DieFaceComponent, which triggered a change to DieFace which triggered a change to Die and have the whole thing just repaint itself, for example...
public class Die {
private int faceValue;
public Die() {
System.out.println("Creating new Dice Object");
//setValue(roll());
roll(); // Roll sets the value any way :P
}
public int roll() {
int val = (int) (6 * Math.random() + 1);
setValue(val);
return val;
}
public int getValue() {
return faceValue;
}
public void setValue(int spots) {
faceValue = spots;
}
}
public class DieFace {
private int spotDiam, wOffset, hOffset, w, h;
//public int faceValue;
private Die die;
public DieFace() {
die = new Die();
//Die die = new Die();
// This is pointless, as you should simply as die for it's value
// when ever you need it...
//this.faceValue = die.getValue();
}
public void roll() {
die.roll();
}
public void draw(Graphics g, int paneWidth, int paneHeight) {
//draw information
}
}
public class DieFaceComponent extends JComponent {
private static final long serialVersionUID = 1L;
DieFace face;
public DieFaceComponent() {
face = new DieFace();
//System.out.println("DIEFACE" + face.faceValue);
// Pointless, as you've probably not actually been added to anything
// that could actuallyt paint you anyway...
//repaint();
}
public void roll() {
face.roll();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//revalidate();
face.draw(g, super.getWidth(), super.getHeight());
}
}
Now, you can call roll on DieFaceComponent, which will call roll on DieFace which will call roll on Die, which will update the actual value. DieFaceComponent will then schedule a repaint to ensure that it's update on the screen.
And then you could use it something like...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DiceRoller {
public static void main(String[] args) {
new DiceRoller();
}
public DiceRoller() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DiePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DiePane extends JPanel {
public DiePane() {
setLayout(new BorderLayout());
DieFaceComponent component = new DieFaceComponent();
JButton roll = new JButton("Roll");
roll.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
component.roll();
}
});
add(component);
add(roll, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Now, a better solution would be to have Die as your primary entry point, allowing it to generate notifications to interested parties and having them update themselves
Maybe something like...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DiceRoller {
public static void main(String[] args) {
new DiceRoller();
}
public DiceRoller() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DiePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DiePane extends JPanel {
public DiePane() {
setLayout(new BorderLayout());
Die die = new Die();
DieFaceComponent component = new DieFaceComponent(die);
JButton roll = new JButton("Roll");
roll.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
die.roll();
}
});
add(component);
add(roll, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class Die {
private PropertyChangeSupport propertyChangeSupport;
private int faceValue;
public Die() {
propertyChangeSupport = new PropertyChangeSupport(this);
System.out.println("Creating new Dice Object");
//setValue(roll());
roll(); // Roll sets the value any way :P
}
public int roll() {
int val = (int) (6 * Math.random() + 1);
setValue(val);
return val;
}
public int getValue() {
return faceValue;
}
public void setValue(int spots) {
int old = faceValue;
faceValue = spots;
propertyChangeSupport.firePropertyChange("value", old, faceValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
}
public class DieFace {
private int spotDiam, wOffset, hOffset, w, h;
private Die die;
public DieFace(Die die) {
this.die = die
}
public void draw(Graphics g, int paneWidth, int paneHeight) {
//draw information
}
}
public class DieFaceComponent extends JComponent {
private static final long serialVersionUID = 1L;
private DieFace face;
public DieFaceComponent(Die die) {
face = new DieFace(die);
die.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//revalidate();
face.draw(g, super.getWidth(), super.getHeight());
}
}
}
This is a simple example of an Observer Pattern, where the Die is the generator of information, to which every body else is interested in knowing when it changes. It's also a variant of the model-view-controller paradigm
I have just written a program in Netbeans that moves/copies/deletes files, and I wanted to give it a "diagnostic mode" where information about selected files, folders, variables, etc is displayed in a Text Area. Now, I could set this to only be visible when the "diagnostic mode" toggle is selected, but I think it would look awesome if the text area started behind the program, and "slid" out from behind the JFrame when the button is toggled. Is there any way to do this?
Thanks!
-Sean
Here is some starter code for you. This will right-slide a panel
of just about any content type. Tweak as necessary. Add error
checking and exception handling.
Tester:
static public void main(final String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
final JPanel slider = new JPanel();
slider.setLayout(new FlowLayout());
slider.setBackground(Color.RED);
slider.add(new JButton("test"));
slider.add(new JButton("test"));
slider.add(new JTree());
slider.add(new JButton("test"));
slider.add(new JButton("test"));
final CpfJFrame42 cpfJFrame42 = new CpfJFrame42(slider, 250, 250);
cpfJFrame42.slide(CpfJFrame42.CLOSE);
cpfJFrame42.setSize(300, 300);
cpfJFrame42.setLocationRelativeTo(null);
cpfJFrame42.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
cpfJFrame42.setVisible(true);
}
});
}
Use GAP & MIN to adjust spacing from JFrame and closed size.
The impl is a little long...it uses a fixed slide speed but
that's one the tweaks you can make ( fixed FPS is better ).
package com.java42.example.code;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
public class CpfJFrame42 extends JFrame {
public static int GAP = 5;
public static int MIN = 1;
public static final int OPEN = 0x01;
public static final int CLOSE = 0x02;
private JDialog jWindow = null;
private final JPanel basePanel;
private final int w;
private final int h;
private final Object lock = new Object();
private final boolean useSlideButton = true;
private boolean isSlideInProgress = false;
private final JPanel glassPane;
{
glassPane = new JPanel();
glassPane.setOpaque(false);
glassPane.addMouseListener(new MouseAdapter() {
});
glassPane.addMouseMotionListener(new MouseMotionAdapter() {
});
glassPane.addKeyListener(new KeyAdapter() {
});
}
public CpfJFrame42(final Component component, final int w, final int h) {
this.w = w;
this.h = h;
component.setSize(w, h);
addComponentListener(new ComponentListener() {
#Override
public void componentShown(final ComponentEvent e) {
}
#Override
public void componentResized(final ComponentEvent e) {
locateSlider(jWindow);
}
#Override
public void componentMoved(final ComponentEvent e) {
locateSlider(jWindow);
}
#Override
public void componentHidden(final ComponentEvent e) {
}
});
jWindow = new JDialog(this) {
#Override
public void doLayout() {
if (isSlideInProgress) {
}
else {
super.doLayout();
}
}
};
jWindow.setModal(false);
jWindow.setUndecorated(true);
jWindow.setSize(component.getWidth(), component.getHeight());
jWindow.getContentPane().add(component);
locateSlider(jWindow);
jWindow.setVisible(true);
if (useSlideButton) {
basePanel = new JPanel();
basePanel.setLayout(new BorderLayout());
final JPanel statusPanel = new JPanel();
basePanel.add(statusPanel, BorderLayout.SOUTH);
statusPanel.add(new JButton("Open") {
private static final long serialVersionUID = 9204819004142223529L;
{
setMargin(new Insets(0, 0, 0, 0));
}
{
addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
slide(OPEN);
}
});
}
});
statusPanel.add(new JButton("Close") {
{
setMargin(new Insets(0, 0, 0, 0));
}
private static final long serialVersionUID = 9204819004142223529L;
{
addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
slide(CLOSE);
}
});
}
});
{
//final BufferedImage bufferedImage = ImageFactory.getInstance().createTestImage(200, false);
//final ImageIcon icon = new ImageIcon(bufferedImage);
//basePanel.add(new JButton(icon), BorderLayout.CENTER);
}
getContentPane().add(basePanel);
}
}
private void locateSlider(final JDialog jWindow) {
if (jWindow != null) {
final int x = getLocation().x + getWidth() + GAP;
final int y = getLocation().y + 10;
jWindow.setLocation(x, y);
}
}
private void enableUserInput() {
getGlassPane().setVisible(false);
}
private void disableUserInput() {
setGlassPane(glassPane);
}
public void slide(final int slideType) {
if (!isSlideInProgress) {
isSlideInProgress = true;
final Thread t0 = new Thread(new Runnable() {
#Override
public void run() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
disableUserInput();
slide(true, slideType);
enableUserInput();
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
isSlideInProgress = false;
}
});
t0.setDaemon(true);
t0.start();
}
else {
Toolkit.getDefaultToolkit().beep();
}
}
private void slide(final boolean useLoop, final int slideType) {
synchronized (lock) {
for (int x = 0; x < w; x += 25) {
if (slideType == OPEN) {
jWindow.setSize(x, h);
}
else {
jWindow.setSize(getWidth() - x, h);
}
jWindow.repaint();
try {
Thread.sleep(42);
} catch (final Exception e) {
e.printStackTrace();
}
}
if (slideType == OPEN) {
jWindow.setSize(w, h);
}
else {
jWindow.setSize(MIN, h);
}
jWindow.repaint();
}
}
}
i made this code that when you start it it's suposed to show you an image and then change it between other two images when you press the left or right key, but for some reason it isn't reading the input from the keyboard, i tryed to use a mouseListener and it worked, this is the code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Implementary extends JFrame
{
private static final long serialVersionUID = 1L;
public Dimension d;
public static ImageIcon Im = new ImageIcon(Implementary.class.getResource("death.png"));
public static ImageIcon Imc = new ImageIcon(Implementary.class.getResource("right.png"));
public static ImageIcon I = new ImageIcon(Implementary.class.getResource("left.png"));
public static Image Img = Im.getImage();
public static int x = 10;
public static int y = 10;
public Implementary()
{
super("hue");
int x1 = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
int y1 = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
d = new Dimension(x1, y1 - 45);
this.setSize(d);
this.setLocationRelativeTo(null);
Panel p = new Panel();
p.addKeyListener(new KeyListener()
{
#Override
public void keyTyped(KeyEvent e)
{
keyPressed(e);
}
#Override
public void keyPressed(KeyEvent e)
{
int k = e.getKeyCode();
if (k == KeyEvent.VK_LEFT)
{
Img = I.getImage();
repaint();
System.out.println(3);
}
else
{
Img = Imc.getImage();
repaint();
System.out.println(2);
}
System.out.println(1);
}
#Override
public void keyReleased(KeyEvent e)
{
keyPressed(e);
}
});
this.add(p);
}
static class Panel extends JPanel
{
private static final long serialVersionUID = 1L;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.cyan);
g.drawImage(Img, x, y, null);
}
}
}
and this is the main class:
public class Yo
{
public static void main(String args[])
{
Implementary imp = new Implementary();
imp.setVisible(true);
}
}
Adding the KeyListener to the whole JFrame could do the trick.
As your JPanel cannot be selected/focused it doesn't receive keystrokes.
Changing
p.addKeyListener(new KeyListener()
to
this.addKeyListener(new KeyListener()
works for me.