Win a copy of Think Java: How to Think Like a Computer Scientist this week in the Java in General forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Can't simultaneously run two threads?

 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey Guys,

I am creating a program which creates two balls (each with their own runnables which control them). This is the important code from the file:

The ControlBallRunnable is here:



To explain this: when the runnable is created, it creates a timer which changes the colour of the ball (using method ball.animate() ) every 1000ms i.e. every second.

Now my problem is this code partially works, it successfully creates one ball (the first time addBall() is called).
It refuses to create more than one ball.

This is the output from the command line:


Now both instances of the thread are being created and finishing, but only one instance of the Ball can be seen.

Now, ive researched this problem for the last couple of days and cant seem to find a solution. Please help me. If you need any clarifications, extra code etc, i will provide it.
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What type of component is BallFrame? Is it actually a Frame or JFrame? If so, don't J/Frames only allow one content (the ContentPane)? Shouldn't you be adding the balls to J/Panel and use that Panel as the Frame's content pane?

And if that is not the problem, then I think you will need to post a runnable solution which shows the problem a SSCCE
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
BallsFrame is a JFrame (essentially a helper frame) which i feed into a viewer called BallsViewer like this:



I swear you could add components directly to the frame? Because thats what i have done with this BallComponent. One of them does work. It displays fine, its just the other one doesnt show.

Both threads start execution, i have tested that using a println before and after the thread.start() method.

Still dont know why it doesnt show?
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can add components to the JFrame - it goes to the default content pane, whose layout is a BorderLayout. A BorderLayout can only have one content per area (with the default area being the center). So when you are adding two balls to the frame you are adding one, then adding the second into the same area, removing the first.

You should use a JPanel as an intermediate. Add the JPanel to the content pane, then add your balls to the JPanel.
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And it has nothing to do with threads. Tracing down threads and what not is a red-herring. If you don't believe me try adding two buttons to a JFrame the same way you add those balls.
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok i will definitely try it out now. Just before i do, if the second component removes the first surely the position should change since the second has completely different coordinates to the first instance ?
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Shady Sback wrote:Ok i will definitely try it out now. Just before i do, if the second component removes the first surely the position should change since the second has completely different coordinates to the first instance ?

No, LayoutManagers (some anyway) completely ignore the positions you give components - it is the LayoutManager's job to position and layout components, not yours. So when you want to control a component's position you should remove the LayoutManager or use one that allows absolute positioning.
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OHHHH!!! I get it now! Just had my eureka moment

Thank you so much for helping me.
If i insert a new JPanel and change the layout to, lets suppose, a FlowLayout, will it allow me to do absolute positioning?
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't remember... I think the default layout for a JPanel is FlowLayout. You will definitely see two balls, but they will either be next to each other (horizontal flow) or one on top of the other (vertical flow). I think the best way to get absolute positioning is to pass null as the LayoutManager. But it has been a while since I played with GUI stuff.
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Steve Luke wrote:I don't remember... I think the default layout for a JPanel is FlowLayout. You will definitely see two balls, but they will either be next to each other (horizontal flow) or one on top of the other (vertical flow). I think the best way to get absolute positioning is to pass null as the LayoutManager. But it has been a while since I played with GUI stuff.


This will keep me busy for the next half hour, i will post here if i encounter any problems. Thanks a bunch!
 
Rob Spoor
Sheriff
Pie
Posts: 20527
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One word of advice - drop the Thread and Runnable. All it does is start a Swing timer which already does what you want.
 
Tony Docherty
Bartender
Posts: 2957
59
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think the best way to get absolute positioning is to pass null as the LayoutManager.

Yes, if you call setLayout(null) it removes any existing LayoutManager and it's then entirely up to you to control the size and location of all child components. Remember you will no longer have auto-handling of scenarios such as the component's size changing so you may want/need to add a listener to handle cases such as this.
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tony Docherty wrote:
I think the best way to get absolute positioning is to pass null as the LayoutManager.

Yes, if you call setLayout(null) it removes any existing LayoutManager and it's then entirely up to you to control the size and location of all child components. Remember you will no longer have auto-handling of scenarios such as the component's size changing so you may want/need to add a listener to handle cases such as this.


I tried to use setLayout(null) but no components showed on the frame despite passing parameters x,y using addBall(x, y);
Or do i need to set explicitly set the coordinates for the component while adding it to the panel, something along the lines of



?
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:One word of advice - drop the Thread and Runnable. All it does is start a Swing timer which already does what you want.


Appreciate it but this is simply a learning exercise for me as my actual program needs to make hundreds of bouncing balls each controlled by their own runnables. This is just a simpler version of it !!
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Did you define the size of the component as well (another function normally influenced by the layout manager)?
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Steve Luke wrote:Did you define the size of the component as well (another function normally influenced by the layout manager)?

i used a setBounds(x,y, FRAME_WIDTH, FRAME_HEIGHT) if thats what you meant? And that didnt solve it either
 
Tony Docherty
Bartender
Posts: 2957
59
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried to use setLayout(null) but no components showed on the frame

You shouldn't be setting a null layout on the frame, set it on the panel that you are adding your Ball components.

My comments on setLayout() were in response to Steve Luke's post and I hadn't read the rest of the thread.
I've just had a quick look and I'm not sure what your Ball class is. I assume it extends JPanel or JComponent, is this correct?

You need to call setLocation() and setSize() on the Ball object to set it's location and size within the component that it has been added to. Then you override paintComponent() to draw your shape. Don't try and draw it at whatever the x, y location is as your component is already at that position so within your Ball object you draw at 0, 0.
 
Rob Spoor
Sheriff
Pie
Posts: 20527
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevie Shorey wrote:
Rob Spoor wrote:One word of advice - drop the Thread and Runnable. All it does is start a Swing timer which already does what you want.


Appreciate it but this is simply a learning exercise for me as my actual program needs to make hundreds of bouncing balls each controlled by their own runnables. This is just a simpler version of it !!

Even with thousands of balls, you shouldn't use threads in Swing. Read Concurrency in Swing for more details.
 
Stevie Shorey
Ranch Hand
Posts: 45
Android Chrome Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By Overriding the paintcomponent do you simply mean i should call the repaint() method ?
 
Tony Docherty
Bartender
Posts: 2957
59
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By Overriding the paintcomponent do you simply mean i should call the repaint() method ?

No, calling repaint() causes a series of actions to occur, one of which is to call a component's paintComponent() method whose task it is to paint the visible component. In, for instance, a JButton the paintComponent() method paints a rectangular button shape at the required size and draws the text on the button. So you have to provide an implementation of paintComponent() in your Ball class to draw your ball.

I suggest you check out the following Java tutorials

http://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html
http://docs.oracle.com/javase/tutorial/uiswing/painting/index.html
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic