Java - A modeless waiting dialog with dynamic text - java

I need to create a dialog (message) box with the following requirements:
It should be able to change it text during it visibility period by adding periodically 1 dot to the current text it displays.
It should be modeless to avoid blocking the work of the main process. It is only a notification message for the user that a work is being processed.
It should be displayed when the process starts and disappeared when it ends. I don't mind to call it explicitly becuase I don't know how much time the task will take in advance.
The dialog should be displayed several times, each time with a different base text.
I have tried to create a modeless dialog like this:
try{
String laf = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(laf); // tell the UIManager to change the look and feel
}
catch (Exception e)
{
System.out.println("Unable to change look and feel");
}
m_optionPane = new JOptionPane(a_sText, JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION, null, new Object[]{}, null);
m_dialog = new JDialog();
m_dialog.setSize(200, 50);
m_dialog.setTitle(a_sTitle);
m_dialog.setModal(false);
m_dialog.setContentPane(m_optionPane);
m_dialog.setLocationRelativeTo(null);
m_dialog.setAlwaysOnTop(true);
m_dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
m_dialog.pack();
public void showDialog(String a_sText, boolean a_bDynamic){
if(a_bDynamic){
m_runnable = new DynamicWait(m_optionPane, a_sText);
m_thread = new Thread(m_runnable);
m_thread.start();
}else{
m_optionPane.setMessage(a_sText);
}
m_dialog.setVisible(true);
}
public void hideDialog2(){
if (m_thread != null){
m_thread.interrupt();
m_runnable = null;
m_thread = null;
}
m_dialog.dispose();
}
and then use a thread to constantly add the dots..
public class DynamicWait implements Runnable {
public DynamicWait(JOptionPane a_optionPane, String a_sText){
Log4jWrapper.writeLog(LogLevelEnum.WARN, "DynamicWait - " + a_sText + " Thread ID " + Thread.currentThread().getId());
m_optionPane = a_optionPane;
m_sText = a_sText;
}
#Override
public void run() {
while(m_bRun){
try {
m_optionPane.setMessage(m_sText);
Thread.sleep(1000);
m_optionPane.setMessage(m_sText + ".");
Thread.sleep(1000);
m_optionPane.setMessage(m_sText + "..");
Thread.sleep(1000);
m_optionPane.setMessage(m_sText + "...");
Thread.sleep(1000);
} catch (InterruptedException e) {
Log4jWrapper.writeLog(LogLevelEnum.WARN, e.getMessage());
}
}
}
public void stopRun(){
m_bRun = false;
}
Well, all in all, I couldn't get the proper results.
I'll appreciate your advise.
Thank you.

Related

Use JAVA timer in the background without causing any lag in the UI

I am making a java application that send data automatically to my remote server.
What i need is to insert data without feeling lag to the end user. the remote db update part should be run in the background. i tried swingworker, thread but nothing worked. still lags my app. here is what i have done so far
public class uploader extends Thread {
static Socket socket;
static Timer ttt;
public void run() {
try {
ttt = new Timer(15000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
socket = new Socket("192.168.10.1", 3306);
//upload
ResultSet rs = DB.search("select query,id FROM general_log where state = 0 order by id asc");
while (rs.next()) {
try {
socket = new Socket("192.168.10.1", 3306);
DB2.acknowledge(rs.getString(1));
DB.acknowledge("update general_log set state = 1 where id = '" + rs.getString(2) + "'");
} catch (Exception e1) {
e1.printStackTrace();
System.out.println("error");
break;
}
}
} catch (Exception e3) {
System.out.println("error");
e3.printStackTrace();
}
}
});
ttt.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
And i run it on the start up
Thread upl = new Thread(new uploader());
upl.start();
every 15 second local data should upload to the remote server. but in here my UI lags ever 15 sec when the timer runs.
how can i do it without causing a lag?
Thanks in advance.
You could optimize your SQL query with index, that's for sure.
Besides regarding main question wouldn't it be better to use Timer Task that starts up in new Handler() ?
===========================================
for example instead of class create a method:
private final Handler handler = new Handler();
private TimerTask timerTask;
private Timer timer = new Timer();
...
public void sendBackgroundData() {
timerTask = new TimerTask() {
#Override
public void run() {
handler.post(() -> {
DO YOUR CODE
}
});
}
};
timer.schedule(timerTask, 0, 2000);
}

JProgressBar doesn't update during download

Using a swing button, I'm trying to download an html file and write it to a new html file, while doing a progress bar. When I click the button, my program seems to freeze until the download finishes, and then the progress bar is suddenly 100%. I'm not quite sure how to fix this problem as I am new to java.
private void jButton2MouseReleased(java.awt.event.MouseEvent evt) {
try {
URL oracle = new URL("http://mywebsite.com");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
String input_path = "d:/website/updatedsite.html";
WriteFile data = new WriteFile(input_path, false);
int length = yc.getContentLength();
int current = 0;
jProgressBar1.setMaximum(length);
jProgressBar1.setValue(0);
while ((inputLine = in.readLine()) != null) {
data.writeToFile(inputLine);
int i = 0;
for (i = 0; i < length; i++) {
jProgressBar1.setValue(i);
}
}
in.close();
}
catch (java.io.IOException e) {
JOptionPane.showMessageDialog(Frame1.this, "Error " + e.getMessage());
}
}
This is because you're both downloading and updating the progress bar in the same thread - that's why the gui gets actually updated AFTER the download is finished.
Use a separate worker thread for downloading like explained here and it should work.
I'd suggest using a SwingWorker. It's made for problems such as this. Here is a snippet from some code from my codebase that uses an indeterminate progress bar, but it'll help give you a general idea of what to do (vui is a JFrame):
vui.clearOutput();
vui.setOutput("Waiting for items to copy...\n"
+ "This could take several minutes. Please standby...");
vui.disableExit();
vui.disableInput();
vui.disableNext();
vui.showProgressBar();
// make thread so you can disable all options when zipping and enable progress bar
SwingWorker transferWorker = new SwingWorker() {
#Override
protected Void doInBackground() throws Exception {
try {
Process p = Runtime.getRuntime().exec("resources/bin/transferCopier.bat");
StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");
StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(), "OUTPUT");
errorGobbler.start();
outputGobbler.start();
p.waitFor();
} catch (IOException ex) {
Logger.getLogger(VaderController.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ie) {
Logger.getLogger(VaderController.class.getName()).log(Level.SEVERE, null, ie);
}
return null;
}
#Override
public void done() {
vui.hideProgressBar();
vui.clearOutput();
vui.setOutput("Transfer Complete!\n\n"
+ "Push \"Exit\" to quit.\n\n");
vui.enableExit();
mode = VaderMode.END;
}
};
transferWorker.execute();
When transferWorker.execute(); is performed, doInBackground() is invoked. Once doInBackground() is done doing its computations, done() is then invoked. done() is where you would do any final updates to the GUI.
The key things to note about my code above is that I enable the progress bar before executing the SwingWorker then when the SwingWorker is done executing, I disable the progress bar.
Resources:
http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

Indeterminate Progress bar wont show

I have an application that copies files (via ADB) to an android tablet. It takes some time so I want to display a popup with an indeterminate progress bar on it. When the copy task is complete then I want to be able to stop the progress bar and let the user close the dialog.
At the moment I have not added the extra dialog box and am just trying to get the progress bar working. The problem I have is that the progress bar is not showing at the start of the task, but I dont know why. The progressbar shows when the dialog box saying sync complete appears. The code is:
progress = new JProgressBar(0, 100);
progress.setForeground(new Color(255, 99, 71));
progress.setIndeterminate(true);
progress.setValue(0);
progress.setPreferredSize( new Dimension( 300, 20 ) );
progress.setBounds( 278, 12, 260, 20 );
progress.setVisible(false);
progress.setString("Sync in progress");
progress.setStringPainted(true);
contentPane.add(progress);
pushtotab = new JButton("");
pushtotab.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (buildpathset==1){
try{
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
progress.setVisible(true);
wiredsync();
}finally{
JOptionPane.showMessageDialog(null, "sync complete. ",null, buildpathset);
setCursor(Cursor.getDefaultCursor());
progress.setVisible(false);
}}else{
//warning in here later - TO Do
}
}
});
public void wiredsync(){
try {
Process process = Runtime.getRuntime().exec("adb" + " push "+ buildpath + " " + adbtabletsync);
InputStreamReader reader = new InputStreamReader(process.getInputStream());
Scanner scanner = new Scanner(reader);
scanner.close();
int exitCode = process.waitFor();
System.out.println("Process returned: " + exitCode);
} catch(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//end
Thanks for the help,
Andy
pooyan has the right idea -- do the long running process in a background thread -- but gives the wrong library example, since your program is a Swing program and not an Android program. The canonical answer to this for Swing is to do your long-running task in the doInBackground() method of a SwingWorker.
Please hold while I find a better example...
Something like so:
if (buildpathset == 1) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
progress.setVisible(true);
// create my SwingWorker object
final SwingWorker<Void, Void> myWorker = new SwingWorker<Void, Void>() {
protected Void doInBackground() throws Exception {
// here is my long running task, calling in background
// thread
wiredsync();
return null;
};
};
// this allows me to be notified when the SwingWorker has
// finished
myWorker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// if the SwingWorker is done
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
// notify the user
JOptionPane.showMessageDialog(null, "sync complete. ",
null, buildpathset);
setCursor(Cursor.getDefaultCursor());
progress.setVisible(false);
try {
// one way to catch any errors that occur in
// SwingWorker
myWorker.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
});
// run my SwingWorker
myWorker.execute();
} else {
// warning in here later - TO Do
}
For more on this, please check out: Lesson: Concurrency in Swing
i think your problem is that you don't use thread . I mean after you turn visibility of your progress bar to true , you should define your long task in a thread. I'm Not familiar with Swing But
take Look there for Swing (sorry if it's no use full):
http://www.java-tips.org/java-se-tips/javax.swing/how-to-handle-long-running-tasks-in-a-swing-applic.html
and there for android :http://www.mkyong.com/android/android-progress-bar-example/

Using Jinput to pop up a JFrame WIndow alarm

Using Jinput and Java in Netbeans, I'm working on a very small project that simply Pops up a JFrame alarm window when lets say a user presses down on the 'K' on the keyboard and terminates the JFrame alarm window when the user lets go of 'k'. In my code, I seemed to get stuck in the while loop as the JFrame opened on the first press down and couldn't seem to close. I researched and I found that using javax.swing.Timer was the better way to do it. However, since I'm a newbie at this, all the different ways to use timer just made me even more confused. Could someone please see my code and point me in the right direction?
Here is my code;
public void startPolling() {
while(true) {
ControllerEnvironment.getDefaultEnvironment().getControllers();
ca[index].poll();
EventQueue queue = ca[index].getEventQueue();
Event event = new Event();
while(queue.getNextEvent(event)) {
StringBuffer buffer = new StringBuffer(ca[index].getName());
buffer.append(" at ");
buffer.append(event.getNanos()).append(", ");
Component comp = event.getComponent();
buffer.append(comp.getName()).append(" changed to ");
float value = event.getValue();
if(comp.isAnalog()) {
buffer.append(value);
} else {
if(value==1.0f) {
buffer.append("On");
if ("K".equals(comp.getName())){
alarmBox();
}
} else {
buffer.append("Off");
if ("K".equals(comp.getName())){
alarmBox.setVisible(false);
}
}
}
System.out.println(buffer.toString());
}
}
}
alarmBox() is my JFrame.
I was working on it and here is my updated code:
public void startPolling() {
Timer timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
ca[index].poll();
EventQueue queue = ca[index].getEventQueue();
Event event = new Event();
while(queue.getNextEvent(event)) {
StringBuffer buffer = new StringBuffer(ca[index].getName());
buffer.append(" at ");
buffer.append(event.getNanos()).append(", ");
Component comp = event.getComponent();
buffer.append(comp.getName()).append(" changed to ");
float value = event.getValue();
if(comp.isAnalog()) {
buffer.append(value);
} else {
if(value==1.0f) {
buffer.append("On");
if ("K".equals(comp.getName())){
alarmBox();
}
} else {
buffer.append("Off");
if ("K".equals(comp.getName())){
alarmBox.dispose();
}
}
}
System.out.println(buffer.toString());
}
try {
Thread.sleep(20);
} catch (InterruptedException f) {
f.printStackTrace();
}
}
}); timer.start();
if you just want to open and close window,y to use timer?
you have a very complicated code,for a simple task.
you can add a ComponentListener to your JFrame to hide,somthing like this:
frame.addComponentListener(new ComponentAdapter(){
public void componentMoved(ComponentEvent e) {
if (popup.isVisible()){
popup.setVisible(false);
}
}
});

JPanel doesn't load in JFrame

I have a problem showing my progress bar when reading a file in Java.
All works as intended, user choose a file, the program must show the progress bar (but it loads an empty blank frame), process the file and then load the results on another window.
I can't get the program to show the content of the progress bar dialog.
A little help here would be really appreciated.
Here is the code of the 3 methods involved.
//this method reads the file
public void processFile(File arch) {
aFile = arch;
Thread threadForSearch = new Thread() {
#Override
public void run() {
try{
listaProveedoresTango = controladoraConsultas.traerProveedores();
listaProveedoresAFIP = new LinkedList();
BufferedReader data = new BufferedReader(new FileReader(aFile));
String s;
while ((s = data.readLine()) != null) {
//long task
}
data.close();
}catch (Exception e){
System.err.println("Error: " + e.getMessage());
}
}
};
interfacesController.loadProgressBar();
threadForSearch.start();
try {
threadForSearch.join();
} catch (InterruptedException ex) {
Logger.getLogger(Controladora.class.getName()).log(Level.SEVERE, null, ex);
}
this.interfacesController.closeProgressBar();
this.interfacesController.loadResults(someStuff);
}
//load a progress bar
public void loadProgressBar(){
JProgressBar pb = new JProgressBar(0,100);
pb.setPreferredSize(new Dimension(175,20));
pb.setString("Processing Data");
pb.setStringPainted(true);
pb.setIndeterminate(true);
JLabel infoLabel = new JLabel("Reading File: ");
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent evt) {
exitSystem();
}
});
cancelButton.setVerticalAlignment(SwingConstants.CENTER);
JPanel center_panel = new JPanel();
center_panel.add(infoLabel);
center_panel.add(pb);
center_panel.add(cancelButton);
center_panel.setLayout(new BoxLayout(center_panel,BoxLayout.Y_AXIS));
dialog = new JDialog((JFrame)null, "Processing ...");
dialog.getContentPane().add(center_panel, BorderLayout.CENTER);
dialog.setSize(100, 100);
dialog.setLocationRelativeTo(null);
dialog.pack();
dialog.setVisible(true);
}
//close the open progress bar
public void closeProgressBar(){
this.dialog.dispose();
}
Solved with SwingWorker, i post a summarized code:
public void processFile(File arch) {
aFile = arch;
final SwingWorker searchOnFile = new SwingWorker(){
#Override
protected Object doInBackground() throws Exception {
try{
BufferedReader data = new BufferedReader(new FileReader(aFile));
String s;
while ((s = data.readLine()) != null) {
//long task
}
data.close();
}catch (Exception e){ //Catch exception if any
System.err.println("Error: " + e.getMessage());
}
interfacesController.closeProgressBar();
interfacesController.loadResults(someStuff);
return null;
}
};
interfacesController.showProgressBar();
searchOnFile.execute();
}
interfacesController contains all the methods to work with GUIs, showProgressBar() is used to show the bar and closeProgressBar() do the opposite. Thank you guys!
Short of more useful code, I suggest using a SwingWorker.
An abstract class to perform lengthy GUI-interaction tasks in a background thread. Several background threads can be used to execute such tasks. ..
Given the nature of the task, you might also look at ProgressMonitorInputStream.
..creates a progress monitor to monitor the progress of reading the input stream. If it's taking a while, a ProgressDialog will be popped up to inform the user. If the user hits the Cancel button an InterruptedIOException will be thrown on the next read. All the right cleanup is done when the stream is closed.

Categories

Resources