sorry in advance if that question did get asked before somewhere here. I really tried to find something that helps me. Sadly I had no luck.
Here is my situation:
I have a Frame class with a button and a slider. And I have a thread class. With the button in the frame class, I create instances of the thread class. One instance of a thread class represents an picture. All the subthreads(pictures) will be displayed in the same frame and move around with a certain interval.
Here is my problem:
The slider controles the interval of the moving pictures. So they move faster or slower. All pictures should get faster or slower simultaneously. Unluckily only the first created thread gets affected by the slider. Same problem is with my ComponentAdapter that has his componentResized function. All the threads(or the pictures) should get bigger or smaller simultaneously relatively to the frame size.
Here I will try to show you roughly how I am doing it:
frame class:
//The actionPerformed for the button that keeps creating threads
//Every thread is a picture (ant in this case) that
// moves through the same field of buttons
public void actionPerformed(ActionEvent e){
a = new AmeiseThread(this);
a.start();
}
// The slider in the frame.When it changes, also the picture movement speed changes
sliderKind.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (!source.getValueIsAdjusting()) {
int speed = source.getValue();
a.sleeptime = 1000 / speed;
}
}
});
// Whenever the Frame gets resized, it will change the Pictures
// on its buttons relatively to its new size
class MyComponentAdapter extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
xScale = jbArray.get(1).getSize().width;
yScale = jbArray.get(1).getSize().height;
a.ameisen.clear();
a.ameisen.add(new ImageIcon(new ImageIcon("ameise.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
a.ameisen.add(new ImageIcon(new ImageIcon("ameise90.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
a.ameisen.add(new ImageIcon(new ImageIcon("ameise180.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
a.ameisen.add(new ImageIcon(new ImageIcon("ameise270.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
}
}
I can't think of anything that is written in my thread class, that could be of interest. I think the problem lies within my already posted code somewhere. But if you do need more informations, comment it and I will post more informations right away.
Sorry again, if that question already exists. I feel like it does, because it sounds rather simple. Though I really tried to find a question similar to this but I had no luck.
Save all the threads you create
threadList.add(a);
itarate over it when the slider changed
for (AmeiseThread a: threadList)
if (!source.getValueIsAdjusting()) {
int speed = source.getValue();
a.sleeptime = 1000 / speed;
}
Related
This was a small assignment given.A JFrame program had to written such that when you click a button another button in the same panel ;the y in button.setBound(x,y,l,b); would decrease by a factor of 100 and stay at that location for some time and return to its original position.
Now the Problem arises that when I press the button the another button jumps but not always. At some clicks it doesn't jumps altogether--and that is happening arbitrarily.
What is it that my code could is missing?
PS-the JFrame was created by using the drag-drop palette in eclipse so most the code is automatically generated.
int jy=325,jx=214;
int x=325;
int o1x=403,o1y=359;//global in class
public void run()
{
int xo1=o1x;
while(true)
{
action.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0)
{
jumper.setBounds(jx, jy-100, 23, 70);
}
});
try{sleep(750);}catch(Exception e){}
jumper.setBounds(jx, jy, 23, 70);
xo1=xo1-50;
if(xo1<=100)
{
xo1=o1x;
}
obs1.setBounds(xo1, o1y, 12, 35);
}
}
Since I can't see all your code, I can only guess. What is the LayoutManager you are using? Is it a null layout? Otherwise the setBounds method may eventually not really work.
If you have a null layout (what should do absolute positioning), you may need to repaint the parent component of jumper after calling setBounds() when jumper is already visible. To do so, try the following:
parent.revalidate();
parent.repaint();
I created a Jframe using netbeans drag-n-drop designer. After asking here , I can make the color changing works after changing the color of some item from recList and paint(g) on a new thread of my Draw class.
Now I want to add another JComponent like DrawCar that will add the car image to the Jframe. I want this new JComponent because I don't want to re-render the "car" if the squares in the background change color.
So I created the DrawCar with paint() method like below:
public void paint(Graphics g) {
//This to make the (0,0) at the bottom-left not top-left as default.
Graphics2D g2 = (Graphics2D)g;
AffineTransform at = g2.getTransform();
at.translate(0, getHeight());
at.scale(1, -1);
g2.setTransform(at);
//Below is to draw the car
try {
image = ImageIO.read(new File("car.png"));
} catch (IOException ex) {
Logger.getLogger(Car.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
g.drawImage(image, 245, 0, null);
}
If I put these code to render the car in the paint() method of Draw class, it works, so no problem with this code!
In the Container (the class with the GUI) class, I have a button handler. I want the car appear when I click that button, so I tried to add to the event handler with
private void starter_btnActionPerformed(java.awt.event.ActionEvent evt) {
Thread reDraw = new Thread(new Runnable() {
#Override
public void run() {
//draw1 below is the instance of "Draw" class
//draw1.paint2(draw1.getGraphics()); //This code works with repainting the square with new color as mentioned before
DrawCar draw2 = new DrawCar();
repaint();
revalidate();
}
});
reDraw.start();
}
but it won't work, I don't know what I missed here. Maybe some ways to add the DrawCar to the current JFrame?
Thank you for your time!
EDIT:
I just make a simple project to make it clear. I created a JFrame named Test and drop in it a button that will show the picture when I click on it. It's all auto-generated codes.
Now I create a new class call MyClass
public class MyClass extends JComponent{
private BufferedImage image;
MyClass(){
try {
image = ImageIO.read(new File("D://pic.jpg"));
} catch (IOException ex) {
Logger.getLogger(this.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image, 50, 50, null);
}
}
And in the Test, the event handler of the button is like this:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
MyClass mc = new MyClass();
add(mc);
repaint();
revalidate();
}
I clicked it and nothing happens. The picture is supposed to shows up on click. How do I make it happens? Thank you
EDIT 2:
This is the image of what I want to achieve, it's the little green car on the bottom, it should appears only when I click "Start!"
I see quite a few general problems with your code, including:
Never override the paint method, but rather a JPanel or JComponent's paintComponent method.
Almost always call the super's method.
Never read in a file from within a painting method.
Your code flagrantly violates Swing threading rules -- most all Swing calls should be made on the Swing event thread, not off of it as you're doing.
Better to create and post your Minimal, Complete, and Verifiable example or sscce as this way we can run your actually functioning code.
As for your specific problem, you're creating a DrawCar component instance, but you never appear to add it to your GUI, and so it will never show since it is never part of a top-level window such as a JFrame or JApplet or JDialog.
re comments:
Just though paint() and paintComponent() are the same, just one calls another...
No they're not. The paint(...) method is the more "primitive" of the two as it's based in the old AWT code base. It does not automatically do double buffering (unlike paintComponent) and is responsible for painting the component, the component's borders, and any child components held by the component. For the latter reason, you want to avoid overriding it since if you mess it up, you risk mispainting more than just the component.
Back to my problem, I make it like this DrawCar draw2 = new DrawCar(); add(draw2); draw2.setVisible(true); revalidate(); repaint(); I don't know if I missed the "prefix" before add, the code is auto-generated so I can't find any JFrame frame = new JFrame(); to make frame.add(draw2) like others do with their code Any chance that we will find some logical problem?
You've got major structural problems as your new DrawCar class again is nowhere to be seen in the main GUI.
So I'm guessing that your main GUI already has a DrawCar component held within it, and that you're goal is to get this to draw a car on button push (you never say!). If so, then why not have the DrawCar hold a JPanel and simply set its Icon with your image. Myself, I'd read the image in at program start up, and also flip it at at that time, if that were my goal.
Again, if you're still having problems, then isolate the problem down to the smallest compilable runnable code, your mcve and let us test it.
I have two classes: logic and the JFrame. In frame I have a JLabel and a JButton, and I would like to:
When this button is clicked, the ImageIcon in the label changes after a determined time using a Swing Timer, like if it is flashing. To do it I loaded two images with different brightness (img1b and img1). I tried to make the timer change the image twice with different delays, but I was unsuccessful. I also put a listener in the button and implemented the actionPerformed as below:
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(btnImg1)) {
logic.piscaImagen(img1, lblImg1);
logic.piscaImagen(img1b, lblImg1);
In logic class:
public void piscaImagen(ImageIcon img, JLabel lbl) {
Timer timer = new Timer(1250, null);
timer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt){
if(lbl.getIcon() != img){
lbl.setIcon(img);
}
}
});
timer.setRepeats(false);
timer.start();
}
But when I run it nothing changes in the logic.piscaImagen. Any tips?
logic.piscaImagen(img1, lblImg1);
logic.piscaImagen(img1b, lblImg1);
It looks to me like you are starting two Timers. So the first Timer fires and it changes the image, then the second timer fires and it restores the image so basically you only see the first image.
All you need is one Timer. Each time the Timer fires you change the image. So the basic code in your Timer would be:
if (lbl.getIcon() == img1)
lbl.setIcon(img1b);
else
lbl.setIcon(img1);
Or for a more flexible solution you can use the Animated Icon.
The Animated Icon will allow you to specify a List of Icons to display. Then when the Timer fires the next Icon in the List is displayed. You can set the Animated Icon for continuous display or you can control the number of cycles.
EDIT: answer inaccurate, repaint() not necessary - see comments.
You're missing the repaint() call that tells the program it needs to update the display.
#Override
public void actionPerformed(ActionEvent evt) {
if(lbl.getIcon() != img){
lbl.setIcon(img);
lbl.repaint();
}
}
(your if statement was also missing a closing brace, unsure what impact that would have / if it was a typo)
I am fairly new to Java programming and want to make a basic game that shows an image when clicked once, a different image when clicked twice and etc.
I know how to do all this but I don't know how to keep track of how any clicks and then do an actions based on how many clicks have been done (Hard to explain, my apologies...)
I ... want to make a basic game that shows an image when clicked once, a different image when clicked twice and etc. I know how to do all this but I don't know how to keep track of how any clicks
As per my comment, give the class with the ActionListener an int field, say called buttonCount, and increment it each time the button is pressed -- inside of the button ActionListener's actionPerformed method: buttonCount++
and then do an actions based on how many clicks have been done (Hard to explain, my apologies...)
In the ActionListener's actionPerformed method change the image displayed. How you change it all depends on how you show it, something that you've yet to show us, and so I can't give you any code.
One way to make it easy is to create an ArrayList of ImageIcons to hold your images (as ImageIcons of course), and then call get(buttonCount) on the ArrayList to get the appropriate ImageIcon and display it in a JLabel via its setIcon(...) method. Make sure that the buttonCount is less than the size of the ArrayList so as not to get an ArrayIndexOutOfBoundsException. One way to do this is to mod your buttonCount by the size of the ArrayList. This will allow you to cycle through your collection of images.
Again, you will want to read the Swing tutorials on how to use JButtons and then break down your big problem into small steps, trying to solve each step one at a time.
Again if you need greater detail and more specific help, then you must show what you've tried and explain in detail what problems you may be having with it. It is my sincere believe and philosophy that you learn most by by forcing your brain to do new and unfamiliar things, by mental effort and sweat. So have at it, you've nothing to lose.
You can count the the mouse clicks in this way. By using an if-else or switch case you can display the images.
public class ButtonStart extends Frame {
private int mouseclicked = 0;
TextField objTextField;
public static void main(String args[]) {
ButtonStart BS = new ButtonStart();
}
public ButtonStart() {
Frame objFrame;
Button objButton;
TextField objTextField;
objFrame = new Frame("Clicking Buttons");
objButton = new Button("Click me!");
objTextField = new TextField("0");
objFrame.addMouseListener(new MyMouseListener());
objFrame.add(objButton);
objFrame.add(objTextField);
objFrame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
public class MyMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent me) {
int mouseclicked = me.getClickCount();
objTextField.setText("Mouse clicked this many times:"
+ mouseclicked);
}
}
}
I am changing the bounds of a JPanel using a Timer to get a sliding effect when someone hovers over a particular rectangular area, this is working as expected. There are buttons in the JPanel and they have different MouseEvent behaviors. But SOMETIMES it starts lagging or slides very slowly. Please, can anyone suggest what can I do, to ensure it performs well every time?
EDITED:
The buttonsPanel have button in it. buttonsPanel is added to a JLayeredPane which have bounds as rect. When JLayeredPane or JButton button is hovered mouse events are triggered. Mouse events then triggers the timer to slide the buttonsPanel and bring to it view.
class MyActionListener implements ActionListener {
private static final int frames = 50;
int count = 0;
private final Timer timer = new Timer(1, this);
public void start() {
timer.start();
}
#Override
public void actionPerformed(ActionEvent ae) {
if (count >= frames) {
timer.stop();
} else {
count = count + 1;
buttonsPanel.setBounds(hidden_width - hidden_width * count / frames, 0, hidden_width, frameHeight);
}
}
}
class MyMouseListener extends MouseAdapter {
private MyActionListener timerListener;
#Override
public void mouseEntered(final MouseEvent event) {
final Color color = new Color(50, 50, 50);
if (event.getSource() instanceof JButton) {
final JButton button = (JButton) event.getSource();
button.setBackground(color);
buttonsPanel.setVisible(true);
} else if (!buttonsPanel.isVisible()) {
buttonsPanel.setVisible(true);
timerListener = new MyActionListener();
timerListener.start();
}
}
#Override
public void mouseExited(final MouseEvent event) {
Point point = new Point(0, 0);
if (event.getSource() instanceof JButton) {
final JButton button = (JButton) event.getSource();
point = button.getLocation();
button.setBackground(Windows8GUI.color);
}
Rectangle rect = new Rectangle(0, 0, hidden_width, frameHeight);
if (!rect.contains(point.x + event.getX(), point.y + event.getY())) {
buttonsPanel.setVisible(false);
buttonsPanel.setBounds(0, 0, hidden_width, frameHeight);
}
}
}
The primary issue is you are assuming that you have control over the paint engine. You don't, in fact, the paint engine is at the mercy of the OS. This means that you can jump up and down all you like, but until the OS and Java's paint engine are ready, nothing will happen.
In fact, if you call repaint repeatedly in quick succession you can find yourself flooding the paint engine with requests, slowing it down even further.
While not a solution to the whole problem, it will make your life vastly simpler take a look at the TimingFramework or Trident.
They are "animation" frameworks designed to take out the guess work and make your life easier. I personal use TimingFramework for all my animation and it works well.
The timing frameworks work on a % over time. That is, you give it a time for a cycle and the frameworks will return a % value based on how far through that cycle they are. You can apply interpolations, allowing you to effect how fast a portion of the animation will play.
Trident has also been designed to provide the means to call other methods on your behalf, so it could set the bounds of the button pane for you, based on values you supply it.
In fact, if you call repaint repeatedly in quick succession you can find yourself flooding the paint engine with requests, slowing it down even further.
I think this is the real problem. Try increasing the delay between the timer events from 1 to 10-50 and it should run a lot better.
For a lot of how-tos for building those (and a lot of other) effects, I can only recommend the Book Filthy Rich Clients. On this page you also find a lot of examples for those effects handled in the book.