layout manager cancelling set location of jlable - java

i wrote my code like below and LABEL moved correctly:
panel.setLayout(null);
JLabel label1=new JLabel("LABEL");
JLabel label2=new JLabel("0");
JButton btn1=new JButton("start");
btn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
Thread t=new Thread()
{
public void run()
{
while(true)
{
try
{
Thread.sleep(10);
}
catch (Exception ex)
{}
label2.setText(String.valueOf(Integer.parseInt(label2.getText())+1));
label1.setLocation(label1.getX()+1, label1.getY());
}
}
};
t.start();
}
});
but when i wrote in Netbeans Jframe it didn't move!
is it possible that problem is from JFrame layout manager??
How can i solve it?
At the same problem, when i comment line A of below code changing location of jLabel2 working correctly but when both line A and B aren't comment jLabel2 never move!!
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Thread t=new Thread()
{ public void run()
{ while(true)
{ try
{ Thread.sleep(10); }
catch (Exception ex) {}
/* line A */
jLabel1.setText(String.valueOf(Integer.parseInt(jLabel1.getText())+1));
/* line B */
jLabel2.setLocation(jLabel2.getX()+1, jLabel2.getY());
}
}
};
t.start();
}

Again
If you're animating a component, then the container that holds it needs to use a null layout. If you're not sure what layout it's using, ask it -- call getLayout() and print out the result.
Use a Swing Timer not a background thread to drive your animation. This will ensure that you make Swing calls on the Swing event thread, something that your code is not doing.
After moving your component, call revalidate() and repaint() on the container that holds it.

Related

Content of JFrame not showing

When the user hits "close" in one JFrame frame, I want the JFrame credits to be displayed showing my name and stuff for 2.5 seconds before the program exits. Now, credits is showing, but empty without the textArea and the Button - couldnt find whats wrong.
Heres my code:
For the closing operation of frame
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
int result = JOptionPane.showConfirmDialog(null, "Sind Sie sicher?", "Schließen", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION){
credits.setVisible(true);
try {
Thread.sleep(2500);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
System.exit(0);
} else {
//do nothing
}
}
});
For credits (just the class initializing the frame):
public class CreditsFrame extends JFrame {
Positioner pos = new Positioner();
private JPanel contentPane;
ImageIcon frameIcon = new ImageIcon("files/images/frameicon.png");
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CreditsFrame frame = new CreditsFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public CreditsFrame() {
setIconImage(frameIcon.getImage());
setAlwaysOnTop(true);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(pos.posX(pos.screenX, 441), pos.posY(pos.screenY, 210), 441, 210);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
JTextArea txtarea = new JTextArea();
txtarea.setBounds(10, 11, 415, 125);
txtarea.setEditable(false);
txtarea.setBackground(Color.WHITE);
txtarea.setWrapStyleWord(true);
txtarea.setLineWrap(true);
txtarea.append("created by & more here");
contentPane.setLayout(null);
contentPane.add(txtarea);
JButton btnOk = new JButton("Ok");
btnOk.setBounds(154, 147, 89, 23);
btnOk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
contentPane.add(btnOk);
}
}
Any suggestions for a quick fix? Thanks.
Any suggestions for a quick fix?
Yes, don't call Thread.sleep(...) on the Swing event thread unless you want to put your entire GUI to sleep. Instead use a Swing Timer to handle the delay. Basically, the timer's ActionListener will be called after the milliseconds delay has passed.
e.g.,
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
int result = JOptionPane.showConfirmDialog(null, "Sind Sie sicher?", "Schließen", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION){
credits.setVisible(true);
new Timer(2500, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.exit();
}
}).start();
} else {
//do nothing
}
}
});
Also, look at The Use of Multiple JFrames, Good/Bad Practice?
Other issues that will bite you in the future:
You look to be using null layouts and setBounds. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms different from the original one.
Never set a JTextAreas bounds as this will make it completely fail if it is placed within a JScrollPane and more text than can be displayed is added -- the scroll bars will seem not to work since you've artificially constrained the size of the text component.

setText() not working in mouseClicked() function

public class Pragrassbar extends JFrame implements MouseListener {
JProgressBar jb;
int i = 0, num = 0;
JButton jbt;
JLabel jl;
Pragrassbar() {
setSize(400, 400);
setLayout(new FlowLayout());
jbt = new JButton("Start");
jl = new JLabel("Click Start!");
jb = new JProgressBar(0, 2000);
jb.setValue(0);
jb.setStringPainted(true);
jbt.addMouseListener(this);
add(jbt);
add(jb);
add(jl);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void mouseClicked(MouseEvent me) {
jl.setText("downloading.....");
jbt.setEnabled(false);
try {
while (i <= 2000) {
jb.setValue(i);
jb.paintImmediately(0, 0, 200, 25);
i = i + 40;
Thread.sleep(30);
}
jl.setText("download complete");
jbt.setEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
Pragrassbar m = new Pragrassbar();
m.setVisible(true);
}
setText() not functioning under mouseClicked function of MouseListener interface
although it works after the while loop that i have used
The Thread.sleep() causes the Event Dispatch Thread (EDT) to sleep which means the GUI can't repaint itself until the looping code is finished executing.
Don't use Thread.sleep. Instead long running code should execute in a separate Thread so you don't block the EDT. You should probably use a SwingWorker for this.
Read the section from the Swing tutorial on Concurrency for more information and working examples on this approach.
You can also read the section on How to Use Progress Bars for the proper way to do this.

Why does the thread not sleep properly?

I am trying to make a simple JButton, which when being clicked causes a simple JLabel to change its text to "second text", after that I want the current thread to sleep for few seconds and finally the JLabel to change its text again, this time to a "third text". I think I have it done here, but it doesn't work the way I want it. The code provided below makes the JButton freeze for the specified timeframe, as if it is held down, and then the label changes to the its third state. Said in other words, the "seconds text" does not appear.
Please advise me how should it be done.
Thank you.
package testPackage;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Demo {
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame();
JButton button = new JButton("Click me!");
final JLabel label = new JLabel("first text");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
JPanel panel = new JPanel();
panel.add(button);
panel.add(label);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText("second text");
try {
Thread.currentThread();
Thread.sleep(4000);
} catch (InterruptedException exc) {
System.out.println("Erorrrrr");
}
}
});
frame.add(panel);
frame.setVisible(true);
}
}
The change of text property is not the only thing that has to be done to see the result when you consider the internals of Java. The control also has to be redrawn (possibly invalidated).
By calling sleep you actually stop java GUI internal worker from redrawing the control you changed. It can happen only after the sleep has finished.
In the action performed method you need to release the main GUI Thread for the changes to occur:
So if you open a new Thread in the actionPerformed method it will release the main GUI thread then after the sleep call the label.setText("third text") this will change the label to second text first wait for 4secs and then change it to third text
#Override
public void actionPerformed(ActionEvent e) {
label.setText("second text");
new Thread(){
public void run(){
try {
//Thread.currentThread();
Thread.sleep(4000);
label.setText("third text");
} catch (InterruptedException exc) {
System.out.println("Erorrrrr");
}
}
}.start();
}
Your GUI runs on a thread. When you sleep that thread for x number of seconds, your GUI freezes for x number of seconds.
As noted in the comments by Marko, "you must instead schedule a delayed event with javax.swing.Timer"
If you sleep on the Event Dispatch Thread (the thread that handles GUI events), then the GUI will freeze. You could start a background thread from the action listener and to the sleeping there.
public void actionPerformed(ActionEvent e)
{
label.setText("text 1");
new Thread(new Runnable()
{
public void run()
{
try {
Thread.sleep(1000);
}catch (InterruptedException ignore){}
// queue Swing code for execution on the EDT
EventQueue.invokeLater(new Runnable()
{
public void run()
{
label.setText("text2");
}
});
}
}).start();
}

Custom Modal Dialog

I am creating my own dialog which is basically a JPanel set as the glasspane on a JFrame. I want to make my dialog modal in the sense that all the code after the setVisible() is not executed while the dialog is visible and once the dialog is closed, the rest of the code after the setVisible() must continue.
To achieve this I am using a thread to display my dialog. I know that the SwingUtilities.invokeLater() method must be used to update the gui because it is executed in another thread. However my dialog does not show on the screen.
Here is my code example:
final JFrame frame = new JFrame();
frame.setBounds(0, 0, 1024, 768);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton button = new JButton("Text");
button.setBounds(200, 300, 110, 50);
button.addActionListener(new ActionListener() {
boolean dispose;
public void actionPerformed(ActionEvent e) {
try {
Thread thread = new Thread(new Runnable() {
public void run() {
final JPanel panelGlass = new JPanel(null);
panelGlass.setBounds(frame.getBounds());
panelGlass.setBackground(Color.red);
frame.setGlassPane(panelGlass);
JButton btnClose = new JButton("close");
btnClose.setBounds(100, 100, 110, 50);
btnClose.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose = true;
}
});
panelGlass.add(btnClose);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
dispose = false;
panelGlass.setVisible(true);
}
});
while (!dispose) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
panelGlass.setVisible(false);
}
});
thread.start();
thread.join();
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
frame.getContentPane().add(button);
frame.setVisible(true);
Why is my dialog not shown?
The problem is here:
thread.start();
thread.join();
You start the thread but you immediately wait for it to finish. This blocks the UI thread and doesn't allow it to process your SwingUtilities.invokeLater update.
I really don't see any good reason for that join call to exist.
You can't do that like that since
you're accessing Swing components from a thread other than the event disptach thread
the event disptach thread, where all the UI painting happens, is completely blocked by the call to Thread.join().
You should be able to do something like what you want with Java 7's SecondaryLoop, but I've never used it.
frame.getRootPane.setGlassPane
your idea is good, but have to consume() events came from keyboard, add there KeyListener only with e.consume() because GlassPane to consume only mouse events
create whole Gui with GlassPane too,
inside actionperformed to show prepared GlassPane, then to start a Runnable.Thread
I have one question here about multiply glasspane
use JLayer Java7, based on JXLayer Java6
your question is booking example for why reason is SwingWorker implemented in Java
reply from cellphone

How to turn on buttons once turned off in ActionListener

Problem: Code does not turn the button back on (Example gives it 5 seconds for you to press)
Example code:
public static void main(String[] args) throws InterruptedException
{
Example call = new Example();
Thread.sleep(5000);
call.ButtonSwitch(1);
}
NOTE: this is the smallest coding i could make to show my problem
public class Example extends JFrame implements ActionListener {
static Example frame2 = new Example();
GridLayout experimentLayout = new GridLayout(0,1);
JPanel Game = new JPanel();
JButton button1 = new JButton("Press");
public Example()
{
Create();
}
public void Set()
{
setResizable(false);
}
public static void Create() {
/* Use an appropriate Look and Feel */
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
//Create and set up the window.
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
frame2.addComponentsToPane(frame2.getContentPane());
//Display the window.
frame2.pack();
frame2.setVisible(true);
}
public void addComponentsToPane(final Container pane)
{
Game.setLayout(experimentLayout);
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(2,3));
//Set up components preferred size
JButton b = new JButton("Just fake button");
Dimension buttonSize = b.getPreferredSize();
Game.setPreferredSize(new Dimension((int)(buttonSize.getWidth() * 2),
(int)(buttonSize.getHeight() * 1)* 4));
Game.add(button1);
button1.addActionListener(this);
//Process the Apply gaps button press
pane.add(Game, BorderLayout.NORTH);
pane.add(new JSeparator(), BorderLayout.CENTER);
pane.add(controls, BorderLayout.SOUTH);
}
//Turns button off On Click
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == button1)
{
button1.setEnabled(false);
}
}
//This does not turn the button on but tries to
public void ButtonSwitch(int num)
{
if (num == 1)
{
System.out.println("This is called");
button1.setEnabled(true);
}
}
}
I want to make the method Enable the button, but if this is not possible a way to do this in action listener without user input would be the second option (which would look like the Button switch method placed inside the ActionListener)
The problem comes from the bad design of the class. The point is that you are not calling setEnabled(true) and setEnabled(false) on the same button1. In your main,
Example call = new Example();
Thread.sleep(5000);
call.ButtonSwitch(1);
the last line invokes setEnabled(true) on the button of call, while the actionPerformed invokes the setEnabled(false) on the button of frame2.
Regardless, you are doing it wrong:
Don't mix the main (entry) thread with the EDT.
Don't hold a member of the same class type as the containing class (unless there's a special reason to do so).
Here is a real MCVE of a working code:
public class Example extends JFrame {
JButton button = new JButton("Press");
Timer timer = new Timer(5000, e -> button.setEnabled(true));
public Example() {
add(button);
button.addActionListener(e -> {
button.setEnabled(false);
timer.start();
});
timer.setRepeats(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) throws InterruptedException {
SwingUtilities.invokeLater(() -> new Example());
}
}
Notes:
Method and non-final variable names start with a lowercase.
Don't use setPreferredSize, override getPreferredSize instead.

Categories

Resources