I want to create a titled border with the title as a CheckBox.
How do i do that?
This tutorial is exactly what you need: CLICK
Unfortunately the images are no longer online, but you can launch the Webstart application.
Credit to JavaLobby and Stephan for the basis of this answer.
However, this is a cut-down example that provides a simple implementation of a TitledBorder with a JCheckBox:
public class CheckBoxTitledBorder extends AbstractBorder {
private final TitledBorder _parent;
private final JCheckBox _checkBox;
public CheckBoxTitledBorder(String title, boolean selected) {
_parent = BorderFactory.createTitledBorder(title);
_checkBox = new JCheckBox(title, selected);
_checkBox.setHorizontalTextPosition(SwingConstants.LEFT);
}
public boolean isSelected() {
return _checkBox.isSelected();
}
public void addActionListener(ActionListener listener) {
_checkBox.addActionListener(listener);
}
#Override
public boolean isBorderOpaque() {
return true;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Insets borderInsets = _parent.getBorderInsets(c);
Insets insets = getBorderInsets(c);
int temp = (insets.top - borderInsets.top) / 2;
_parent.paintBorder(c, g, x, y + temp, width, height - temp);
Dimension size = _checkBox.getPreferredSize();
final Rectangle rectangle = new Rectangle(5, 0, size.width, size.height);
final Container container = (Container) c;
container.addMouseListener(new MouseAdapter() {
private void dispatchEvent(MouseEvent me) {
if (rectangle.contains(me.getX(), me.getY())) {
Point pt = me.getPoint();
pt.translate(-5, 0);
_checkBox.setBounds(rectangle);
_checkBox.dispatchEvent(new MouseEvent(_checkBox, me.getID(),
me.getWhen(), me.getModifiers(), pt.x, pt.y, me.getClickCount(), me.isPopupTrigger(), me.getButton()));
if (!_checkBox.isValid()) {
container.repaint();
}
}
}
public void mousePressed(MouseEvent me) {
dispatchEvent(me);
}
public void mouseReleased(MouseEvent me) {
dispatchEvent(me);
}
});
SwingUtilities.paintComponent(g, _checkBox, container, rectangle);
}
#Override
public Insets getBorderInsets(Component c) {
Insets insets = _parent.getBorderInsets(c);
insets.top = Math.max(insets.top, _checkBox.getPreferredSize().height);
return insets;
}
}
I also found this example.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
/**
* #version 1.0 08/12/99
*/
public class CompTitledPaneExample2 extends JFrame {
public CompTitledPaneExample2() {
super("CompTitledPaneExample2");
JCheckBox title = new JCheckBox("Title");
title.setSelected(true);
final CompTitledPane p1 = new CompTitledPane(title);
title.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
p1.setEnabled(e.getStateChange() == ItemEvent.SELECTED);
}
});
APanel p2 = new APanel();
p1.setTransmittingAllowed(true);
p1.setTransmitter(p2);
p1.getContentPane().add(p2);
getContentPane().add(p1, BorderLayout.CENTER);
}
class APanel extends JPanel implements StateTransmitter {
JButton button;
JTextField textField;
APanel() {
button = new JButton("abc");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Ouch!");
}
});
textField = new JTextField(10);
textField.setText("text");
add(button, BorderLayout.NORTH);
add(textField, BorderLayout.SOUTH);
}
public void setChildrenEnabled(boolean enable) {
button.setEnabled(enable);
textField.setEnabled(enable);
}
}
public static void main(String args[]) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {
}
CompTitledPaneExample2 frame = new CompTitledPaneExample2();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(280, 110);
frame.setVisible(true);
}
}
class CompTitledPane extends JPanel {
protected CompTitledBorder border;
protected JComponent component;
protected JPanel panel;
protected boolean transmittingAllowed;
protected StateTransmitter transmitter;
public CompTitledPane() {
this(new JLabel("Title"));
// debug
// JLabel label = (JLabel)getTitleComponent();
// label.setOpaque(true);
// label.setBackground(Color.yellow);
}
public CompTitledPane(JComponent component) {
this.component = component;
border = new CompTitledBorder(component);
setBorder(border);
panel = new JPanel();
setLayout(null);
add(component);
add(panel);
transmittingAllowed = false;
transmitter = null;
}
public JComponent getTitleComponent() {
return component;
}
public void setTitleComponent(JComponent newComponent) {
remove(component);
add(newComponent);
border.setTitleComponent(newComponent);
component = newComponent;
}
public JPanel getContentPane() {
return panel;
}
public void doLayout() {
Insets insets = getInsets();
Rectangle rect = getBounds();
rect.x = 0;
rect.y = 0;
Rectangle compR = border.getComponentRect(rect, insets);
component.setBounds(compR);
rect.x += insets.left;
rect.y += insets.top;
rect.width -= insets.left + insets.right;
rect.height -= insets.top + insets.bottom;
panel.setBounds(rect);
}
public void setTransmittingAllowed(boolean enable) {
transmittingAllowed = enable;
}
public boolean getTransmittingAllowed() {
return transmittingAllowed;
}
public void setTransmitter(StateTransmitter transmitter) {
this.transmitter = transmitter;
}
public StateTransmitter getTransmitter() {
return transmitter;
}
public void setEnabled(boolean enable) {
super.setEnabled(enable);
if (transmittingAllowed && transmitter != null) {
transmitter.setChildrenEnabled(enable);
}
}
}
interface StateTransmitter {
public void setChildrenEnabled(boolean enable);
}
class CompTitledBorder extends TitledBorder {
protected JComponent component;
public CompTitledBorder(JComponent component) {
this(null, component, LEFT, TOP);
}
public CompTitledBorder(Border border) {
this(border, null, LEFT, TOP);
}
public CompTitledBorder(Border border, JComponent component) {
this(border, component, LEFT, TOP);
}
public CompTitledBorder(Border border, JComponent component,
int titleJustification, int titlePosition) {
super(border, null, titleJustification, titlePosition, null, null);
this.component = component;
if (border == null) {
this.border = super.getBorder();
}
}
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
Rectangle borderR = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING,
width - (EDGE_SPACING * 2), height - (EDGE_SPACING * 2));
Insets borderInsets;
if (border != null) {
borderInsets = border.getBorderInsets(c);
} else {
borderInsets = new Insets(0, 0, 0, 0);
}
Rectangle rect = new Rectangle(x, y, width, height);
Insets insets = getBorderInsets(c);
Rectangle compR = getComponentRect(rect, insets);
int diff;
switch (titlePosition) {
case ABOVE_TOP:
diff = compR.height + TEXT_SPACING;
borderR.y += diff;
borderR.height -= diff;
break;
case TOP:
case DEFAULT_POSITION:
diff = insets.top / 2 - borderInsets.top - EDGE_SPACING;
borderR.y += diff;
borderR.height -= diff;
break;
case BELOW_TOP:
case ABOVE_BOTTOM:
break;
case BOTTOM:
diff = insets.bottom / 2 - borderInsets.bottom - EDGE_SPACING;
borderR.height -= diff;
break;
case BELOW_BOTTOM:
diff = compR.height + TEXT_SPACING;
borderR.height -= diff;
break;
}
border.paintBorder(c, g, borderR.x, borderR.y, borderR.width,
borderR.height);
Color col = g.getColor();
g.setColor(c.getBackground());
g.fillRect(compR.x, compR.y, compR.width, compR.height);
g.setColor(col);
component.repaint();
}
public Insets getBorderInsets(Component c, Insets insets) {
Insets borderInsets;
if (border != null) {
borderInsets = border.getBorderInsets(c);
} else {
borderInsets = new Insets(0, 0, 0, 0);
}
insets.top = EDGE_SPACING + TEXT_SPACING + borderInsets.top;
insets.right = EDGE_SPACING + TEXT_SPACING + borderInsets.right;
insets.bottom = EDGE_SPACING + TEXT_SPACING + borderInsets.bottom;
insets.left = EDGE_SPACING + TEXT_SPACING + borderInsets.left;
if (c == null || component == null) {
return insets;
}
int compHeight = 0;
if (component != null) {
compHeight = component.getPreferredSize().height;
}
switch (titlePosition) {
case ABOVE_TOP:
insets.top += compHeight + TEXT_SPACING;
break;
case TOP:
case DEFAULT_POSITION:
insets.top += Math.max(compHeight, borderInsets.top)
- borderInsets.top;
break;
case BELOW_TOP:
insets.top += compHeight + TEXT_SPACING;
break;
case ABOVE_BOTTOM:
insets.bottom += compHeight + TEXT_SPACING;
break;
case BOTTOM:
insets.bottom += Math.max(compHeight, borderInsets.bottom)
- borderInsets.bottom;
break;
case BELOW_BOTTOM:
insets.bottom += compHeight + TEXT_SPACING;
break;
}
return insets;
}
public JComponent getTitleComponent() {
return component;
}
public void setTitleComponent(JComponent component) {
this.component = component;
}
public Rectangle getComponentRect(Rectangle rect, Insets borderInsets) {
Dimension compD = component.getPreferredSize();
Rectangle compR = new Rectangle(0, 0, compD.width, compD.height);
switch (titlePosition) {
case ABOVE_TOP:
compR.y = EDGE_SPACING;
break;
case TOP:
case DEFAULT_POSITION:
compR.y = EDGE_SPACING
+ (borderInsets.top - EDGE_SPACING - TEXT_SPACING - compD.height)
/ 2;
break;
case BELOW_TOP:
compR.y = borderInsets.top - compD.height - TEXT_SPACING;
break;
case ABOVE_BOTTOM:
compR.y = rect.height - borderInsets.bottom + TEXT_SPACING;
break;
case BOTTOM:
compR.y = rect.height
- borderInsets.bottom
+ TEXT_SPACING
+ (borderInsets.bottom - EDGE_SPACING - TEXT_SPACING - compD.height)
/ 2;
break;
case BELOW_BOTTOM:
compR.y = rect.height - compD.height - EDGE_SPACING;
break;
}
switch (titleJustification) {
case LEFT:
case DEFAULT_JUSTIFICATION:
compR.x = TEXT_INSET_H + borderInsets.left;
break;
case RIGHT:
compR.x = rect.width - borderInsets.right - TEXT_INSET_H
- compR.width;
break;
case CENTER:
compR.x = (rect.width - compR.width) / 2;
break;
}
return compR;
}
}
An easy solution is to just make your checkbox overlap the other panel with the titled border, with the title text as just " ".
You can do this by having the bordered JPanel and the JCheckBox in the same GridBagLayout cell for instance. Just make sure that you add the checkbox first, and give it different GridBagConstraints Insets than your bordered JPanel so that it lines up.
I set the title text to " " so that it automatically adjusts the contents and stuff to make room for the title as it normally would, but you could just as easily use a different border and size everything up yourself.
Related
There is one Paraview user interface as follow attracted me.
I think this interface can be used to assign value into array. It works like this :
I want to implement this into a Java program but I found no Java API can support my idea. The closest design from me would be adding multiple JSlider like this :
But what if it is a 100 size array, I wouldn't want to add 100 JSliders. Do you have better solution for this ?
Okay, so this is a pretty basic example. It needs a lot more work and optimisation, but should get you moving in the right direction
Have a look at Painting in AWT and Swing, Performing Custom Painting, 2D Graphics and How to Write a Mouse Listener for more details
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGraph {
public static void main(String[] args) {
new TestGraph();
}
public TestGraph() {
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 GraphPane(0, 100, new int[100]));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class GraphPane extends JPanel {
protected static final int COLUMN_WIDTH = 10;
protected static final int VERTICAL_INSETS = 10;
private int[] data;
private int minValue, maxValue;
private Path2D.Double graph;
private List<Shape> buttons;
private Point mousePoint;
public GraphPane(int minValue, int maxValue, int[] data) {
this.data = data;
this.minValue = minValue;
this.maxValue = maxValue;
buttons = new ArrayList<>(data == null ? 25 : data.length);
updateView();
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
updateData(e);
}
#Override
public void mouseDragged(MouseEvent e) {
updateData(e);
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
protected void updateData(MouseEvent e) {
// Which "column" was clicked on
int column = (int) Math.round(((double) e.getX() / (double) COLUMN_WIDTH)) - 1;
// Get the "height" of the clickable area
int clickRange = getHeight() - (VERTICAL_INSETS * 2);
// Adjust the y click point for the margins...
int yPos = e.getY() - VERTICAL_INSETS;
// Calculate the vertical position that was clicked
// this ensures that the range is between 0 and clickRange
// You could choose to ignore values out side of this range
int row = Math.min(Math.max(clickRange - yPos, 0), clickRange);
// Normalise the value between 0-1
double clickNormalised = row / (double) clickRange;
// Calculate the actual row value...
row = minValue + (int) (Math.round(clickNormalised * maxValue));
// Update the data
data[column] = row;
mousePoint = new Point(
COLUMN_WIDTH + (column * COLUMN_WIDTH),
getHeight() - (VERTICAL_INSETS + (int) Math.round((data[column] / 100d) * clickRange)));
updateView();
repaint();
}
#Override
public void invalidate() {
super.invalidate();
updateView();
}
protected Shape createButton(int xPos, int yPos) {
return new Ellipse2D.Double(xPos - COLUMN_WIDTH / 2, yPos - COLUMN_WIDTH / 2, COLUMN_WIDTH, COLUMN_WIDTH);
}
protected void updateView() {
graph = new Path2D.Double();
buttons.clear();
if (data != null && data.length > 0) {
int verticalRange = getHeight() - (VERTICAL_INSETS * 2);
int xPos = COLUMN_WIDTH;
int yPos = getHeight() - (VERTICAL_INSETS + (int) Math.round((data[0] / 100d) * verticalRange));
graph.moveTo(xPos, yPos);
if (data[0] > 0) {
buttons.add(createButton(xPos, yPos));
}
for (int index = 1; index < data.length; index++) {
xPos = (index * COLUMN_WIDTH) + COLUMN_WIDTH;
yPos = getHeight() - (VERTICAL_INSETS + (int) Math.round((data[index] / 100d) * verticalRange));
graph.lineTo(xPos, yPos);
if (data[index] > 0) {
buttons.add(createButton(xPos, yPos));
}
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(data == null ? 0 : (data.length + 1) * COLUMN_WIDTH, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (data != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(64, 64, 64, 32));
for (int index = 0; index < data.length; index++) {
int xPos = (index * COLUMN_WIDTH) + COLUMN_WIDTH;
g2d.drawLine(xPos, VERTICAL_INSETS, xPos, getHeight() - VERTICAL_INSETS);
}
g2d.setColor(Color.BLACK);
g2d.draw(graph);
for (Shape button : buttons) {
g2d.fill(button);
}
if (mousePoint != null) {
g2d.setColor(new Color(255, 192, 203));
Ellipse2D dot = new Ellipse2D.Double((mousePoint.x - COLUMN_WIDTH / 2) - 2, (mousePoint.y - COLUMN_WIDTH / 2) - 2, COLUMN_WIDTH + 4, COLUMN_WIDTH + 4);
g2d.draw(dot);
g2d.setColor(new Color(255, 192, 203, 128));
g2d.fill(dot);
}
g2d.dispose();
}
}
}
}
Before anyone says I didn't put the "fill" in, I deliberately used a Path2D to make it much simpler to achieve ;)
here is a small example how to create this using polygon class .i sorted x coordinate and use polygon class to make this.
GraphPane.class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.JPanel;
public class GraphPane extends JPanel {
ArrayList<XYpoints> poinList = new ArrayList();
private int px;
private int py;
private XYpoints last;
private boolean drag;
private static Color graphColor=new Color(32, 178, 170);
public GraphPane() {
initComponents();
poinList.add(new XYpoints(50, 400));
poinList.add(new XYpoints(450, 50));
poinList.add(new XYpoints(600, 400));
}
private void initComponents() {
setBackground(new java.awt.Color(255, 255, 255));
addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
System.out.println("drag");
if (drag) {
last.setY(evt.getY());
GraphPane.this.repaint();
}
}
});
addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent evt) {
int x = evt.getX();
int y = evt.getY();
for (XYpoints poinList1 : poinList) {
px = poinList1.getpX();
py = poinList1.getpY();
if (x < px + 5 && x > px - 5 && y < py + 5 && y > py - 5) {
System.out.println("inter");
poinList1.setIntersect(true);
last = poinList1;
drag = true;
GraphPane.this.repaint();
return;
}
}
poinList.add(new XYpoints(x, y));
Collections.sort(poinList, new XComp());
GraphPane.this.repaint();
}
public void mouseReleased(java.awt.event.MouseEvent evt) {
if (drag) {
drag = false;
last.setIntersect(false);
GraphPane.this.repaint();
}
}
});
}
#Override
protected void paintComponent(Graphics gr) {
super.paintComponent(gr);
Graphics2D g = (Graphics2D) gr.create();
Polygon p = new Polygon();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (XYpoints poinList1 : poinList) {
px = poinList1.getpX();
py = poinList1.getpY();
p.addPoint(px, py);
}
g.setColor(graphColor);
g.fillPolygon(p);
for (XYpoints poinList1 : poinList) {
px = poinList1.getpX();
py = poinList1.getpY();
g.setColor(Color.red);
if (poinList1.isIntersect()) {
g.setColor(Color.blue);
}
g.fillOval(px - 5, py - 5, 10, 10);
}
g.dispose();
}
}
XYpoints.class
import java.awt.Polygon;
import java.util.Comparator;
public class XYpoints extends Polygon {
private int x;
private int y;
private boolean inter;
public XYpoints(int x, int y) {
this.x = x;
this.y = y;
}
public void setIntersect(boolean state) {
inter = state;
}
public void setY(int y){
this.y=y;
}
public boolean isIntersect() {
return inter;
}
public int getpX() {
//System.out.println("send " + this.x);
return this.x;
}
public int getpY() {
return this.y;
}
}
XComp .class
class XComp implements Comparator<XYpoints> {
#Override
public int compare(XYpoints t, XYpoints t1) {
if (t.getpX() < t1.getpX()) {
return -1;
} else {
return 1;
}
}
}
myframe.class
import javax.swing.JFrame;
public class myframe extends JFrame {
public myframe() {
GraphPane pane = new GraphPane();
setContentPane(pane);
setSize(650, 500);
setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new myframe();
}
});
}
}
So I am writing a program in Java, and one of the important things it needs to be able to do is render multiple objects onto the screen that can be dragged and dropped by the user. I have made a class (pasted below), but when I try to initialise one with
new DragNode();
it doesn't work.
Can someone please tell me what I am doing wrong?
Thanks,
Sam
public static class DragNode extends JLabel{
public static final long serialVersionUID=155L;
public class MA extends MouseAdapter{
public void mousePressed(MouseEvent e) {
preX = rect.x - e.getX();
preY = rect.y - e.getY();
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
System.out.println("Mouse pressed on rectangle");
} else {
pressOut = true;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (!pressOut) {
updateLocation(e);
} else {
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = false;
}
}
public void updateLocation(MouseEvent e) {
rect.setLocation(preX + e.getX(), preY + e.getY());
checkRect();
repaint();
}
}
public int x,y;
Rectangle rect,area;
int preX,preY;
boolean firstTime=true;
boolean pressOut=false;
private Dimension dim=getGraphPanelSize();
private Image Node_Sprite;
public DragNode(){
init();
}
public DragNode(int x,int y){
this.x=x;
this.y=y;
init();
}
public void init(){
//setBackground(Color.GRAY);
setOpaque(false);
addMouseMotionListener(new MA());
addMouseListener(new MA());
rect = new Rectangle(x, y, 50, 50);
area=new Rectangle(dim);
try{
Node_Sprite=ImageIO.read(new File("Node_Sprite.png"));
}catch(IOException ioe){}
}
boolean checkRect() {
if (area == null) {
return false;
}
if (area.contains(rect.x, rect.y, rect.getWidth(), rect.getHeight())) {
return true;
}
int new_x = rect.x;
int new_y = rect.y;
if ((rect.x + rect.getWidth()) > area.getWidth()) {
new_x = (int) area.getWidth() - (int) (rect.getWidth() - 1);
}
if (rect.x < 0) {
new_x = -1;
}
if ((rect.y + rect.getHeight()) > area.getHeight()) {
new_y = (int) area.getHeight() - (int) (rect.getHeight() - 1);
}
if (rect.y < 0) {
new_y = -1;
}
rect.setLocation(new_x, new_y);
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
if (firstTime) {
rect.setLocation(x,y);
firstTime = false;
}
g2d.setColor(new Color(0,0,0,0));
g2d.drawImage(Node_Sprite, rect.x,rect.y,50,50,null);
}
}
When I replace the code for drawing the rectangle with
g2d.setColor(Color.red);
g2d.fillRect( rect.x, rect.y, 50, 50);
// g2d.drawImage(Node_Sprite, rect.x, rect.y, 50, 50, null);
It is drawn and can be dragged in the x-direction. So there might be something wrong with your image (does it exist in the specified folder?). I expected the dragging to be in both directions, so there might be an issue there as well for the y-direction.
EDIT: Ok, I tried it with an image as well, works well. I also saw that your "borders" 'dim' are set very narrow, so I increased them to 300/300 so I can drag around my image in both axis.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
public class DragNode extends JLabel {
public static final long serialVersionUID = 155L;
public static void main(String[] args) {
JLabel node = new DragNode();
JFrame frame = new JFrame("blupp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new MigLayout(""));
frame.getContentPane().add(node, "grow, push");
frame.setLocationRelativeTo(null);
frame.setSize(new Dimension(500, 300));
frame.setVisible(true);
}
public class MA extends MouseAdapter {
public void mousePressed(MouseEvent e) {
preX = rect.x - e.getX();
preY = rect.y - e.getY();
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
System.out.println("Mouse pressed on rectangle");
} else {
pressOut = true;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (!pressOut) {
updateLocation(e);
} else {}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = false;
}
}
public void updateLocation(MouseEvent e) {
rect.setLocation(preX + e.getX(), preY + e.getY());
checkRect();
repaint();
}
}
public int x, y;
Rectangle rect, area;
int preX, preY;
boolean firstTime = true;
boolean pressOut = false;
private Dimension dim = new Dimension(300, 300);
private Image Node_Sprite;
public DragNode() {
init();
}
public DragNode(int x, int y) {
this.x = x;
this.y = y;
init();
}
public void init() {
//setBackground(Color.GRAY);
setOpaque(false);
addMouseMotionListener(new MA());
addMouseListener(new MA());
rect = new Rectangle(x, y, 50, 50);
area = new Rectangle(dim);
try {
Node_Sprite = ImageIO.read(new File("Node_Sprite.png"));
} catch (IOException ioe) {}
}
boolean checkRect() {
if (area == null) {
return false;
}
if (area.contains(rect.x, rect.y, rect.getWidth(), rect.getHeight())) {
return true;
}
int new_x = rect.x;
int new_y = rect.y;
if ((rect.x + rect.getWidth()) > area.getWidth()) {
new_x = (int) area.getWidth() - (int) (rect.getWidth() - 1);
}
if (rect.x < 0) {
new_x = -1;
}
if ((rect.y + rect.getHeight()) > area.getHeight()) {
new_y = (int) area.getHeight() - (int) (rect.getHeight() - 1);
}
if (rect.y < 0) {
new_y = -1;
}
rect.setLocation(new_x, new_y);
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.green);
// g2d.fillRect(10, 10, 100, 100);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
if (firstTime) {
rect.setLocation(x, y);
firstTime = false;
}
g2d.setColor(Color.red);
// g2d.fillRect( rect.x, rect.y, 50, 50);
g2d.drawImage(Node_Sprite, rect.x, rect.y, 50, 50, null);
}
}
Not sure why you are extending JLabel. You are not using the label to paint text or an Icon. Instead you are actually doing the custom painting yourself so you should be extending JComponent.
Or the other approach is to just use a JLabel to display the image and then create your listener to drag the label to a new location and let the label to the painting. You can check out Component Mover which allows you to drag any component.
I am working on a 4 Way Pong Program. I have it to the point where my paddles will move with mouse movement, and the ball will bounce around the screen.
I am stuck when it comes to figuring out how to check for collisions between the ball and the paddles (which will increase the score) and between the ball and the edges of the JPanel (which will end the game).
Any guidance is greatly appreciated...
Game Class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Game extends JPanel {
JFrame window = new JFrame();
Timer timer = new Timer(30, new ActionHandler());
ArrayList<Ball> balls = new ArrayList<Ball>();
ArrayList<Paddle> horizPaddles = new ArrayList<Paddle>();
ArrayList<Paddle> vertPaddles = new ArrayList<Paddle>();
Paddle pTop;
Paddle pBottom;
Paddle pRight;
Paddle pLeft;
Ball b;
int score = 0;
JLabel scoreLabel;
//==========================================================
public Game() {
window.setBounds(100,100,900,500);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setTitle("4 Way Pong");
window.setResizable(false);
JPanel scorePanel = new JPanel(true);
scoreLabel = new JLabel("Current Score: " + Integer.toString(score));
scoreLabel.setFont(new Font("sansserif", Font.PLAIN, 20));
scoreLabel.setForeground(Color.RED);
scorePanel.add(scoreLabel);
JPanel buttons = new JPanel(true);
Container con = window.getContentPane();
con.setLayout(new BorderLayout());
con.add(this, BorderLayout.CENTER);
con.add(buttons, BorderLayout.SOUTH);
con.add(scorePanel, BorderLayout.NORTH);
this.setBackground(Color.BLACK);
this.addMouseMotionListener(new MouseMoved());
ButtonCatch bc = new ButtonCatch();
JButton btn;
btn = new JButton("New Game");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("Swap Colors");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("High Scores");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("Save Score");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("Quit");
btn.addActionListener(bc);
buttons.add(btn);
timer.start();
window.setVisible(true);
}
//==========================================================
public static void main(String[] args) {
new Game();
}
//==========================================================
public void update() {
for(Ball b : balls) {
b.move(getWidth() + 30, getHeight() + 25);
}
//checkSideCollision();
//checkHorizPaddleCollision();
//checkVertPaddleCollision();
repaint();
}
//==========================================================
public void checkSideCollision() {
if(b.getyPos() > getHeight()) {
JOptionPane.showMessageDialog(null, "Game Over. You Scored " + score + ".", "GAME OVER", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
//==========================================================
public void checkHorizPaddleCollision() {
if(b.getxPos() == pBottom.getX() && b.getyPos() == pBottom.getY()) {
//b.yPos = b.yPos - 5;
score++;
}
}
//==========================================================
public void checkVertPaddleCollision() {
}
//==========================================================
public class ButtonCatch implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
switch(e.getActionCommand()) {
case "Quit": JOptionPane.showMessageDialog(null, "You Quit... No Score Recorded", "Game Over", JOptionPane.INFORMATION_MESSAGE); System.exit(0);
case "New Game": newGame(); break;
case "Swap Colors": swapColors(); break;
case "High Scores": try { displayScores(); } catch (Exception e1) { System.out.println(e1.getMessage()); } break;
case "Save Score": try { saveScore(); } catch (Exception e2) { System.out.println(e2.getMessage()); } break;
}
}
}
//==========================================================
public void paint(Graphics g) {
super.paint(g);
for(Ball b : balls) {
b.draw(g);
}
for(Paddle p : horizPaddles) {
p.draw((Graphics2D) g);
}
for(Paddle p : vertPaddles) {
p.draw((Graphics2D) g);
}
}
//==========================================================
//FIX FOR DISPLAYING SCORES
private void displayScores() throws Exception {
}
//==========================================================
//FIX -- Store Score in a File
private void saveScore() throws Exception {
int userScore = score;
String name = JOptionPane.showInputDialog("Enter Your Name: ");
JOptionPane.showMessageDialog(null, "Saved!\n" + name + " scored " + userScore, "Score Recorded", JOptionPane.INFORMATION_MESSAGE);
}
//==========================================================
private void swapColors() {
for(Ball b : balls) {
if(b.color.equals(Color.red)) {
b.setColor(Color.yellow);
} else if (b.color.equals(Color.yellow)) {
b.setColor(Color.blue);
} else {
b.setColor(Color.red);
}
}
}
//==========================================================
private void newGame() {
//CREATE BALL
balls.clear();
b = new Ball();
b.color = Color.red;
b.dx = (int)(Math.random() * 4) + 1;
b.dy = (int)(Math.random() * 4) + 1;
b.xPos = (int)(Math.random() * 4) + 1;
b.yPos = (int)(Math.random() * 4) + 1;
balls.add(b);
//CREATE PADDLES
horizPaddles.clear();
vertPaddles.clear();
// bottom
pBottom = new Paddle();
pBottom.x = getWidth() / 2;
pBottom.y = getHeight();
pBottom.setX(pBottom.getX()-20);
pBottom.setY(pBottom.getY()-20);
pBottom.setWidth(100);
pBottom.setHeight(20);
horizPaddles.add(pBottom);
//top
pTop = new Paddle();
pTop.x = getWidth() / 2;
pTop.y = getHeight();
pTop.setX(0 + pTop.getX());
pTop.setY(0);
pTop.setWidth(100);
pTop.setHeight(20);
horizPaddles.add(pTop);
//left
pLeft = new Paddle();
pLeft.x = getWidth() / 2;
pLeft.y = getHeight();
pLeft.setX(0);
pLeft.setY(pLeft.getY() / 2);
pLeft.setWidth(20);
pLeft.setHeight(100);
vertPaddles.add(pLeft);
//right
pRight = new Paddle();
pRight.x = getWidth() / 2;
pRight.y = getHeight();
pRight.setX(875);
pRight.setY(pRight.getY() / 2);
pRight.setWidth(20);
pRight.setHeight(100);
vertPaddles.add(pRight);
timer.start();
}
//==========================================================
public class ActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
update();
}
}
//==========================================================
public class MouseMoved implements MouseMotionListener {
#Override
public void mouseMoved(MouseEvent e) {
for(Paddle p : horizPaddles) {
p.x = e.getX();
}
for(Paddle p : vertPaddles) {
p.y = e.getY();
}
}
#Override public void mouseDragged(MouseEvent e) {}
}
}
Paddle Class
import java.awt.Color;
import java.awt.Graphics2D;
public class Paddle implements Drawable{
public int x, y, width, height;
public Paddle() {
super();
}
public Paddle(int x, int y, int width, int height) {
super();
setX(x);
setY(y);
setWidth(width);
setHeight(height);
}
#Override
public void draw(Graphics2D g) {
g.setColor(Color.green);
g.fillRect(x, y, width, height);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
Ball Class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.swing.JPanel;
public class Ball implements Comparable<Ball>, Cloneable{
private static int count = 0;
public static final int NAME_LENGTH = 20;
public String name = "";
public int xPos=0, yPos=0, dx = 3, dy = 2;
public Color color = Color.red;
public static void resetCounter() { count = 0; }
public Ball() {name = "Rock: " + ++count;}
public Ball(RandomAccessFile file) {
load(file);
}
public void load(RandomAccessFile file) {
try {
xPos = file.readInt();
yPos = file.readInt();
dx = file.readInt();
dy = file.readInt();
color = new Color( file.readInt() );
byte[] n = new byte[NAME_LENGTH];
file.readFully(n);
name = new String(n).trim();
System.out.println(name);
} catch (IOException e) {
e.printStackTrace();
}
}
public void save(RandomAccessFile file) {
try {
file.writeInt(xPos);
file.writeInt(yPos);
file.writeInt(dx);
file.writeInt(dy);
file.writeInt(color.getRGB());
file.writeBytes( getStringBlock(name, NAME_LENGTH) );
} catch (IOException e) {
e.printStackTrace();
}
}
private String getStringBlock(String string, int len) {
StringBuilder sb = new StringBuilder(name);
sb.setLength(len);
return sb.toString();
}
public void draw(Graphics g) {
g.setColor(color);
g.fillOval(xPos, yPos, 25, 25);
g.setColor(Color.black);
g.drawOval(xPos, yPos, 25, 25);
}
public void setColor(Color c) {
color = c;
}
public void move(int width, int height) {
xPos+=dx;
yPos+=dy;
if(xPos + 50 > width) {
xPos = width - 50;
dx = -dx;
}
if(yPos + 50 > height) {
yPos = height - 50;
dy = -dy;
}
if(xPos < 0) {
xPos = 0;
dx = -dx;
}
if(yPos < 0) {
yPos = 0;
dy = -dy;
}
}
#Override
public int compareTo(Ball arg0) {
return 0;
}
public int getxPos() {
return xPos;
}
public int getyPos() {
return yPos;
}
}
Thanks again...
For the Paddle-Ball collisions, I think calling this method on a timer might suffice:
public void checkPaddleCollisions(){
Rectangle a = new Rectangle(pTop.getX(), pTop.getY(), pTop.getWidth(), pTop.getHeight());
Rectangle b = ... //Do this for all the paddles.
Rectangle ball = new Rectangle(ball.getX(), ball.getY(), ball.getWidth(), ball.getHeight());
if(a.intersects(ball) || b.intersects(ball) || c.intersects(ball) || d.intersects(ball)){
//Increment score and bounce ball.
}
}
As for collisions with the edge, I think you could do something similar, just create 4 rectangles representing the edges of the screen.
Currently, I am using the following code to drag and move my undecordated JFrames.
private void initialiseGUI(Component component){
//<editor-fold defaultstate="collapsed" desc="code">
component.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
posX = e.getX();
posY = e.getY();
}
});
component.addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent evt) {
//sets frame position when mouse dragged
Rectangle rectangle = getBounds();
getGUI().setBounds(evt.getXOnScreen() - posX, evt.getYOnScreen() - posY, rectangle.width, rectangle.height);
}
});
//</editor-fold>
}
What must I write so that the user can resize it like a decorated window, by dragging the side?
You can check out mr Rob Camick's ComponentResizer class. Pretty simple and straight forward to use.
Just instantiate the ComponentResizer and register the frame with something like:
JFrame frame = new JFrame();
ComponentResizer cr = new ComponentResizer();
cr.registerComponent(frame);
cr.setSnapSize(new Dimension(10, 10));
cr.setMaximumSize(new Dimension(...));
cr.setMinimumSize(new Dimension(...));
Here's a complete example of using the class
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class UndecoratedExample {
private JFrame frame = new JFrame();
class MainPanel extends JPanel {
public MainPanel() {
setBackground(Color.gray);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
class BorderPanel extends JPanel {
private JLabel label;
int pX, pY;
public BorderPanel() {
label = new JLabel(" X ");
label.setOpaque(true);
label.setBackground(Color.RED);
label.setForeground(Color.WHITE);
setBackground(Color.black);
setLayout(new FlowLayout(FlowLayout.RIGHT));
add(label);
label.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
});
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
// Get x,y and store them
pX = me.getX();
pY = me.getY();
}
public void mouseDragged(MouseEvent me) {
frame.setLocation(frame.getLocation().x + me.getX() - pX,
frame.getLocation().y + me.getY() - pY);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent me) {
frame.setLocation(frame.getLocation().x + me.getX() - pX,
frame.getLocation().y + me.getY() - pY);
}
});
}
}
class OutsidePanel extends JPanel {
public OutsidePanel() {
setLayout(new BorderLayout());
add(new MainPanel(), BorderLayout.CENTER);
add(new BorderPanel(), BorderLayout.PAGE_START);
setBorder(new LineBorder(Color.BLACK, 5));
}
}
private void createAnsShowGui() {
ComponentResizer cr = new ComponentResizer();
cr.setMinimumSize(new Dimension(300, 300));
cr.setMaximumSize(new Dimension(800, 600));
cr.registerComponent(frame);
cr.setSnapSize(new Dimension(10, 10));
frame.setUndecorated(true);
frame.add(new OutsidePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new UndecoratedExample().createAnsShowGui();
}
});
}
}
I have recently built my own prototype for this. Maybe you will find this useful.
It uses 2 different components one on top of the other. Unlike Rob Camick's ComponentResizer on which this is inspired, the mouse listeners set to the components in the JFrame will be functional. You will not get the JFrame to capture all the mouse events making it useless to attach listeners to the components in the JFrame. It captures mouse events only when and where a double headed arrow must be displayed.
The key is this method in the top component:
#Override
public boolean contains(int x, int y) {
return x < insets.left || y < insets.top
|| getHeight() - y < insets.bottom
|| getWidth() - x < insets.right;
}
Here is the code:
import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
public class BackgroundComponentDragger implements MouseMotionListener {
private Component controlledComponent;
/*
* Point where cursor was last clicked.
*/
private Point originPoint;
public BackgroundComponentDragger(Component component) {
this.controlledComponent = component;
}
#Override
public void mouseDragged(MouseEvent e) {
Point currentFramePosition = controlledComponent.getLocation();
Point newFramePosition = new Point(currentFramePosition.x + e.getX()
- originPoint.x, currentFramePosition.y + e.getY() - originPoint.y);
controlledComponent.setLocation(newFramePosition);
}
#Override
public void mouseMoved(MouseEvent e) {
originPoint = e.getPoint();
}
}
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.HashMap;
import java.util.Map;
public class ComponentBorderDragger implements MouseMotionListener {
private Component controlledComponent;
private byte direction;
protected static final byte NORTH = 1;
protected static final byte WEST = 2;
protected static final byte SOUTH = 4;
protected static final byte EAST = 8;
private Cursor sourceCursor;
private static Map<Byte, Integer> cursors = new HashMap<Byte, Integer>();
{
cursors.put((byte) 1, Cursor.N_RESIZE_CURSOR);
cursors.put((byte) 2, Cursor.W_RESIZE_CURSOR);
cursors.put((byte) 4, Cursor.S_RESIZE_CURSOR);
cursors.put((byte) 8, Cursor.E_RESIZE_CURSOR);
cursors.put((byte) 3, Cursor.NW_RESIZE_CURSOR);
cursors.put((byte) 9, Cursor.NE_RESIZE_CURSOR);
cursors.put((byte) 6, Cursor.SW_RESIZE_CURSOR);
cursors.put((byte) 12, Cursor.SE_RESIZE_CURSOR);
}
private Insets dragInsets;
private Dimension minSize;
private Point basePoint;
public ComponentBorderDragger(Component controlledComponent, Insets dragInsets,
Dimension minSize) {
super();
this.controlledComponent = controlledComponent;
this.dragInsets = dragInsets;
this.minSize = minSize;
}
#Override
public void mouseDragged(MouseEvent e) {
if (direction == 0) {
return;
}
Point newPoint = e.getPoint();
int x, y, width, height, newBasePointX, newBasePointY;
x = controlledComponent.getX();
y = controlledComponent.getY();
width = controlledComponent.getWidth();
height = controlledComponent.getHeight();
newBasePointX = newPoint.x;
newBasePointY = newPoint.y;
if ((direction & EAST) == EAST) {
int newWidth;
newWidth = Math.max(minSize.width, width + newPoint.x
- basePoint.x);
width = newWidth;
}
if ((direction & SOUTH) == SOUTH) {
int novoAlto;
novoAlto = Math.max(minSize.height, height + newPoint.y
- basePoint.y);
height = novoAlto;
}
if ((direction & WEST) == WEST) {
int newWidth, newX;
newWidth = Math.max(minSize.width, width - newPoint.x
+ basePoint.x);
newX = Math.min(x + width - minSize.width, x + newPoint.x
- basePoint.x);
// Changing coordenates of new base point to refer to the new component position
newBasePointX -= newX - x;
x = newX;
width = newWidth;
}
if ((direction & NORTH) == NORTH) {
int newHeigth, newY;
newHeigth = Math.max(minSize.height, height - newPoint.y
+ basePoint.y);
newY = Math.min(y + height - minSize.height, y + newPoint.y
- basePoint.y);
// Changing coordenates of new base point to refer to the new component position
newBasePointY -= newY - y;
y = newY;
height = newHeigth;
}
controlledComponent.setBounds(x, y, width, height);
basePoint = new Point(newBasePointX, newBasePointY);
}
#Override
public void mouseMoved(MouseEvent e) {
Component originator = e.getComponent();
if (direction == 0) {
sourceCursor = originator.getCursor();
}
calculateDirection(e.getPoint(), e.getComponent().getSize());
setCursor(e.getComponent());
basePoint = e.getPoint();
}
private void setCursor(Component component) {
if (direction == 0) {
component.setCursor(sourceCursor);
} else {
int cursorType = cursors.get(direction);
Cursor cursor = Cursor.getPredefinedCursor(cursorType);
component.setCursor(cursor);
}
}
private void calculateDirection(Point point, Dimension componentSize) {
direction = 0;
if (point.x < dragInsets.left) {
direction |= WEST;
}
if (point.y < dragInsets.top) {
direction |= NORTH;
}
if (point.x > componentSize.width - dragInsets.right) {
direction |= EAST;
}
if (point.y > componentSize.height - dragInsets.bottom) {
direction |= SOUTH;
}
}
}
import java.awt.Insets;
import javax.swing.JComponent;
public class FrameComponent extends JComponent {
private static final long serialVersionUID = 3383070502274306213L;
private Insets insets;
#Override
public boolean contains(int x, int y) {
return x < insets.left || y < insets.top || getHeight() - y < insets.bottom || getWidth() - x < insets.right;
}
public FrameComponent(Insets insets) {
this.insets = insets;
}
}
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI {
private JFrame compoundFrame;
private JPanel backgroundPanel;
Dimension gUISize = new Dimension(400, 400);
public GUI() {
buildResizeableFrame();
}
public void activate() {
compoundFrame.setVisible(true);
}
private void buildResizeableFrame() {
compoundFrame = new JFrame();
FrameComponent frame = new FrameComponent(new Insets(5, 5, 5, 5));
backgroundPanel = new JPanel();
compoundFrame.setLayout(null);
compoundFrame.add(frame);
compoundFrame.add(backgroundPanel);
setFrameSizeController(frame, backgroundPanel);
setFrameController(frame);
setBackgroundPanelController(backgroundPanel);
Dimension dimPant = Toolkit.getDefaultToolkit().getScreenSize();
compoundFrame.setBounds(dimPant.width / 4, dimPant.height / 4, dimPant.width / 2, dimPant.height / 2);
compoundFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
compoundFrame.setUndecorated(true);
}
private void setFrameSizeController(FrameComponent frame, JPanel panel) {
compoundFrame.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
Dimension sizeIn = ((JFrame) e.getComponent()).getContentPane().getSize();
frame.setSize(sizeIn);
panel.setSize(sizeIn);
}
});
}
private void setFrameController(FrameComponent frame) {
ComponentBorderDragger controller = new ComponentBorderDragger(compoundFrame,
new Insets(5, 5, 5, 5), new Dimension(10, 10));
frame.addMouseMotionListener(controller);
}
private void setBackgroundPanelController(JPanel panel) {
panel.addMouseMotionListener(new BackgroundComponentDragger(compoundFrame));
}
public static void main(String[] args) {
new GUI().activate();
}
}
Note: This code sets a null LayoutManager and a listener to the container to resize the inner component when needed. This practice is discouraged. This logic should be moved to a custom layout manager.
Add this to your frame after selecting "undecorated" option (below uses a jbutton from the main menu to open a new undecorated input form called PlumbingPRO that has a border and is draggable). I would add this to MAIN Method or at the class that has the "initComponents();" at the beginning of the java file if using within the main form. If using for a follow-on form, the below should work from the button selection. Make sure you do your "imports" for the below actions (BorderFactory, FrameDragListener, addmouselistener, addMouseMotionListener) in the form that has the button selection and not the follow-on form.
private void jbtn_PLUMBINGActionPerformed(java.awt.event.ActionEvent evt) {
PlumbingPRO frame = new PlumbingPRO();
frame.getRootPane().setBorder(BorderFactory.createMatteBorder(3, 3, 3, 3,
Color.DARK_GRAY));
FrameDragListener frameDragListener = new FrameDragListener(frame );
frame.addMouseListener(frameDragListener);
frame.addMouseMotionListener(frameDragListener);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
You might want to try this, but you need to add a functionality to close the window.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Map.Entry;
import javax.swing.*;
public class AppWindow extends JFrame {
Map<Boolean, String> mousePoint;
private String direction;
public AppWindow() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 570, 337);
setUndecorated(true);
getContentPane().setBackground(new Color(33, 115, 70));
getContentPane().setLayout(null);
setLocationRelativeTo(null);
setVisible(true);
setMinimumSize(new Dimension(100, 100));
getContentPane().addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
mousePoint = new HashMap<Boolean, String>();
mousePoint.put(e.getY() < 5, "N");
mousePoint.put(e.getX() > (getWidth() - 5), "E");
mousePoint.put(e.getY() > (getHeight() - 5), "S");
mousePoint.put(e.getX() < 5, "W");
mousePoint.put(e.getY() < 5 && e.getX() > (getWidth() - 5), "NE");
mousePoint.put(e.getY() > (getHeight() - 5) && e.getX() > (getWidth() - 5), "SE");
mousePoint.put(e.getY() > (getHeight() - 5) && e.getX() <= 5, "SW");
mousePoint.put(e.getY() < 5 && e.getX() < 5, "NW");
for (Entry<Boolean, String> item : mousePoint.entrySet()) {
if (item.getKey()) {
direction = item.getValue();
switch (item.getValue()) {
case "N":
setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
break;
case "E":
setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
break;
case "S":
setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
break;
case "W":
setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
break;
case "NE":
setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
break;
case "SE":
setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
break;
case "SW":
setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
break;
case "NW":
setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
break;
}
} else {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (!getCursor().equals(Cursor.getDefaultCursor())) {
switch (direction) {
case "N":
if (e.getYOnScreen() > getY()) {
setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() - (e.getYOnScreen() - getY()));
} else {
setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() + (getY() - e.getYOnScreen()));
}
break;
case "E":
setBounds(getX(), getY(), e.getX(), getHeight());
break;
case "S":
setBounds(getX(), getY(), getWidth(), e.getY());
break;
case "W":
if (e.getXOnScreen() > getX()) {
setBounds(e.getXOnScreen(), getY(), getWidth() - (e.getXOnScreen() - getX()), getHeight());
} else {
setBounds(e.getXOnScreen(), getY(), getWidth() + (getX() - e.getXOnScreen()), getHeight());
}
break;
case "NE":
setBounds(getX(), getY(), e.getX(), getHeight());
if (e.getYOnScreen() > getY()) {
setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() - (e.getYOnScreen() - getY()));
} else {
setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() + (getY() - e.getYOnScreen()));
}
break;
case "SE":
setBounds(getX(), getY(), e.getX(), e.getY());
break;
case "SW":
setBounds(getX(), getY(), getWidth(), e.getY());
if (e.getXOnScreen() > getX()) {
setBounds(e.getXOnScreen(), getY(), getWidth() - (e.getXOnScreen() - getX()), getHeight());
} else {
setBounds(e.getXOnScreen(), getY(), getWidth() + (getX() - e.getXOnScreen()), getHeight());
}
break;
case "NW":
if (e.getYOnScreen() > getY()) {
setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() - (e.getYOnScreen() - getY()));
} else {
setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() + (getY() - e.getYOnScreen()));
}
if (e.getXOnScreen() > getX()) {
setBounds(e.getXOnScreen(), getY(), getWidth() - (e.getXOnScreen() - getX()), getHeight());
} else {
setBounds(e.getXOnScreen(), getY(), getWidth() + (getX() - e.getXOnScreen()), getHeight());
}
break;
}
}
}
});
}
}
I'm starting to learn java programming and I think it's cool to learn java through game development. I know how to draw image and listen to a keypress then move that image. But is it possible to make the image move back and forth to the window while the window is listening to a keypress? Like for example, while the image or object(like spaceship) is moving left to right in the window, then if I press space key, a laser will fire at the bottom of the screen( cool huh :D ). But basically I just want to know how to make the image move left to right while the window is listening to a keypress.
I'm thinking that I will add a key listener to my window then fire an infinite loop to move the image. Or do I need to learn about threading so that another thread will move the object?
Please advise.
Many thanks.
Yep, a Swing Timer and Key Bindings would work well. Here's another example (mine) :)
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class AnimationWithKeyBinding {
private static void createAndShowUI() {
AnimationPanel panel = new AnimationPanel(); // the drawing JPanel
JFrame frame = new JFrame("Animation With Key Binding");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
#SuppressWarnings("serial")
class AnimationPanel extends JPanel {
public static final int SPRITE_WIDTH = 20;
public static final int PANEL_WIDTH = 400;
public static final int PANEL_HEIGHT = 400;
private static final int MAX_MSTATE = 25;
private static final int SPIN_TIMER_PERIOD = 16;
private static final int SPRITE_STEP = 3;
private int mState = 0;
private int mX = (PANEL_WIDTH - SPRITE_WIDTH) / 2;
private int mY = (PANEL_HEIGHT - SPRITE_WIDTH) / 2;
private int oldMX = mX;
private int oldMY = mY;
private boolean moved = false;
// an array of sprite images that are drawn sequentially
private BufferedImage[] spriteImages = new BufferedImage[MAX_MSTATE];
public AnimationPanel() {
// create and start the main animation timer
new Timer(SPIN_TIMER_PERIOD, new SpinTimerListener()).start();
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
setBackground(Color.white);
createSprites(); // create the images
setupKeyBinding();
}
private void setupKeyBinding() {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inMap = getInputMap(condition);
ActionMap actMap = getActionMap();
// this uses an enum of Direction that holds ints for the arrow keys
for (Direction direction : Direction.values()) {
int key = direction.getKey();
String name = direction.name();
// add the key bindings for arrow key and shift-arrow key
inMap.put(KeyStroke.getKeyStroke(key, 0), name);
inMap.put(KeyStroke.getKeyStroke(key, InputEvent.SHIFT_DOWN_MASK), name);
actMap.put(name, new MyKeyAction(this, direction));
}
}
// create a bunch of buffered images and place into an array,
// to be displayed sequentially
private void createSprites() {
for (int i = 0; i < spriteImages.length; i++) {
spriteImages[i] = new BufferedImage(SPRITE_WIDTH, SPRITE_WIDTH,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = spriteImages[i].createGraphics();
g2.setColor(Color.red);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double theta = i * Math.PI / (2 * spriteImages.length);
double x = SPRITE_WIDTH * Math.abs(Math.cos(theta)) / 2.0;
double y = SPRITE_WIDTH * Math.abs(Math.sin(theta)) / 2.0;
int x1 = (int) ((SPRITE_WIDTH / 2.0) - x);
int y1 = (int) ((SPRITE_WIDTH / 2.0) - y);
int x2 = (int) ((SPRITE_WIDTH / 2.0) + x);
int y2 = (int) ((SPRITE_WIDTH / 2.0) + y);
g2.drawLine(x1, y1, x2, y2);
g2.drawLine(y1, x2, y2, x1);
g2.dispose();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(spriteImages[mState], mX, mY, null);
}
public void incrementX(boolean right) {
oldMX = mX;
if (right) {
mX = Math.min(getWidth() - SPRITE_WIDTH, mX + SPRITE_STEP);
} else {
mX = Math.max(0, mX - SPRITE_STEP);
}
moved = true;
}
public void incrementY(boolean down) {
oldMY = mY;
if (down) {
mY = Math.min(getHeight() - SPRITE_WIDTH, mY + SPRITE_STEP);
} else {
mY = Math.max(0, mY - SPRITE_STEP);
}
moved = true;
}
public void tick() {
mState = (mState + 1) % MAX_MSTATE;
}
private class SpinTimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
tick();
int delta = 20;
int width = SPRITE_WIDTH + 2 * delta;
int height = width;
// make sure to erase the old image
if (moved) {
int x = oldMX - delta;
int y = oldMY - delta;
repaint(x, y, width, height);
}
int x = mX - delta;
int y = mY - delta;
// draw the new image
repaint(x, y, width, height);
moved = false;
}
}
}
enum Direction {
UP(KeyEvent.VK_UP), DOWN(KeyEvent.VK_DOWN), LEFT(KeyEvent.VK_LEFT), RIGHT(KeyEvent.VK_RIGHT);
private int key;
private Direction(int key) {
this.key = key;
}
public int getKey() {
return key;
}
}
// Actions for the key binding
#SuppressWarnings("serial")
class MyKeyAction extends AbstractAction {
private AnimationPanel draw;
private Direction direction;
public MyKeyAction(AnimationPanel draw, Direction direction) {
this.draw = draw;
this.direction = direction;
}
#Override
public void actionPerformed(ActionEvent e) {
switch (direction) {
case UP:
draw.incrementY(false);
break;
case DOWN:
draw.incrementY(true);
break;
case LEFT:
draw.incrementX(false);
break;
case RIGHT:
draw.incrementX(true);
break;
default:
break;
}
}
}
Here is another example that uses this sprite sheet:
obtained from this site.
Again it's an example of drawing within a JPanel's paintComponent method and using Key Bindings to tell which direction to move.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class Mcve3 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 640;
private static final int TIMER_DELAY = 50;
private int spriteX = 400;
private int spriteY = 320;
private SpriteDirection spriteDirection = SpriteDirection.RIGHT;
private MySprite sprite = null;
private Timer timer = null;
public Mcve3() {
try {
sprite = new MySprite(spriteDirection, spriteX, spriteY);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
setBackground(Color.WHITE);
setKeyBindings(SpriteDirection.LEFT, KeyEvent.VK_LEFT);
setKeyBindings(SpriteDirection.RIGHT, KeyEvent.VK_RIGHT);
setKeyBindings(SpriteDirection.FORWARD, KeyEvent.VK_DOWN);
setKeyBindings(SpriteDirection.AWAY, KeyEvent.VK_UP);
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
private void setKeyBindings(SpriteDirection dir, int keyCode) {
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
KeyStroke keyPressed = KeyStroke.getKeyStroke(keyCode, 0, false);
KeyStroke keyReleased = KeyStroke.getKeyStroke(keyCode, 0, true);
inputMap.put(keyPressed, keyPressed.toString());
inputMap.put(keyReleased, keyReleased.toString());
actionMap.put(keyPressed.toString(), new MoveAction(dir, false));
actionMap.put(keyReleased.toString(), new MoveAction(dir, true));
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
sprite.draw(g);
}
private class MoveAction extends AbstractAction {
private SpriteDirection dir;
private boolean released;
public MoveAction(SpriteDirection dir, boolean released) {
this.dir = dir;
this.released = released;
}
#Override
public void actionPerformed(ActionEvent e) {
if (released) {
sprite.setMoving(false);
} else {
sprite.setMoving(true);
sprite.setDirection(dir);
}
}
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (sprite.isMoving()) {
sprite.tick();
}
repaint();
}
}
private static void createAndShowGui() {
Mcve3 mainPanel = new Mcve3();
JFrame frame = new JFrame("MCVE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MySprite {
private static final String SPRITE_SHEET_PATH = "http://"
+ "orig12.deviantart.net/7db3/f/2010/338/3/3/"
+ "animated_sprite_sheet_32x32_by_digibody-d3479l2.gif";
private static final int MAX_MOVING_INDEX = 4;
private static final int DELTA = 4;
private SpriteDirection direction;
private Map<SpriteDirection, Image> standingImgMap = new EnumMap<>(SpriteDirection.class);
private Map<SpriteDirection, List<Image>> movingImgMap = new EnumMap<>(SpriteDirection.class);
private int x;
private int y;
private boolean moving = false;
private int movingIndex = 0;
public MySprite(SpriteDirection direction, int x, int y) throws IOException {
this.direction = direction;
this.x = x;
this.y = y;
createSprites();
}
public void draw(Graphics g) {
Image img = null;
if (!moving) {
img = standingImgMap.get(direction);
} else {
img = movingImgMap.get(direction).get(movingIndex);
}
g.drawImage(img, x, y, null);
}
private void createSprites() throws IOException {
URL spriteSheetUrl = new URL(SPRITE_SHEET_PATH);
BufferedImage img = ImageIO.read(spriteSheetUrl);
// get sub-images (sprites) from the sprite sheet
// magic numbers for getting sprites from sheet, all obtained by trial and error
int x0 = 0;
int y0 = 64;
int rW = 32;
int rH = 32;
for (int row = 0; row < 4; row++) {
SpriteDirection dir = SpriteDirection.values()[row];
List<Image> imgList = new ArrayList<>();
movingImgMap.put(dir, imgList);
int rY = y0 + row * rH;
for (int col = 0; col < 5; col++) {
int rX = x0 + col * rW;
BufferedImage subImg = img.getSubimage(rX, rY, rW, rH);
if (col == 0) {
// first image is standing
standingImgMap.put(dir, subImg);
} else {
// all others are moving
imgList.add(subImg);
}
}
}
}
public SpriteDirection getDirection() {
return direction;
}
public void setDirection(SpriteDirection direction) {
if (this.direction != direction) {
setMoving(false);
}
this.direction = direction;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public boolean isMoving() {
return moving;
}
public void setMoving(boolean moving) {
this.moving = moving;
if (!moving) {
movingIndex = 0;
}
}
public void tick() {
if (moving) {
switch (direction) {
case RIGHT:
x += DELTA;
break;
case LEFT:
x -= DELTA;
break;
case FORWARD:
y += DELTA;
break;
case AWAY:
y -= DELTA;
}
movingIndex++;
movingIndex %= MAX_MOVING_INDEX;
}
}
public int getMovingIndex() {
return movingIndex;
}
public void setMovingIndex(int movingIndex) {
this.movingIndex = movingIndex;
}
}
enum SpriteDirection {
FORWARD, LEFT, AWAY, RIGHT
}
As an alternative to KeyListener, consider using actions and key bindings, discussed here. Derived from this example, the program below moves a line left, down, up or right using either buttons or keys.
import java.awt.BasicStroke;
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.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
/**
* #see https://stackoverflow.com/questions/6991648
* #see https://stackoverflow.com/questions/6887296
* #see https://stackoverflow.com/questions/5797965
*/
public class LinePanel extends JPanel {
private MouseHandler mouseHandler = new MouseHandler();
private Point p1 = new Point(100, 100);
private Point p2 = new Point(540, 380);
private boolean drawing;
public LinePanel() {
this.setPreferredSize(new Dimension(640, 480));
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.blue);
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(8,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
g.drawLine(p1.x, p1.y, p2.x, p2.y);
}
private class MouseHandler extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
drawing = true;
p1 = e.getPoint();
p2 = p1;
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
drawing = false;
p2 = e.getPoint();
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
p2 = e.getPoint();
repaint();
}
}
}
private class ControlPanel extends JPanel {
private static final int DELTA = 10;
public ControlPanel() {
this.add(new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0));
this.add(new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA));
this.add(new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0));
this.add(new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA));
}
private class MoveButton extends JButton {
KeyStroke k;
int dx, dy;
public MoveButton(String name, int code, final int dx, final int dy) {
super(name);
this.k = KeyStroke.getKeyStroke(code, 0);
this.dx = dx;
this.dy = dy;
this.setAction(new AbstractAction(this.getText()) {
#Override
public void actionPerformed(ActionEvent e) {
LinePanel.this.p1.translate(dx, dy);
LinePanel.this.p2.translate(dx, dy);
LinePanel.this.repaint();
}
});
ControlPanel.this.getInputMap(
WHEN_IN_FOCUSED_WINDOW).put(k, k.toString());
ControlPanel.this.getActionMap().put(k.toString(), new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
MoveButton.this.doClick();
}
});
}
}
}
private void display() {
JFrame f = new JFrame("LinePanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.add(new ControlPanel(), BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new LinePanel().display();
}
});
}
}
But basically I just want to know how to make the image move left to right while the window is listening to a keypress
You can use a Swing Timer to animate an image:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TimerAnimation extends JLabel implements ActionListener
{
int deltaX = 2;
int deltaY = 3;
int directionX = 1;
int directionY = 1;
public TimerAnimation(
int startX, int startY,
int deltaX, int deltaY,
int directionX, int directionY,
int delay)
{
this.deltaX = deltaX;
this.deltaY = deltaY;
this.directionX = directionX;
this.directionY = directionY;
setIcon( new ImageIcon("dukewavered.gif") );
// setIcon( new ImageIcon("copy16.gif") );
setSize( getPreferredSize() );
setLocation(startX, startY);
new javax.swing.Timer(delay, this).start();
}
public void actionPerformed(ActionEvent e)
{
Container parent = getParent();
// Determine next X position
int nextX = getLocation().x + (deltaX * directionX);
if (nextX < 0)
{
nextX = 0;
directionX *= -1;
}
if ( nextX + getSize().width > parent.getSize().width)
{
nextX = parent.getSize().width - getSize().width;
directionX *= -1;
}
// Determine next Y position
int nextY = getLocation().y + (deltaY * directionY);
if (nextY < 0)
{
nextY = 0;
directionY *= -1;
}
if ( nextY + getSize().height > parent.getSize().height)
{
nextY = parent.getSize().height - getSize().height;
directionY *= -1;
}
// Move the label
setLocation(nextX, nextY);
}
public static void main(String[] args)
{
JPanel panel = new JPanel();
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().setLayout(null);
// frame.getContentPane().add( new TimerAnimation(10, 10, 2, 3, 1, 1, 10) );
frame.getContentPane().add( new TimerAnimation(300, 100, 3, 2, -1, 1, 20) );
// frame.getContentPane().add( new TimerAnimation(0, 000, 5, 0, 1, 1, 20) );
frame.getContentPane().add( new TimerAnimation(0, 200, 5, 0, 1, 1, 80) );
frame.setSize(400, 400);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
// frame.getContentPane().add( new TimerAnimation(10, 10, 2, 3, 1, 1, 10) );
// frame.getContentPane().add( new TimerAnimation(10, 10, 3, 0, 1, 1, 10) );
}
}
You can add a KeyListener to the panel and it will operate independently of the image animation.