Thread issues in JFrame - java

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();

Related

GUI application that the shape changes on a radio button click

What my application is meant to do is change the background and foreground on a click of a radio button and change the shape of the item based on a radio button.I am trying to get my application to actively change shape based on the radio button that is selected.I have the background and foreground working just not the shape. I have seen another post kinda like this but it has a submit button and does not use the JSlider
Below is what I have been messing with and cannot seem to get the program to execute correctly. I have gotten the shape to change but then the slider breaks. Am i approaching this the wrong way?
public class OvalPanel extends JPanel
{
private int diameter = 10; // default diameter
// draw an oval of the specified diameter
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(rectFillRadioButton.isSelected()){
g.fillRect(10,10,10,10);
//repaint();
}
if(ovalFillRadioButton.isSelected()){
g.fillOval(10,10,10,10);
//repaint();
}
}
// validate and set diameter, then repaint
public void setDiameter(int newDiameter)
{
// if diameter invalid, default to 10
diameter = (newDiameter >= 0 ? newDiameter : 10);
repaint(); // repaint panel
}
// used by layout manager to determine preferred size
public Dimension getPreferredSize()
{
return new Dimension(200, 200);
}
// used by layout manager to determine minimum size
public Dimension getMinimumSize()
{
return getPreferredSize();
}
}
this is the class that i initially have that sets the paintComponent. I also have
private class TopRadioButtonHandler extends JFrame implements ItemListener {
private Graphics panel;
public TopRadioButtonHandler(Graphics p) {
panel = p;
}
#Override
public void itemStateChanged(ItemEvent event) {
if(rectFillRadioButton.isSelected()){
panel = myPanel.getGraphics();
panel.fillRect(10,10,10,10);
repaint();
}
if(ovalFillRadioButton.isSelected()){
panel = myPanel.getGraphics();
panel.fillOval(10,10,10,10);
repaint();
}
}
}
i dont think i need the repaint but when i use this method my JSlider stops working.
Am i approaching this the wrong way?
Yes, the paintComponent() method should not be referencing another Swing component.
When you do custom painting, the paintComponent() should only paint the current state of your component.
For example when you use a Jlabel you have methods like setText() and setIcon() to set the text and icon you want to paint.
You already have a method, setDiameter() which is a good start. However, your painting code just hard codes the size of the oval/rectangle. The painting methods should reference you diameter variable.
Now, you need another property to idicate whether to paint an oval or a rectangle. So maybe you need a property like setPaintOval(boolean paintOval).
Then your painting code could be:
If (paintOval)
g.fillOval(10, 10, diameter, diameter);
else
g.fillRect(10, 10, diameter, diameter);
Of course the problem with this approach is that you can only paint two objects.
Also, you should never invoke repaint() in a painting method. The repaint() should only be invoked from your setter methods when you change the state of the component.
but then the slider breaks
The code you posted has nothing to do with a slider.
I'm guessing you want the slider to change the diameter of the oval? Well you need to add a ChangeListener to the slider and then invoke your setDiameter() method with the slider value.
Read the section from the Swing tutorial on How to Use Sliders for a working example.

Change ImageIcon in JLabel using Timer

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)

Changing the same variable for all existing subthreads

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;
}

Refresh java program with Button

I am trying to make a refresh button that will essentially restart the program when ever I click the button. I don't know how I should go about doing this.
I've place the Graphical User Interface i decided to use do complete this action. Any and all help would be greatly appreciated.
package pdfView;
import javax.swing.*;
import java.awt.*;
public class View extends JFrame {
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
JButton ReFresh = new JButton("ReFresh");
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.squing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc){
}
}
public static void main(String[] args) {
View pdf = new View();
}
}
What do you mean by refresh or restart?
Do you mean:
Let the application be as it is, just update what it's showing?
Really restart the application?
Updating what the application is showing
You first need to decide what actually should cause your application to refresh. You already talked about a Button. The mechanism for activating something like a button is called Action. You can do that stuff manually, using an ActionListener, or you could extend AbstractAction, which is what I recommend. Extending AbstractAction allows you to use the same logical action something in more than one location on the UI. Look at typical applications, they offer Cut/Copy/Paste through menu, toolbar, popupmenu and keyboard shortcuts. The simplest way to achieve this in Java is using Action by extending AbstractAction.
The methods you need to call to update your application are invalidate(), validate() or repaint().
Restarting an application
So you want to run through main() again? That should actually not be required, unless you have an application that supports updating itself. Even then it can sometimes be avoided by smart usage of a ClassLoader.
Some more notes on your code
Usage by extension anti-pattern
I wouldn't extend JFrame just to display a window on the screen. Usage by extension is an anti-pattern. You don't need to extend JFrame to get a JFrame displayed on the screen and do what you want.
Referring static members
I would refer to constants via their original declaration. I.e. I'd refer to EXIT_ON_CLOSE via WindowConstants.EXIT_ON_CLOSE, not JFrame.EXIT_ON_CLOSE.
Typo
You have a typo in your UIManager.setLookAndFeel() code. Search for swing and you will see the typo.
Exception information
You might actually want to print the exception to stderr using exc.printStackTrace() instead of ignoring it completely, because when you have a typo in the LaF class name, as you do, and you don't print the exception, you might actually not come to know what's going wrong.
Sequence of widget construction and UIManager.setLookAndFeel()
The sequence of UIManager.setLookAndFeel() and the effective new JFrame() via super(...) does not guarantee you that the whole UI will be in Nimbus, parts of it might still be in Metal. I recommend to set the LaF before even constructing the first widget, to be on the safe side. As far as I remember, it's not guaranteed that changing the LaF after component construction has an effect, unless you tell the UIManager to update the LaF. See also this quote from the documentation of UIManager:
Once the look and feel has been changed it is imperative to invoke updateUI on all JComponents. The method SwingUtilities.updateComponentTreeUI(java.awt.Component) makes it easy to apply updateUI to a containment hierarchy. Refer to it for details. The exact behavior of not invoking updateUI after changing the look and feel is unspecified. It is very possible to receive unexpected exceptions, painting problems, or worse.
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
setSize() vs. pack() with a little help of Insets and Border
Instead of setting the size manually, you might want to play with Insets or Border and JFrame.pack() in order to get a decent layout of your window. Setting the size manually assumes that you know a lot about the screen resolution and the font size of the user.
The pack() method performs automatic size calculation based on the contents. Insets and Border allow you to create some space and borders, even with some designs or labels, around components so they wouldn't be cramped tightly in a window but be nicely spaced.
First you have to assign an actionListener to the ReFresh Jbutton.
You can either implement the interface ActionListener to the class, and override the actionPerformed() method like this
public class View extends JFrame implements ActionListener{
private JButton ReFresh;
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
ReFresh = new JButton("ReFresh");
ReFresh.addActionListener(this);
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() { //right way for nimbus: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/nimbus.html
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.equals(ReFresh))
{
super.repaint();
}
}}
public static void main(String[] args) {
View pdf = new View();
}
Or you can do inline assignment to addActionListener, like this
ReFresh.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
super.repaint();
}
});
You can try these methods to refresh/reload the JFrame,
invalidate();
validate();
repaint();
you can also use dispose(); and then new View(); to create the new JFrame, but in this sequence it will close the window and create new one.
or you can even try setVisible(false); then setVisible(true);
I recommend the first 3.

Java Refreshing a screen

I have a screen in which one of its components is made invisible depending on a boolean value. If the boolean changes after the screen has been created, how do I refresh the screen to take this into account?
I think revalidate() is more appropriate here if you are dealing with JComponents.
From the JavaDoc:
Supports deferred automatic layout.
Calls invalidate and then adds this component's validateRoot to a list of components that need to be validated. Validation will occur after all currently pending events have been dispatched. In other words after this method is called, the first validateRoot (if any) found when walking up the containment hierarchy of this component will be validated. By default, JRootPane, JScrollPane, and JTextField return true from isValidateRoot.
This method will automatically be called on this component when a property value changes such that size, location, or internal layout of this component has been affected. This automatic updating differs from the AWT because programs generally no longer need to invoke validate to get the contents of the GUI to update.
Call the validate() method on the container that needs to be laid out -- probably your window's content pane.
Try calling repaint() which in turn will call paintComponent().
I thought that (with Java 6?) you need not do anything... This should happen automatically - no?
With the following example, it does happen automatically...
public class TT extends JFrame
{
public TT()
{
setLayout(new FlowLayout());
JLabel label = new JLabel();
label.setText("Label:");
add(label);
final JTextField textField = new JTextField();
add(textField);
JButton button = new JButton();
button.setText("Button");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
if (textField.isVisible())
{
textField.setVisible(false);
}
else
{
textField.setVisible(true);
}
}
});
add(button);
setSize(100,100);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
TT frame = new TT();
frame.setDefaultCloseOperation(TT.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
[Add] And using a layout manager like GridBagLayout would also solve the problem of "Re-Laying out" the page.

Categories