-1

Basically, I have a JFrame & in this frame there is a JPanel. On top of panel there are four JLabel components, lets call them colorLabels, and on the bottom of panel I have one label (let's call it playerLabel). I want to implements next thing.

Top colorLabels need to change their color from time to time (less then second) and they need to, let's say, shoot projectiles on bottom. On bottom playerLabel need to be move around x-axis so it can block shots.

My problem is that, when I activate SwingWorker or any thread on colorLabels so they can shoot projectiles and change color overtime my EDT get blocked so I can not move playLabel (event doesn't work). I mean they work but at the same time, playerLabel get back to original position. (EDT blocked)

My question is, how can I split actions on colorLabel (top labels) from action on playerLabel (bottom label)?

How to make colorLabels do their job and to be able to move playerLabel? Basically, How to unblock EDT and still have or actions going.

EDIT:

static Point click;
static int thisX;
static int xMoved;
static int x;
static Integer elapsed = 0;

public static void main(String[] args) {

    JFrame frame = new JFrame();
    SpringLayout sp = new SpringLayout();
    frame.setLayout(sp);

    JLabel label = new JLabel("This is label");
    label.setBorder(BorderFactory.createLineBorder(Color.red));
    JLabel timeLabel = new JLabel("Time: ");

    frame.add(label);
    sp.putConstraint(SpringLayout.NORTH, label, 10, SpringLayout.NORTH, frame);
    sp.putConstraint(SpringLayout.WEST, label, 10, SpringLayout.WEST, frame);

    frame.add(timeLabel);
    sp.putConstraint(SpringLayout.NORTH, timeLabel, 100, SpringLayout.NORTH, frame);
    sp.putConstraint(SpringLayout.WEST, timeLabel, 100, SpringLayout.WEST, frame);

    frame.setSize(600, 400);
    frame.setVisible(true);



     Timer t = new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            elapsed++;
           timeLabel.setText("Time: " + elapsed);
        }
    });


         label.addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            click = e.getPoint();
        }
});

     label.addMouseMotionListener(new MouseAdapter() {
        @Override
        public void mouseDragged(MouseEvent e) {
            thisX = label.getLocation().x;
            xMoved = (thisX + e.getX()) - (thisX + click.x);
            x = thisX + xMoved;
                   label.setLocation(x, label.getLocation().y);
                   label.repaint();       
        }    
});

     t.start();


}
camickr
  • 321,443
  • 19
  • 166
  • 288
toxX
  • 11
  • 4
  • 1
    Do you update your UI components from other threads than EDT? – Ravindra Ranwala Dec 27 '19 at 08:01
  • 1
    It is very difficult to help you since you are not providing any code. – Just another Java programmer Dec 27 '19 at 09:45
  • 1) For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) I think from the description that this is best handled by custom painting each of the elements. 3) I doubt the EDT is actually blocked if all that is happening is that a few labels are changing positions. It seems more like the layout managers are positioning the labels in an unexpected way. – Andrew Thompson Dec 27 '19 at 09:47
  • Yes, I try to update them from another thread than EDT. – toxX Dec 27 '19 at 14:10
  • Well, this colorLabels who change color overtime and shot projectils have fixed postions and I used SwintWorker to change their background. So, I think that because SwingWorker work with colorLabels I mean they are in while loop and that's how they changeing color. That's reason why my EDT is blocked ( I think that ). This SwingWorker do work on EDT and I think that's why I cant move my playerLabel. I dunno how to manage all this – toxX Dec 27 '19 at 14:15
  • 1
    *they are in while loop* - you should NOT be using a while loop. For animation you use a [Swing Timer](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html). The Timer will generate events which will allow you to change the color. The code executes on the EDT so there is no need for a SwingWorker. Check out: https://stackoverflow.com/questions/54028090/get-width-and-height-of-jpanel-outside-of-the-class/54028681#54028681 for a working example. – camickr Dec 27 '19 at 16:24
  • Thx, will check that. Update soon. – toxX Dec 27 '19 at 17:25
  • *"Thx, will check that."* Tip: Add @camickr (or whoever, the `@` is important) to *notify* the person of a new comment. Also, these are not text messages or social media posts. They are comments on a technical forum. Please spell out **all 6** letters of words like 'Thanks'. – Andrew Thompson Dec 28 '19 at 01:54
  • @camickr Sir, I try to use Swing Timer instend SwingWorker (without loop) and still have the same problem. Whole frame get blocked as timer goes on. I try to move my playerLabel and label again get back to original position. I try to turn off timer, with that move my frame get unblocked and I can move around my playerLabel. Is it possible to update GUI (move components around) as timer goes on ? – toxX Dec 28 '19 at 09:43
  • I suspect that we need to see an example (the MRE) of using a `Timer` and `SwingWorker` to be able to help further. I mean me & @camickr (OK this is more his area of expertise!). – Andrew Thompson Dec 28 '19 at 09:57
  • @AndrewThompson I did edit of my post with Timer code and events for moveing playerLabel. I used this Timer for time in my code, when app start there is label which displey time from start. Also this Timer block my move events. I hope you can help me. Thank you for your time. – toxX Dec 28 '19 at 10:28
  • ***Again*** For better help sooner, [edit] to add a **[MCVE]** or **[Short, Self Contained, Correct Example](http://www.sscce.org/)**. Uncompilable code snippets are neither of those. Please follow the links, read carefully, ask if there is anything in either document that is not understood. – Andrew Thompson Dec 28 '19 at 12:10
  • *I try to use Swing Timer* - the code in your Timer does nothing except change the text on a label. Your question is about motion. If you want your projectile to move you need to change the location of the projectile. I gave you a working example that shows how to move a ball around the screen. I have no idea why you posted code related to a mouseDragged event. That has nothing to do with animation of a projectile. *Also this Timer block my move events.* - no it doesn't. – camickr Dec 28 '19 at 15:52
  • @camickr Sir, I updated code with clone of my problem. If you run this code that I post you will see that... when timer start changeing text on this label that represent time, You will not be able to move around label which have listeners to move. That is my problem. Can you help me to solve it, please ? – toxX Dec 29 '19 at 12:10

1 Answers1

1

You will not be able to move around label which have listeners to move.

That is because you are using a layout manager. The layout manager will determine the size/location of the component, even if you manually set the location.

If you need the ability to dynamically move components then you need to add the component to a panel with a null layout. You will then be responsible for setting the initial size/location of the component.

So I would suggest that you:

  1. Uuse the default BorderLayout of the frame.
  2. Add your "text label" to the BorderLayout.PAGE_START.
  3. Add a JPanel with a null layoout to the BorderLayout.CENTER
  4. Add the label you want to drag to the above panel
  5. See the Basic Dragging section from Moving Windows for a simple class that will allow you to drag the label around the panel.
camickr
  • 321,443
  • 19
  • 166
  • 288