I tried to make any Component draggable by simply adding mouse listeners and using the setLocation function of java.awt.Component. I started with JButton to test if it were possible the way i thought.
Here is a code example for what I am trying to do:
import java.awt.*;
import javax.swing.*;
public class DragButton extends JButton{
private volatile int draggedAtX, draggedAtY;
public DragButton(String text){
super(text);
setDoubleBuffered(false);
setMargin(new Insets(0, 0, 0, 0));
setSize(25, 25);
setPreferredSize(new Dimension(25, 25));
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
draggedAtX = e.getX() - getLocation().x;
draggedAtY = e.getY() - getLocation().y;
}
});
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
setLocation(e.getX() - draggedAtX, e.getY() - draggedAtY);
}
});
}
public static void main(String[] args){
JFrame frame = new JFrame("DragButton");
frame.setLayout(null);
frame.getContentPane().add(new DragButton("1"));
frame.getContentPane().add(new DragButton("2"));
frame.getContentPane().add(new DragButton("3"));
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Somehow this fails to work properly and I don't get why. The actual distance dragged is half the distance of the mouse movement and it flickers around that distance while dragging as if two mouse positions are competing over the MouseMotionListener.
May anyone help a swing/awt noob? =)
Many thanks in advance.
Edit:
Ok, so the problem was that I did not know that the event would refire at each mouse location with the position being relative(!) to the firing JComponent. So this is the corrected and working code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragButton extends JButton{
private volatile int draggedAtX, draggedAtY;
public DragButton(String text){
super(text);
setDoubleBuffered(false);
setMargin(new Insets(0, 0, 0, 0));
setSize(25, 25);
setPreferredSize(new Dimension(25, 25));
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
draggedAtX = e.getX();
draggedAtY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
setLocation(e.getX() - draggedAtX + getLocation().x,
e.getY() - draggedAtY + getLocation().y);
}
});
}
public static void main(String[] args){
JFrame frame = new JFrame("DragButton");
frame.setLayout(null);
frame.getContentPane().add(new DragButton("1"));
frame.getContentPane().add(new DragButton("2"));
frame.getContentPane().add(new DragButton("3"));
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Thanks Adel for your efforts and mKorbel for the link.
You have to move with JComponent, I miss this definitions in voids mousePressed/mouseDragged; in other hands, there nothing better around as #[camickr][1] excellent code for ComponentMover.
import javax.swing.*;
import java.awt.event.*;
public class movingButton extends JFrame{
private JButton button ;
public movingButton ()
{
super("Position helper");
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.setSize(500,520);
super.setVisible(true);
super.setLayout(null);
button = new JButton ("drag me ");
add(button);
button.setBounds(100, 100, 150, 40);
button.addMouseMotionListener(new MouseAdapter(){
public void mouseDragged(MouseEvent E)
{
int X=E.getX()+button.getX();
int Y=E.getY()+button.getY;
button.setBounds(X,Y,150,40);
}
});
}
public static void main (String x[])
{
new movingButton();
}
}
Why don't you use the java Transferable interface instead?
Here's a tutorial on how to do it:
http://www.javaworld.com/javaworld/jw-03-1999/jw-03-dragndrop.html
It is better if you would do
int X=E.getX() + button.getX();
int Y=E.getY() + button.getY();
Related
I'm learning basics of Java Applet and Swings. I'm trying a simple code. I want to change the color of my panel when a button is clicked. Here's the code:
SimpleGui.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleGui implements ActionListener {
JFrame frame;
JButton button;
public static void main(String[] args) {
SimpleGui gui = new SimpleGui();
gui.go();
}
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button = new JButton("changes colour");
button.addActionListener(this);
MyPanel drawPanel = new MyPanel();
frame.getContentPane().add(BorderLayout.SOUTH,button);
frame.getContentPane().add(BorderLayout.CENTER,drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
}
//event handling method
public void actionPerformed(ActionEvent event) {
frame.repaint();
button.setText("color changed");
}
}
class MyPanel extends JPanel {
public void paintCompenent(Graphics g) {
g.setColor(Color.green);
g.fillRect(20, 50, 100, 100);
}
}
I added some println statements to debug and I found out that paintComponent method is not called. Can you please correct me. Where I am making mistake. Is my entire implementation is wrong?
paintComponent must be protected (see here).
change your code to :
class MyPanel extends JPanel {
protected void paintComponent(Graphics g) {
g.setColor(Color.green);
g.fillRect(20, 50, 100, 100);
}
}
Result:
I am trying to get the mouse coordinates display in the panel but each time I move the cursor the message and new coordinates are being displayed on the previous one.I am using MouseMotionListener with JPanel. I can't figure out the problem.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.event.MouseMotionListener;
public class Main extends JPanel implements MouseMotionListener {
public JLabel label;
public static void main(String[] args) {
new Main();
JFrame frame = new JFrame();
frame.setTitle("MouseCoordinates");
frame.setSize(400, 400);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
Container contentPane = frame.getContentPane();
contentPane.add(new Main());
frame.setVisible(true);
}
public Main() {
setSize(400, 400);
label = new JLabel("No Mouse Event Captured", JLabel.CENTER);
add(label);
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent e) {
label.setText("Mouse Cursor Coordinates => X:" + e.getX() + " |Y:" + e.getY());
}
public void mouseDragged(MouseEvent e) {}
}
You're creating Main twice.
public class Main extends JPanel implements MouseMotionListener {
public JLabel label;
public static void main(String[] args) {
Main m = new Main();// create an object and reference it
JFrame frame = new JFrame();
frame.setTitle("MouseCoordinates");
frame.setSize(400, 400);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
Container contentPane = frame.getContentPane();
contentPane.add(m);
frame.setVisible(true);
}
//...
your problem was creating the Main object twice (which is a jpanel) and then the writing appeared twice. if you give the Main object a reference, then your problem should be fixed.
I am making a custom JFrame. I already have this layout, and it works completely fine:
The frame is undecorated, but I want to be able to move it around. I want my custom panel to be the moving grip for this, so what I did was add a MouseMotionListener to it. The mouseDragged function looks like this:
#Override
public void mouseDragged(MouseEvent e) {
parent.setBounds(e.getX(), e.getY(), parent.getWidth(), parent.getHeight());
}
The parent field is set in the constructor and is final.
When I try to drag the frame with the panel, it works, but not quite right. The frame constantly flickers between two positions on the screen. I am able to move the frame, but it looks horrible. When I don't drag the frame, it doesn't flicker. The two positions are relative to each other, so if you move the frame, the other one moves along (but doesn't stay at the same distance from the other). Another problem is that the frame doesn't move well with the mouse. So, if you move the frame like 100 pixels in the x direction, the frame moves less pixels in the same direction.
How can you make a moving grip for a JFrame without this happening (and what is actually causing it to do this)?
If more code is required, just tell me.
You need to provide a mousePressed also to get the initial point of the click. Then use that point to do some calculations.
Try something like this, where pX and pY are class fields (and assuming listeners are added in the panel constructor
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
// Get x,y and store them
pX = me.getX();
pY = me.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent me) {
parent.setLocation(parent.getLocation().x + me.getX() - pX,
parent.getLocation().y + me.getY() - pY);
}
});
Here's a full example
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();
}
});
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() {
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 want my custom panel to be the moving grip for this,
Check out Moving Windows which contains a class that will allow you to drag a window around the screen or any component around its parent container.
i'm trying to draw a line in a java program but the line has not drawn
i have try every function but still no line on JLable
i don't know why the graphics of JLable does not updated after i draw my line and it's still empty.
help me please
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class t
{
private static JFrame frame;
private static JLabel field;
public static void main(String[] args)
{
frame = new JFrame("Simple Server");
frame.setLayout(new FlowLayout());
frame.setPreferredSize(new Dimension(1200, 700));
frame.setSize(new Dimension(1200, 700));
frame.setMinimumSize(new Dimension(1200, 700));
frame.addWindowListener(new WindowAdapter()
{
#Override
public void windowClosing(WindowEvent we)
{
System.gc();
System.exit(0);
}
});
int maxW = 1000, maxH = 600;
field = new JLabel();
field.setSize(maxW, maxH);
field.setPreferredSize(new Dimension(maxW, maxH));
field.setMaximumSize(new Dimension(maxW, maxH));
field.setMinimumSize(new Dimension(maxW, maxH));
field.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
field.setBackground(Color.GREEN);
field.setOpaque(true);
frame.add(field, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
Graphics g = field.getGraphics();
g.drawLine(0, 0, 100, 100);
field.paintComponents(g);
field.paint(g);
field.paintAll(g);
field.update(g);
field.repaint();
frame.paint(g);
frame.paintAll(g);
frame.paintComponents(g);
frame.update(g);
frame.repaint();
frame.setVisible(true);
}
getGraphics can return null and is, at best, a snapshot of what was painted on the last paint cycle.
While you can use this technique, the next time the component needs to be painted, anything you've painted to it will be erased.
Take a look at Perofrming Custom Painting and Painting in AWT and Swing for more details about how painting works
To be swing graphics conformant, do this:
public class CrossedLabel extends JLabel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, 0, 100, 100);
}
}
Use an infinite while loop and within add the line "g.drawLine(0,0,100,100);" alone and then end the main function. Then a line is visible on screen. Similarly you can use a loop to play an animation until a condition is completed to make it work.
The code should be like this below one :-
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class t implements Runnable
{
private static JFrame frame;
private static JLabel field;
private java.lang.Thread tdr;
t()
{
tdr = new java.lang.Thread(this);
}
public static void main(String[] args)
{
t tsk= new t();
frame = new JFrame("Simple Server");
frame.setLayout(new FlowLayout());
frame.setPreferredSize(new Dimension(1200, 700));
frame.setSize(new Dimension(1200, 700));
frame.setMinimumSize(new Dimension(1200, 700));
frame.addWindowListener(new WindowAdapter()
{
#Override
public void windowClosing(WindowEvent we)
{
System.gc();
System.exit(0);
}
});
int maxW = 1000, maxH = 600;
field = new JLabel();
field.setSize(maxW, maxH);
field.setPreferredSize(new Dimension(maxW, maxH));
field.setMaximumSize(new Dimension(maxW, maxH));
field.setMinimumSize(new Dimension(maxW, maxH));
field.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
field.setBackground(Color.GREEN);
field.setOpaque(true);
frame.add(field, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
Graphics g = field.getGraphics();
while(true)
{
g.drawLine(0, 0, 100, 100);
try{
tsk.tdr.sleep(1000);
}
catch ( Exception e)
{
System.out.println(e.getMessage());
}
System.out.println("Thread started");
}
}
#Override
public void run() {
tdr.start();
}
}
Similarly use some other condition in the while loop instead of true, which would meet until the animation like moving a circle form point a to b is finished.
I am trying to make a JFrame appear on mousePressed Location but I keep failing and it get's annoying :( Any ideas what isn't working?
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class SSCCE
{
#SuppressWarnings("static-access")
public static void getInputData()
{
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.DISPOSE_ON_CLOSE);
JLabel emptyLabel = new JLabel("Test");
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
frame.setSize(new Dimension(375, 100));
MouseAdapter ml = new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent me)
{
frame.setLocation(me.getX(), me.getY());
}
#Override
public void mouseDragged(MouseEvent me)
{
frame.setLocation(me.getX(), me.getY());
}
};
frame.getContentPane().addMouseListener(ml);
frame.getContentPane().addMouseMotionListener(ml);
frame.setVisible(true);
}
public static void main(String args[])
{
JFrame test = new JFrame();
JButton but = new JButton("Click me");
but.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
getInputData();
}
});
test.getContentPane().add(but, BorderLayout.CENTER);
test.setSize(500, 500);
test.setVisible(true);
}
}
Use the SwingUtilities methods convertPointToScreen() and convertPointFromScreen() to transform the MouseEvent coordinates.
Addendum: Alternatively, calculate the offset from getLocationOnScreen(), which is "the component's top-left corner in the screen's coordinate space."
Addendum: To position the new frame relative to the original mouse click, add a mouse listener to the parent frame instead of a button; use the coordinates to position the new frame, as shown below.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SSCCE {
public static void getInputData(MouseEvent e) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("Test", JLabel.CENTER);
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
frame.setPreferredSize(new Dimension(375, 100));
MouseAdapter ma = new MouseAdapter() {
Point local, global;
Point delta = new Point();
#Override
public void mousePressed(MouseEvent me) {
local = me.getPoint();
}
#Override
public void mouseDragged(MouseEvent me) {
delta.setLocation(
me.getX() - local.x, me.getY() - local.y);
global = frame.getLocationOnScreen();
global.setLocation(
global.x + delta.x, global.y + delta.y);
frame.setLocation(global.x, global.y);
}
};
frame.getContentPane().addMouseListener(ma);
frame.getContentPane().addMouseMotionListener(ma);
frame.pack();
frame.setLocation(e.getLocationOnScreen());
frame.setVisible(true);
}
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(640, 480));
frame.add(new JLabel("Click me", JLabel.CENTER));
frame.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
getInputData(e);
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Previously,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SSCCE {
public static void getInputData() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("Test", JLabel.CENTER);
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
frame.setPreferredSize(new Dimension(375, 100));
MouseAdapter ma = new MouseAdapter() {
Point local = new Point();
Point delta = new Point();
Point global = new Point();
#Override
public void mousePressed(MouseEvent me) {
local = me.getPoint();
}
#Override
public void mouseDragged(MouseEvent me) {
delta.setLocation(
me.getX() - local.x,
me.getY() - local.y);
global = frame.getLocationOnScreen();
global.setLocation(global.x + delta.x, global.y + delta.y);
frame.setLocation(global.x, global.y);
}
};
frame.getContentPane().addMouseListener(ma);
frame.getContentPane().addMouseMotionListener(ma);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton but = new JButton("Click me");
but.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
getInputData();
}
});
frame.getContentPane().add(but, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}