I am using swing timer to to load different pdf files in swing application
but I am facing a problem when ever I execute a program the screen remains blank for few seconds like 4 to 5 seconds and then the pdf file is rendered so during this time I want to show a message like please wait. Here is my sample code
if (type[i].equalsIgnoreCase("PDF")) {
int k = i;
pdfTimer = new Timer(0, (ActionEvent e) -> {
renderPDF(k);
});
pdfTimer.setDelay(1000*2);
pdfTimer.start();
Run rendering on SwingWorker's background thread (doInBackground) method. That way, your GUI will remain responsive. From done method you can notify user that rendering is done. Keep in mind not to update any Swing GUI from doInBackground method since it runs outside of EDT.
P.S. Swing Timer is for repetitive tasks.
You can display a progress bar and compute the renderding on a second thread.
JLabel lblWait = new JLabel("Please wait...");
lblWait .setBounds(116, 26, 113, 14);
contentPanel.add(lblWait );
final JProgressBar progressBar = new JProgressBar();
progressBar.setStringPainted(true);
progressBar.setBounds(72, 66, 187, 16);
contentPanel.add(progressBar);
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
final JButton btFin = new JButton("Cancel");
btFin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
buttonPane.add(btFin);
}
}
Thread t = new Thread() {
public void run() {
//You launch the thread with your progress bar as an argument
maStructure.setaAfficher(new MgtSimulation(aAfficher, nombreSimulations).jouerSimulations(progressBar));
maStructure.actualiserAffichage();
dispose();
}
};
t.start();
}
And you change your progress bar value in your method
public BeanAffichage jouerSimulations(JProgressBar progressBar){
//Variables
for (int i = 0; i < nombreSimulations; i++) {
//Computing
progressBar.setValue(Whatever you want);
}
return aAfficher;
}
Just an alternative for SwingWorker
By default show some message like Loading... and create a Thread to run in the background which loads the PDF and updates the window
class BackgroundThread implements Runnable {
#Override
public void run() {
// the Swing call below must be queued onto the Swing event thread
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
// OK To make Swing method calls here
loadFile(args..);
repaint();//Or something similar that fits your purpose
}
});
}
}
Related
For example, I want a JTextfield to display different random numbers continuously with start, stop and resume buttons. What is the possible solution to automatically update the JTextField continuously when the start button is pressed?
I tried using while loop inside the start button's action listener but it just makes the button stuck in the while loop.
This is the part of the code that I tried.
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
while(true){
textField.setText(String.valueOf(random.nextInt()));
}
}
});
Read Concurrency in Swing.
You can use a javax.swing.Timer to change the text of the JTextField.
A tiny example:
public class TimerExample {
public static void main(String[] args) {
SwingUtilities.invokeLater(()->{
JTextField field = new JTextField(10);
Timer timer = new Timer(100, e->{
field.setText(String.valueOf(Math.random()));
});
timer.start();
JOptionPane.showMessageDialog(null,field);
});
}
}
If you use while(true) in the Thread that runs the UI (this thread is called EDT - event dispatch thread), the thread won't be able to handle events since it is stucked inside the while loop.
I have a problem with this code:
public class Gui_01 extends JFrame {
private JPanel display;
private ActionListener visualizza() {
ActionListener evento = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
display.removeAll();
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
);
t.start();
}
};
return evento;
}
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
}
});
}}
I don't understand why the code don't work properly, the thread t and the thread in updateProgress work fine, but any modification to display won't affect the GUI even with invokeLater.
display.add(visualizza, BorderLayout.SOUTH)
This code don't modify the gui, i know it's normal (due to Swing), but why invokeLater don't work.
Sorry for my bad english, thanks in advance for replys.
First get rid of the display.add(visualizza, BorderLayout.SOUTH); statement in your thread. as you should never update or modify the UI from outside the context of the EDT...
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
//display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
In fact, I'd discourage your from creating UI elements outside of the EDT, as you can't guarantee when they might start interacting with the UI.
Second, call revalidate and repaint after you've updated the UI...
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
display.revalidate();
display.repaint();
}
});
}}
Swing is lazy when it comes to updating the UI, this is a good thing, as it allows you to make sweeping changes and only update the UI when you're ready to do so.
I'd also encourage you to use a SwingWorker instead, as it has functionality which you can use to synchronise the updates with the EDT. See Worker Threads and SwingWorker for more details
I have a maybe simple question. Obviously because my program does not do what it is supposed to...
First of all my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
public class Timer
extends JFrame
implements ActionListener
{
protected class TThread extends Thread{
private boolean running = false;
#Override
public void run() {
int timer = 10,
index = 0;
running = true;
while(running){
try {
out.setText(timer + " Secs");
timer--;
if(timer == 0){
if(index % 2 == 0){
timer = ti1;
out.setBackground(Color.red);
}else{
timer = ti2;
out.setBackground(Color.green);
}
index++;
}
sleep(1000L);
} catch (InterruptedException e) {
}
}
}
#Override
public void interrupt() {
running = false;
}
}
private static final long serialVersionUID = 1L;
private JTextField t1 = new JTextField(),
t2 = new JTextField();
private int ti1 = 0, ti2 = 0;
private JLabel l1 = new JLabel("Zeit 1"),
l2 = new JLabel("Zeit 2"),
out = new JLabel("00 Secs", SwingConstants.CENTER);
private JButton go = new JButton("Go"),
stop = new JButton("Stop");
private JPanel cont = new JPanel();
private TThread tr = new TThread();
public Timer() {
super("Timer");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(800, 600);
setLayout(null);
add(cont);
cont.setBounds(0, 0, getWidth(), 200);
cont.setLayout(new GridLayout(3, 2));
cont.add(l1);
cont.add(t1);
cont.add(l2);
cont.add(t2);
cont.add(go);
go.addActionListener(this);
cont.add(stop);
stop.addActionListener(this);
add(out);
out.setBounds(0, 200, getWidth(), getHeight()-200);
out.setFont(new Font("Arial", Font.BOLD, 72));
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
SwingUtilities.updateComponentTreeUI(this);
} catch (UnsupportedLookAndFeelException e) {
}
}
public static void main(String[] args) {
Timer t = new Timer();
t.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(go)){
ti1 = Integer.parseInt(t1.getText());
ti2 = Integer.parseInt(t2.getText());
tr.run();
}else if(e.getSource().equals(stop)){
tr.interrupt();
}
}
}
So back to my problem:
If I run the program and hit the 'Go'-Button after entering some numbers the program gets stuck. I think the issue is caused by the while-loop in TThread.
It's quite a time since I last used Threads and now i searched for a long time and nothing worked for me...
Hopefully someone can tell me what the issue is and can give a solution or some hints how to solve the problem.
Greetings
max.
You never run the thread in a background thread by calling start() on it. Instead you call run() which runs it on the current thread and not in a background thread. To solve this, call start() on your Thread object, not run().
so not:
tr.run();
but rather:
tr.start();
Other issues:
You're generally better off having classes implement Runnable rather than extend Thread.
You're trying to make Swing calls from a background thread which shouldn't be done. Almost all Swing method calls should be done on the Swing event thread or EDT. For more on this, please see: Concurrency in Swing.
One of your class names, Timer, is the same as a critical Swing class, the javax.swing.Timer class. I'd rename your class to avoid confusion, especially if you would want to use a Swing Timer.
And in fact on view of your code, I think that you would be much better off using a Swing Timer instead of a background Thread for your application. This is a much easier way to do your timer animation and makes it much easier to ensure that Swing calls are made on the Swing event thread. Please check the Swing Timer tutorial.
You are using null layout. While to a newbie a null layout often appears to be the best way to easily create complex GUI's, as you gain more Swing GUI experience you will find that actually the opposite is true. If you use layout managers, often nesting JPanels, each with its own layout manager, you can more easily create complex, beautiful GUI's, that easily resize, that look good on all platforms, and that are much easier to maintain, debug and enhance.
I want to keep executing work while a button is pressed, using Java. When the button is released, the work should stop. Something like this:
Button_is_pressed()
{
for(int i=0;i<100;i++)
{
count=i;
print "count"
}
}
How might I achieve this?
One way:
Add a ChangeListener to the JButton's ButtonModel
In this listener check the model's isPressed() method and turn on or off a Swing Timer depending on its state.
If you want a background process, then you can execute or cancel a SwingWorker in the same way.
An example of the former:
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class ButtonPressedEg {
public static void main(String[] args) {
int timerDelay = 100;
final Timer timer = new Timer(timerDelay , new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button Pressed!");
}
});
JButton button = new JButton("Press Me!");
final ButtonModel bModel = button.getModel();
bModel.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent cEvt) {
if (bModel.isPressed() && !timer.isRunning()) {
timer.start();
} else if (!bModel.isPressed() && timer.isRunning()) {
timer.stop();
}
}
});
JPanel panel = new JPanel();
panel.add(button);
JOptionPane.showMessageDialog(null, panel);
}
}
I want to keep executing work while a button is pressed
Execute that process in another thread and then your form is not block and you can press the button to cancel or stop the execution.
see :
How to stop threads of a Java program?
Stop/cancel SwingWorker thread?
Control thread through button
You may need to use mousePressed event to start the action
And use mouseReleased event to stop the action (This is neccesary)
For more information refer here
For Android Apps
I know this question is old, but you can use:
while (yourButton.isPressed()) {
// Do Stuff
}
I am creating a popup JFrame that will have a message and yes/no buttons. I am using this method in 2 ways. In 1, the main program calls this method and in the other, this method is called directly after a previous JFrame is closed. This method works when being called form the main program, but when another JFrame calls it, the JFrame created in this method shows up completely blank and the GUI freezes. I cannot exit out of the JFrame, but I can move it. The freezing is a result of the Thread.yield because response is always null, but in what instances will the JFrame fail to be created properly?
Note: response is a static variable. Also when this JFrame is created by another JFrame, the original JFrame does not exit correctly. That JFrame has a JComboBox, and the selected option is frozen on the dropdown. When it does not call this method, it closes properly.
public static String confirmPropertyPurchase(String message)
{
response = null;
final JFrame confirmFrame = new JFrame("Confirm");
confirmFrame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
response = "No";
}
public void windowDeactivated(WindowEvent e) {
confirmFrame.requestFocus();
}
});
final JPanel confirmPanel = new JPanel();
final JButton yes = new JButton();
final JButton no = new JButton();
yes.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
response = "Yes";
confirmFrame.setVisible(false);
}
});
no.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
response = "No";
confirmFrame.setVisible(false);
}
});
final JLabel confirmLabel = new JLabel(" " + message);
yes.setText("Yes");
yes.setPreferredSize(new Dimension(100, 100));
no.setText("No");
no.setPreferredSize(new Dimension(100,100));
confirmFrame.add(confirmLabel, BorderLayout.CENTER);
confirmPanel.add(yes);
confirmPanel.add(no);
confirmFrame.add(confirmPanel, BorderLayout.AFTER_LAST_LINE);
confirmFrame.setPreferredSize(new Dimension(520, 175
));
confirmFrame.pack();
confirmFrame.setVisible(true);
while(response == null)
{
Thread.yield();
}
return response;
}
Again, you shouldn't be using a JFrame as a dialog. In fact your whole bit of code can be replaced with a simple JOptionPane. e.g.,
Component parent = null; // non-null if being called by a GUI
queryString = "Do you want fries with that?";
int intResponse = JOptionPane.showConfirmDialog(parent, queryString,
"Confirm", JOptionPane.YES_NO_OPTION);
myResponse = (intResponse == JOptionPane.YES_OPTION) ? "Yes" : "No";
System.out.println(myResponse);
And this:
while(response == null)
{
Thread.yield();
}
should never be called on the main Swing thread, the EDT or event dispatch thread. The reason the code works when it does is because you're calling this little bit above off of the EDT, but when you call it on the EDT it freezes the EDT and thus the entire GUI. Simply don't do it.
You can't do this, plain and simple. There's only one event thread, and while you're sitting in a loop waiting for somebody to click in your JFrame, you're tying up that thread such that no events can be handled.
Don't try to create your own dialog out of a JFrame -- use JOptionPane or a JDialog, which are designed to handle this situation for you internally.