I have created a checkers game interface using java and placed pieces in each position on the game board but at the moment I am having trouble moving the pieces from one square to another.
How to moving checkers pieces in board game?
Below is source code that I've tried:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package chackergame;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
/**
*
* #author wenda
*/
public class CheckerGame extends JFrame {
private final int ROWS = 8;
private final int COLL = 8;
private final JPanel[][] square = new JPanel[8][8];
private JPanel backgroundPanel;
private final JLabel statusBar = new JLabel(" Red turn to play");
private JLabel lbPieces = new JLabel();
private boolean inDrag = false;
public CheckerGame() {
//Add a chess board to the Layered Pane
backgroundPanel = new JPanel();
backgroundPanel.setLayout(new GridLayout(8, 8, 0, 0));
add(backgroundPanel, BorderLayout.CENTER);
add(statusBar, BorderLayout.SOUTH);
createSquare();
addPieces();
setIconImage(PiecesIcon.iconGame.getImage());
setTitle("Java Checkers");// set title game
setSize(500, 500);
//setResizable(false);
setLocationRelativeTo(null);
setLocationByPlatform(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void createSquare() {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLL; col++) {
JPanel cell = new JPanel();
if ((row + col) % 2 == 1) {
cell.setBackground(new Color(99, 164, 54));
// cell.setBackground(Color.BLACK);
}
if ((row + col) % 2 == 0) {
cell.setBackground(new Color(247, 235, 164));
// cell.setBackground(Color.WHITE);
}
square[row][col] = cell;
backgroundPanel.add(square[row][col]);
}
}
}
/**
* Add pieces to the board
*/
private void addPieces() {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLL; col++) {
lbPieces = new JLabel();
lbPieces.setHorizontalAlignment(SwingConstants.CENTER);
//lb.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
if ((row + col) % 2 == 1) {
if (row < 3) {
lbPieces.setIcon(PiecesIcon.redPiece);
} else if (row > 4) {
lbPieces.setIcon(PiecesIcon.whitePiece);
}
}
square[row][col].setLayout(new BorderLayout());
square[row][col].add(lbPieces, BorderLayout.CENTER);
} // end of for col loop
} // end of for row loop
} // end of addPieces method
public class MouseInput extends MouseAdapter {
#Override
public void mousePressed(MouseEvent evt) {
}
#Override
public void mouseReleased(MouseEvent evt) {
}
#Override
public void mouseClicked(MouseEvent evt) {
}
#Override
public void mouseDragged(MouseEvent evt) {
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new CheckerGame();
}
}
The basic question is about dragging a component (in this case a JLable) from any source container (a JPanel) to any other one.
Every such container can be a source of the dragged component or a drop-target for it. so it needs to support both. Such JPanel is implemented in the following DragDropPane class.
To write this code I borrowed from MadProgrammer's answer which shows a solution for one source and one target.
It is a one-file mre : the entire code can be copy-pasted to LabelDnD.java file, and run. It demonstrates dragging a JLabel from panel to panel. Please note the comments:
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class LabelDnD{
private static final int ROWS = 5, COLS = 5, GAP = 4;
private Component makeContent() {
JPanel content = new JPanel(new GridLayout(ROWS,COLS, GAP,GAP));
content.setBorder(BorderFactory.createLineBorder(content.getBackground(), GAP));
for(int i = 0; i < ROWS*COLS ; i++){
content.add(new DragDropPane(String.valueOf(i)));
}
return content;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame("Label Drag & Drop");
f.add(new LabelDnD().makeContent());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.pack();
f.setVisible(true);
});
}
}
class DragDropPane extends JPanel implements DragGestureListener, DragSourceListener {
private static final int W = 50, H = 50;
private JComponent dragable;
public DragDropPane(String text) {
setBackground(Color.white);
setPreferredSize(new Dimension(W, H));
setBorder(BorderFactory.createLineBorder(Color.blue, 1));
var label = new JLabel(text, JLabel.CENTER);
setContent(label);
new MyDropTargetListener(this);
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
this, DnDConstants.ACTION_COPY, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
public void setContent(JComponent component) {
removeAll();
dragable = component;
add(component);
repaint();
}
//-->DragGestureListener implementation
#Override
public void dragGestureRecognized(DragGestureEvent dge) {
// Create our transferable wrapper
Transferable transferable = new TransferableComponent(dragable);
// Start the "drag" process...
DragSource ds = dge.getDragSource();
ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
remove(dragable);
revalidate(); repaint();
}
//-->DragSourceListener implementation
#Override
public void dragEnter(DragSourceDragEvent dsde) {}
#Override
public void dragOver(DragSourceDragEvent dsde) {}
#Override
public void dropActionChanged(DragSourceDragEvent dsde) {}
#Override
public void dragExit(DragSourceEvent dse) {}
#Override
public void dragDropEnd(DragSourceDropEvent dsde) {
// If the drop was not successful, we need to
// return the component back to it's previous
// parent
if (!dsde.getDropSuccess()) {
setContent(dragable);
}
}
}
class MyDropTargetListener extends DropTargetAdapter {
private final DragDropPane target;
public MyDropTargetListener(DragDropPane target) {
this.target = target;
new DropTarget(target, DnDConstants.ACTION_COPY, this, true, null);
}
#Override
public void drop(DropTargetDropEvent event) {
try {
var tr = event.getTransferable();
var component = (JComponent) tr.getTransferData(TransferableComponent.component);
if (event.isDataFlavorSupported(TransferableComponent.component)) {
event.acceptDrop(DnDConstants.ACTION_COPY);
target.setContent(component);
event.dropComplete(true);
} else {
event.rejectDrop();
}
} catch (Exception e) {
e.printStackTrace();
event.rejectDrop();
}
}
}
class TransferableComponent implements Transferable {
protected static final DataFlavor component =
new DataFlavor(JComponent.class, "A Component");
protected static final DataFlavor[] supportedFlavors = {
component
};
private final JComponent componentToTransfer;
public TransferableComponent(JComponent componentToTransfer) {
this.componentToTransfer = componentToTransfer;
}
#Override
public DataFlavor[] getTransferDataFlavors() {
return supportedFlavors;
}
#Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(component);
}
#Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (flavor.equals(component)) return componentToTransfer;
else throw new UnsupportedFlavorException(flavor);
}
}
Related
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();
}
});
}
}
I'm writing a GUI for my neural network(https://github.com/banana01/Neural-Network If you need to see any other classes) to show a map of the network and I have a map organised by layers. I would like to be able to draw connections between the nodes on a transparent JPanel that is on top of the JPanel that has the layers and nodes in it.
I have read the following question but that requires the class be a JFrame, I would like to be able to do it in a JPanel so I can add it to a tab so I can have different tabs for different things such as the map, the input, setting etc.
placing a transparent JPanel on top of another JPanel not working
Here is my current class, lacking any sort of overlay layer.
public class NeuralNetworkDisplay extends JPanel //implements MouseListener
{
private Network ntk;
JPanel[] layerPanels;
JPanel[] layerSubPanels;
JButton[] nodeButtons;
JSplitPane splitPane;
JLayeredPane NNMap;
JPanel test;
ArrayList<Layer> layers = new ArrayList<Layer>();
ArrayList<Node[]> nodes = new ArrayList<Node[]>();
public NeuralNetworkDisplay(Network ntk)
{
setNtk(ntk);
parseNetworkDesign();
splitPane = new JSplitPane();
NNMap = new JLayeredPane();
test = new JPanel();
NNMap.setLayout(new GridLayout(3,1,5,5));
splitPane.setRightComponent(NNMap);
add(splitPane);
}
public void init()
{
drawLayers();
drawNodes();
}
public void parseNetworkDesign()
{
for (int i = 0;i < ntk.getLayers().size(); i++)
{
layers.add(ntk.getLayers().get(i));
}
for (int i = 0; i < layers.size(); i++)
{
nodes.add(layers.get(i).getNodes().toArray(new Node[layers.get(i).getNodes().size()]));
}
}
public Network getNtk() {
return ntk;
}
public void setNtk(Network ntk) {
this.ntk = ntk;
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
}
public ArrayList<Layer> getLayers() {
return layers;
}
public void setLayers(ArrayList<Layer> layers) {
this.layers = layers;
}
public ArrayList<Node[]> getNodes() {
return nodes;
}
public int getNodesSize() {
return nodes.size();
}
public int getLayersSize() {
return layers.size();
}
public void setNodes(ArrayList<Node[]> nodes) {
this.nodes = nodes;
}
public void drawLayers()
{
layerPanels = new JPanel[getLayersSize()];
layerSubPanels = new JPanel[getLayersSize()];
for (int i = 0; i < layerPanels.length; i++)
{
layerPanels[i] = new JPanel();
layerSubPanels[i] = new JPanel();
layerPanels[i].setLayout(new FlowLayout());
layerSubPanels[i].setLayout(new GridLayout(3,5,5,5));
layerPanels[i].add(new JLabel("Layer::"+i));
layerPanels[i].add(layerSubPanels[i]);
NNMap.add(layerPanels[i]);
}
}
public void drawNodes()
{
int nod = 0;
for (int i = 0; i < getNodes().size(); i++)
{
nod += getNodes().get(i).length;
}
nodeButtons = new JButton[nod];
for (int i = 0; i < getLayersSize(); i++)
{
for (int j = 0; j < getNodes().get(i).length; j++)
{
//nodeButtons[j]
layerSubPanels[i].add(MyFactory.createNODEButton(getNodes().get(i)[j]));
}
}
}
}
This is a JPanel that is added to the main window in a split pane. That is all done in a different class.
Here is the Map Panel:
What would I use to create a transparent JPanel on top of the JPanel that contains the map. So I could draw connections between the nodes.
There's probably a few ways you could do this, but one way might be to create a custom JLayeredPane, which can maintain and paint the relationships between the components, for example...
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GroupPane parent = new GroupPane("Parent", Color.RED);
GroupPane child1 = new GroupPane("Child 1", Color.BLUE);
GroupPane child2 = new GroupPane("Child 2", Color.CYAN);
parent.setBounds(10, 10, 100, 100);
child1.setBounds(10, 150, 100, 100);
child2.setBounds(150, 150, 100, 100);
ConnectionPane connectionPane = new ConnectionPane();
connectionPane.add(parent, child1);
connectionPane.add(parent, child2);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(connectionPane);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GroupPane extends JPanel {
public GroupPane(String name, Color background) {
setLayout(new GridBagLayout());
add(new JLabel(name));
setBackground(background);
}
}
public class ConnectionPane extends JLayeredPane {
private List<Component[]> connections;
public ConnectionPane() {
connections = new ArrayList<>();
MouseAdapter ma = new MouseAdapter() {
private Component dragComponent;
private Point clickPoint;
private Point offset;
#Override
public void mousePressed(MouseEvent e) {
Component component = getComponentAt(e.getPoint());
if (component != ConnectionPane.this && component != null) {
dragComponent = component;
clickPoint = e.getPoint();
int deltaX = clickPoint.x - dragComponent.getX();
int deltaY = clickPoint.y - dragComponent.getY();
offset = new Point(deltaX, deltaY);
}
}
#Override
public void mouseDragged(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
int xDelta = mouseX - offset.x;
int yDelta = mouseY - offset.y;
dragComponent.setLocation(xDelta, yDelta);
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
public void add(Component parent, Component child) {
if (parent.getParent() != this) {
add(parent);
}
if (child.getParent() != this) {
add(child);
}
connections.add(new Component[]{parent, child});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Component[] connection : connections) {
Rectangle parent = connection[0].getBounds();
Rectangle child = connection[1].getBounds();
g2d.draw(new Line2D.Double(parent.getCenterX(), parent.getCenterY(), child.getCenterX(), child.getCenterY()));
}
g2d.dispose();
}
}
}
I would like to animate an Image placed in a JLabel like you can see below.
I have a problem with animation. The code doesn't produce any errors, but it just works in the void indefinitely.
Class Obstacle:
package imageTest;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Obstacle extends JPanel {
//Position
int posX,posY;
public int getPosX(){
return this.posX;
}
public void setPosX(int posX){
this.posX=posX;
}
public int getPosY(){
return this.posY;
}
public void setPosY(int posY){
this.posY=posY;
}
public int fctHasard(int borneInf,int borneSup){
int random = (int)(Math.random() * (borneSup-borneInf)) + borneInf;
return random;
}
//Image Obstacle
Image imgObstacle =new Image("C:\\Users\\antoine\\Desktop\\imgProjetObstacle.JPG");
JLabel labImgObstacle =null;
public void fctDessinerObstacle(JFrame fenPrincipale, JPanel panPrincipale) throws IOException{
int posXDepart=fctHasard(0,fenPrincipale.getWidth()),posYDepart=ImageUtil.getImageHeight(imgObstacle.adresseImg);
posX=posXDepart;
posY=posYDepart;
labImgObstacle=imgObstacle.fctAfficherImg(panPrincipale, posX,posY,ImageUtil.getImageWidth(imgObstacle.adresseImg), ImageUtil.getImageHeight(imgObstacle.adresseImg));
panPrincipale.add(labImgObstacle);
//fctMouvement(fenPrincipale, labImgObstacle ,panPrincipale,posX,posY);
}
public void fctMouvement(JFrame fenPrincipale, JLabel labImgObstacle , JPanel panPrincipale,int posX ,int posY) throws IOException{
boolean continuer=true;
while(continuer){
posY++;
labImgObstacle=imgObstacle.fctAfficherImg(panPrincipale, posX,posY,ImageUtil.getImageWidth(imgObstacle.adresseImg), ImageUtil.getImageHeight(imgObstacle.adresseImg));
panPrincipale.add(labImgObstacle);
panPrincipale.repaint();//remetlefondvierge
if(posY==fenPrincipale.getHeight()){
posX=fctHasard(0,fenPrincipale.getWidth());
posY=-ImageUtil.getImageHeight(imgObstacle.adresseImg);
//remet le fond vierge
labImgObstacle=imgObstacle.fctAfficherImg(panPrincipale, posX,posY,ImageUtil.getImageWidth(imgObstacle.adresseImg), ImageUtil.getImageHeight(imgObstacle.adresseImg));
panPrincipale.add(labImgObstacle);
}
}
}
}
EDIT1:
I try to understand you problem, is it to move a image into a JLabel ?
In this case, I try just to put an image as icon into a Jlabel and move while clicking on the JPanel as you can see below :
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
import javax.swing.UIManager;
import javax.swing.SwingUtilities;
public class Main extends JPanel {
public JLabel label1 ;
private int x = 100;
private int y = 5;
public Main() {
setLayout(null);
setPreferredSize( new Dimension(640, 480 ) );
addMouseListener(new MouseListener() {
#Override
public void mousePressed(MouseEvent e) {
x = x + 10;
y = y + 10;
label1.setBounds(x + getInsets().left, y + getInsets().top, label1.getPreferredSize().width, label1.getPreferredSize().height);
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
ImageIcon icon = createImageIcon("middle.gif", "a pretty but meaningless splat");
label1 = new JLabel("Image and Text",icon, JLabel.CENTER);
add(label1);
label1.setBounds(x + getInsets().left, y + getInsets().top, label1.getPreferredSize().width, label1.getPreferredSize().height);
}
protected static ImageIcon createImageIcon(String path,
String description) {
java.net.URL imgURL = Main.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Main());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
May be that could be the beginning to animate something ?
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'm trying to perform some actions, in example - drawing the rectangle on one of the many charts in separate tabs. Actually, I have functionality to draw rectangles and scrolling the chart, but it work only on last chart created. I know, this is logical, but how to manage these actions on previous charts in other tabs? Could I use list of chartpanels, to get these datasets and add new values to them? How to solve this? Can anyone help me?
SSCCE:
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellRenderer;
import net.miginfocom.swing.MigLayout;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYShapeAnnotation;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.Range;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.Layer;
public class TabbedPaneTEST extends JFrame {
private JFrame frame;
public JTabbedPane tabbedPane;
public JButton btnadd;
public TabbedPaneTEST okno = this;
ChartPanel chartpanel;
XYPlot subplot1;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TabbedPaneTEST window = new TabbedPaneTEST();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public TabbedPaneTEST() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tabbedPane = new JTabbedPane(JTabbedPane.TOP);
frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
btnadd = new JButton("add chart");
frame.getContentPane().add(btnadd, BorderLayout.NORTH);
panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.SOUTH);
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
btnpr = new JButton("draw rectangle");
panel.add(btnpr);
btnkr = new JButton("cursor");
panel.add(btnkr);
btnadd.addActionListener(new OtworzOknoWyboruInstruDoWykres(this));
// ==================================================================================================================================
// Action listener rectangle
btnpr.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
chartpanel.removeMouseListener(mouselistenerProstokat);
chartpanel
.removeMouseMotionListener(mousemotionlistenerProstokat);
chartpanel.removeMouseListener(mouselistenercursor);
chartpanel
.removeMouseMotionListener(mousemotionlistenercursor);
chartpanel
.removeMouseWheelListener(mousewheellistenercursor);
chartpanel.setPopupMenu(null);
} catch (Exception e) {
}
flagrectangle = true;
chartpanel.addMouseListener(mouselistenerProstokat);
chartpanel.addMouseMotionListener(mousemotionlistenerProstokat);
currentx = chartpanel.getLocationOnScreen().x;
currenty = Math.abs(chartpanel.getLocationOnScreen().y
- frame.getLocationOnScreen().y);
}
});
// ==================================================================================================================================
// ==================================================================================================================================
// Action listener cursor
btnkr.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
chartpanel.removeMouseListener(mouselistenerProstokat);
chartpanel
.removeMouseMotionListener(mousemotionlistenerProstokat);
chartpanel.removeMouseListener(mouselistenercursor);
chartpanel
.removeMouseMotionListener(mousemotionlistenercursor);
chartpanel
.removeMouseWheelListener(mousewheellistenercursor);
chartpanel.setPopupMenu(null);
} catch (Exception e) {
}
flagrectangle = false;
chartpanel.addMouseListener(mouselistenercursor);
chartpanel.addMouseMotionListener(mousemotionlistenercursor);
chartpanel.addMouseWheelListener(mousewheellistenercursor);
}
});
// ==================================================================================================================================
}
class OtworzOknoWyboruInstruDoWykres implements ActionListener {
private TabbedPaneTEST okno;
public OtworzOknoWyboruInstruDoWykres(TabbedPaneTEST okno) {
super();
this.okno = okno;
}
#Override
public void actionPerformed(ActionEvent e) {
formchild FrameDoInstruWyk = null;
FrameDoInstruWyk = new formchild();
FrameDoInstruWyk.setOkno(okno);
}
}
List<ChartPanel> CPlist = new ArrayList<>();
public void DodajWykresInstrumentu(String string) {
double[] value = new double[1];
Random generator = new Random();
value[0] = generator.nextDouble();
XYSeries series = new XYSeries("Random Data");
series.add(1.0, 400.2);
series.add(5.0, 294.1);
series.add(4.0, 100.0);
series.add(12.5, 734.4);
series.add(17.3, 453.2);
series.add(21.2, 500.2);
series.add(21.9, null);
series.add(25.6, 734.4);
series.add(30.0, 453.2);
XYSeriesCollection dataset = new XYSeriesCollection(series);
String plotTitle = "sometitle";
String xaxis = "number";
String yaxis = "value";
PlotOrientation orientation = PlotOrientation.VERTICAL;
boolean show = false;
boolean toolTips = false;
boolean urls = false;
JFreeChart chart = ChartFactory.createHistogram(plotTitle, xaxis,
yaxis, dataset, orientation, show, toolTips, urls);
subplot1 = (XYPlot) chart.getPlot();
chartpanel = new ChartPanel(chart) {
#Override
public void restoreAutoBounds() {
}
};
chartpanel.setRangeZoomable(false);
chartpanel.setDomainZoomable(true);
chartpanel.setDismissDelay(400);
chartpanel.setZoomTriggerDistance(-1000);
chartpanel.setMouseZoomable(false);
CPlist.add(chartpanel);
tabbedPane.addTab(string, chartpanel);
}
private double pointstartxrange;
private double pointendxrange;
private double pointstartx;
private double pointstarty;
private double pointendx;
private double pointendy;
Point pointstart = null;
Point pointend = null;
// ==================================================================================================================================
// mouse listener cursor
MouseListener mouselistenercursor = new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
Point pointstart = e.getPoint();
Point2D point = chartpanel.translateScreenToJava2D(pointstart);
Rectangle2D plotArea = chartpanel.getScreenDataArea();
pointstartxrange = subplot1.getDomainAxis().java2DToValue(
point.getX(), plotArea, subplot1.getDomainAxisEdge());
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
};
MouseMotionListener mousemotionlistenercursor = new MouseMotionListener() {
#Override
public void mouseMoved(MouseEvent arg0) {
}
#Override
public void mouseDragged(MouseEvent arg0) {
Point pointstart = arg0.getPoint();
Point2D point = chartpanel.translateScreenToJava2D(pointstart);
Rectangle2D plotArea = chartpanel.getScreenDataArea();
pointendxrange = subplot1.getDomainAxis().java2DToValue(
point.getX(), plotArea, subplot1.getDomainAxisEdge());
double roznica = (pointendxrange - pointstartxrange) * (-1);
double mini = subplot1.getDomainAxis().getRange().getLowerBound()
+ roznica / 10;
double maxi = subplot1.getDomainAxis().getRange().getUpperBound()
+ roznica / 10;
double maximumRange = subplot1.getDataRange(
subplot1.getDomainAxis()).getUpperBound();
double minimumRange = subplot1.getDataRange(
subplot1.getDomainAxis()).getLowerBound();
if (mini >= minimumRange - 50D
&& pointstartxrange <= pointendxrange) {
Range range = new Range(mini, maxi);
subplot1.getDomainAxis().setRange(range, true, true);
pointstartxrange = pointstartxrange + roznica / 10;
pointendxrange = pointendxrange + roznica / 10;
} else if (maxi <= maximumRange + 50D
&& pointstartxrange >= pointendxrange) {
Range range = new Range(mini, maxi);
subplot1.getDomainAxis().setRange(range, true, true);
pointstartxrange = pointstartxrange + roznica / 10;
pointendxrange = pointendxrange + roznica / 10;
}
}
};
MouseWheelListener mousewheellistenercursor = new MouseWheelListener() {
int zoomCounter = 0;
#Override
public void mouseWheelMoved(MouseWheelEvent arg0) {
System.out.println(zoomCounter);
if (arg0.getWheelRotation() > 0) {
if (zoomCounter > (-5)) {
chartpanel.zoomOutDomain(MouseInfo.getPointerInfo()
.getLocation().x, MouseInfo.getPointerInfo()
.getLocation().y);
zoomCounter = zoomCounter - 1;
}
} else if (arg0.getWheelRotation() < 0) {
if (zoomCounter < 5) {
chartpanel.zoomInDomain(MouseInfo.getPointerInfo()
.getLocation().x, MouseInfo.getPointerInfo()
.getLocation().y);
zoomCounter = zoomCounter + 1;
}
}
}
};
// ==================================================================================================================================
// ==================================================================================================================================
// Drawing rectangle
private MouseListener mouselistenerProstokat = new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
Point2D point = chartpanel.translateScreenToJava2D(e.getPoint());
Rectangle2D plotArea = chartpanel.getScreenDataArea();
pointendx = subplot1.getDomainAxis().java2DToValue(point.getX(),
plotArea, subplot1.getDomainAxisEdge());
pointendy = subplot1.getRangeAxis().java2DToValue(point.getY(),
plotArea, subplot1.getRangeAxisEdge());
chartfigura();
pointstart = null;
}
#Override
public void mousePressed(MouseEvent e) {
Point2D point = chartpanel.translateScreenToJava2D(e.getPoint());
Rectangle2D plotArea = chartpanel.getScreenDataArea();
pointstartx = subplot1.getDomainAxis().java2DToValue(point.getX(),
plotArea, subplot1.getDomainAxisEdge());
pointstarty = subplot1.getRangeAxis().java2DToValue(point.getY(),
plotArea, subplot1.getRangeAxisEdge());
pointstart = e.getPoint();
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
};
private MouseMotionListener mousemotionlistenerProstokat = new MouseMotionListener() {
#Override
public void mouseMoved(MouseEvent e) {
pointend = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent arg0) {
chartpanel.setMouseZoomable(false);
pointend = arg0.getPoint();
repaint();
}
};
private boolean flagrectangle;
private int datasetIndex;
private Shape createRectangle(double startx, double starty, double endx,
double endy) {
Rectangle2D e = new Rectangle2D.Double();
e.setFrameFromDiagonal(startx, starty, endx, endy);
return e;
}
// ==================================================================================================================================
// ==================================================================================================================================
private void chartfigura() {
float alpha = 0.75f;
int type = AlphaComposite.SRC_OVER;
AlphaComposite composite = AlphaComposite.getInstance(type, alpha);
if (flagrectangle == true) {
datasetIndex++;
subplot1.setDataset(datasetIndex,
Annotacja("rect", pointstartx, pointstarty));
XYLineAndShapeRenderer rendererShape = new XYLineAndShapeRenderer();
rendererShape.setBaseShapesVisible(false);
Rectangle2D rectangle = (Rectangle2D) createRectangle(pointstartx,
pointstarty, pointendx, pointendy);
rendererShape.addAnnotation(new XYShapeAnnotation(rectangle,
new BasicStroke(1.0f), Color.BLACK, new Color(255, 90, 100,
128)), Layer.BACKGROUND);
subplot1.setRenderer(datasetIndex, rendererShape);
}
}
// ==================================================================================================================================
public XYSeriesCollection Annotacja(final String name, double wartosc1,
double data1) {
final XYSeries series = new XYSeries(name);
series.add(wartosc1, data1);
return new XYSeriesCollection(series);
}
// ==================================================================================================================================
int currentx;
int currenty;
public JPanel panel;
public JButton btnpr;
public JButton btnkr;
// ==================================================================================================================================
public void paint(Graphics g) {
super.paint(g);
g.translate(currentx, currenty);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (pointstart != null) {
if (flagrectangle == true) {
g.setClip(chartpanel.getBounds());
g.setColor(Color.BLACK);
((Graphics2D) g).draw(createRectangle(pointstart.x,
pointstart.y, pointend.x, pointend.y));
}
}
}
// ==================================================================================================================================
}
class formchild extends JFrame {
public JFrame frame = this;
public JPanel panel;
public JPanel panel_1;
public JTable table;
public JPanel panel_2;
public JButton btnOk;
public JButton btnOK;
public JScrollPane scrollPane;
private TabbedPaneTEST okno;
public JTextField textField;
JButton button = new JButton();
public JLabel lblSzukajFrazy;
public formchild() {
frame.setMinimumSize(new Dimension(400, 450));
frame.setPreferredSize(new Dimension(400, 450));
panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.NORTH);
panel.setLayout(new MigLayout("", "[544px]", "[23px]"));
panel_1 = new JPanel();
frame.getContentPane().add(panel_1, BorderLayout.CENTER);
panel_1.setLayout(new BorderLayout(0, 0));
panel_2 = new JPanel();
FlowLayout flowLayout = (FlowLayout) panel_2.getLayout();
flowLayout.setAlignment(FlowLayout.RIGHT);
frame.getContentPane().add(panel_2, BorderLayout.SOUTH);
btnOK = new JButton("OK");
btnOK.setPreferredSize(new Dimension(70, 23));
panel_2.add(btnOK);
btnOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
frame.dispose();
okno = null;
}
});
String[] nazwyKolumn = { "element", "button" };
String[][] data = new String[10][2];
for (int i = 0; i < 10; i++) {
data[i][0] = "a" + i;
data[i][1] = "add";
}
table = new JTable(data, nazwyKolumn);
table.setAutoCreateRowSorter(true);
table.getColumn("button").setMaxWidth(70);
table.getColumn("button").setCellRenderer(new ButtonRenderer());
table.getColumn("button").setCellEditor(
new ButtonEditor(new JCheckBox()));
table.setRowHeight(30);
scrollPane = new JScrollPane(table);
panel_1.add(scrollPane, BorderLayout.CENTER);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println(table.getValueAt(table.getSelectedRow(), 0));
okno.DodajWykresInstrumentu((table.getValueAt(
table.getSelectedRow(), 0)).toString());
}
});
frame.validate();
frame.show();
}
public void setOkno(TabbedPaneTEST okno) {
this.okno = okno;
}
class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
setText((value == null) ? "" : value.toString());
return this;
}
}
class ButtonEditor extends DefaultCellEditor {
private String label = "add";
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
}
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
label = (value == null) ? "" : value.toString();
button.setText(label);
return button;
}
public Object getCellEditorValue() {
return new String(label);
}
}
}
Your example overrides JFrame and its paint() method to replace the functionality usually provided by ChartPanel. Instead, extend ChartPanel and override paintComponent(), then each panel you create will have a single chart with the new functionality.
You can control available listeners more reliably.
You can make a control panel available, as shown here.
As discussed in Painting in AWT and Swing: The Paint Methods, "Swing programs should override paintComponent() instead of overriding paint()."
Sounds like your looking for the Observer pattern to handle events on the other GUI components.
Take a look at http://en.wikipedia.org/wiki/Observer_pattern.
Basic idé is that whenever an event happens(say drawing a triangle in a chart) then all the classes that listens to said event are notified with whatever information you feel is relevant to the event.
Theres ALOT of literature/examples about it on the web.