In first, I'm using Eclipse IDE. So my question is: I create a progress bar, but I want to make it load according to the place where the program is. I have a refresh button, and when I click it my entire program update. What I want is a progress bar that accompanying the process of updating and ends when it ends.
Sorry if my English isn't the best, but I'm a young Portuguese developer.
my btn code
JButton btnActualizar = new JButton("\u21BB");
btnActualizar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
TxtIpExternoLoja.setText(" ");
TxtSSIDLoja.setText(" ");
TxtFirewallLoja.setText(" ");
TxtIpLojaEtho.setText(" ");
TxtMaskLojaEtho.setText(" ");
TxtGWLojaEtho.setText(" ");
TxtDns1LojaEtho.setText(" ");
TxtDns2LojaEtho.setText(" ");
TxtIpLojaWlan.setText(" ");
TxtMaskLojaWlan.setText(" ");
TxtGwLojaWlan.setText(" ");
TxtDns1LojaWlan.setText(" ");
TxtDns2LojaWlan.setText(" ");
TxtIpLojaVpn.setText(" ");
TxtMaskLojaVpn.setText(" ");
TxtGwLojaVpn.setText(" ");
TxtDns1LojaVpn.setText(" ");
TxtDns2LojaVpn.setText(" ");
// DefaultTableModel model = (DefaultTableModel)
// tablePing.getModel();
// model.setRowCount(0);
TxtTime.setText(" ");
i = 0;
t.start();
btnActualizar.setEnabled(false);
update();
}
});
my progressbar code:
JProgressBar progressBar = new JProgressBar(0, 15);
GridBagConstraints gbc_progressBar = new GridBagConstraints();
gbc_progressBar.insets = new Insets(0, 0, 0, 5);
gbc_progressBar.gridx = 3;
gbc_progressBar.gridy = 0;
PanelBotoes.add(progressBar, gbc_progressBar);
GridBagConstraints gbc_btnImprimir = new GridBagConstraints();
gbc_btnImprimir.insets = new Insets(0, 0, 0, 5);
gbc_btnImprimir.gridx = 5;
gbc_btnImprimir.gridy = 0;
PanelBotoes.add(btnImprimir, gbc_btnImprimir);
progressBar.setStringPainted(true);
progressBar.setValue(0);
t = new Timer(interval, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (i == 15) {
t.stop();
btnActualizar.setEnabled(true);
} else {
i++;
progressBar.setValue(i);
}
}
});
Take a look at this page: https://docs.oracle.com/javase/tutorial/uiswing/components/progress.html.
Specifically, the section on "Using Determinate Progress Bars" should be what you are looking for. The example code is a little complex, but probably about as simple as it can get with this stuff.
Take note: the example uses a SwingWorker (more on those here) to update the progress value. This is because the progress bar is drawn in the Swing thread and won't be updated if the process is running on that thread too.
You will need to update your program on a thread which is not the Swing thread.
Edit 1 - For your question update with code
So it looks like you've got the idea with the progress bar code. I've not run it, but what you've got looks like it should work. Your next step is to replace the timer with the update() methods process.
To do this you'll need to do the following:
Make sure your update() method is running in a thread separate from the swing thread (something like a SwingWorker could be used here).
From within the update thread you need to call progressBar.setValue(x) when you want to update the bar, where x = how far your process has got.
Add some more calls to progressBar.setValue(x) in the update thread. You can put these wherever you like, but it's probably best to put them before and after long processes.
Note: you have to use threads for progress bars. This means you could run into things like deadlock and race conditions. Be careful!
Related
So I have been having some trouble trying to create a teletype effect for my swing program. I essentially want to update a JFrame at 40ms increments with a new letter, "typing" out a message to the user. However, it flickers a lot when I try to do this. The method is below:
public static void animateTeletype(String input, JTextArea displayArea)
throws InterruptedException {
displayArea.setText("");
String s = "";
for(int i = 0; i<input.length(); i++) {
s += input.substring(i, i+1);
displayArea.setText(textToDisplay);
Thread.sleep(40);
displayArea.update(displayArea.getGraphics());
}
}
I figure the problem stems from updating the text too fast, and it has to update more than it can handle. I am not sure how I would go about this issue, as reducing tick time will make text scroll too slowly. Any advice is appreciated!
** I've solved the problem. This is my new code:
static Timer timer = null;
public static void animateTeletype(final String input, final JTextArea displayArea) throws InterruptedException
{
final String[] s = new String[1];
s[0] = " ";
final int[] i = new int[1];
i[0] = 0;
displayArea.setText("");
timer = new Timer(30, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
s[0] = input.substring(i[0], i[0]+1);
i[0]++;
displayArea.append(s[0]);
if(displayArea.getText().equals(input))
timer.stop();
}
});
timer.start();
}
displayArea.update(displayArea.getGraphics());
Don't use the update() method. There is never any reason to do that. Get rid of that statement.
Swing components will automatically repaint themselves.
displayArea.setText(textToDisplay);
Don't uset setText(...) to add new text.
Instead you should be using:
displayArea.append( "some more text" );
Don't use Thread.sleep(40) for animation. It you want animation then use a Swing Timer to schedule the animation.
I suggest you look at other section of the tutorial for Swing basics. Maybe something like How to Use Text Fields.
I've created a tool where I paste some data in a text area and this data is being split per lines by (\n) in an array.
My tool works perfect, I just need to connect this progress of the array to the progress bar so the user may know what's going on.
so if the array will have 10 lines the progress bar shall start from one and count till it reaches ten when the tool moves to the next line.
so I mean when it starts working on the array in position 0, the progress bar shall show 1, and when the array moved to position 1, progress bar shall show 2 .......
Here is an example of my code:
// Run button (start the search)
final JButton btn = new JButton("Run");
btn.addActionListener(new ActionListener() {
#SuppressWarnings("resource")
public void actionPerformed(ActionEvent e) {
try {
String getTextArea;
getTextArea = textArea.getText();
// converting the input to an array
String[] arr = getTextArea.split("\\n");
// clearing the text
textArea_1.setText("");
//line = arr.length;
// looping for the input
// doing something.....
}
// end of for loop
} catch (Exception e2) {
JOptionPane.showMessageDialog(null, "Search was not completed due to bad connection, please try pressing run again or close the tool and reopen it");
}
}
});
// Creating the progress bar
JProgressBar progressBar = new JProgressBar();
progressBar.setStringPainted(true);
progressBar.setValue(0);
for(int z = 0; z <= line; z++) {
progressBar.setValue(z);
z = z + 1;
progressBar.repaint();
}
progressBar.setBounds(364, 11, 139, 22);
contentPane.add(progressBar);
Thank you for your help in advance
I've interpreted your question as how do I get the line number to be displayed instead of the percentage?
If that is the question, then you need to use the JProgressBar's setString(String s) method as well as setValue(int n)
For example:
// Set up of the JProgressBar
final int MIN = 0;
final int MAX = 100;
JProgressBar progressBar = new JProgressBar(MIN, MAX);
progressBar.setStringPainted(true); // show the text on the progress bar
progressBar.setString("Loop no. " + MIN); // initial display
// Code to update the JProgressBar
for (int i=MIN; i<=MAX; i++) {
progressBar.setValue(i);
progressBar.setString("Loop no. " + i);
}
Personally I prefer to use an implementation of BoundedRangeModel when working with progress bars. Swing provides DefaultBoundedRangeModel which is good for most tasks.
Remember to use concurrency correctly in your implementation, otherwise your interface will be unrespsonive if the task is long. SwingWorker can assist you with this https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html
I have a program that processes some files. From time to time, I need to stop it in the middle of processing, but am having difficulty with how to accomplish that. I have seen several possibilities, but I'm not sure which to pursue. Is it multithreading, like in a game? I found some information on cancelling, but it seems like it only applies while data is being inputted? I'm including the code for my gui below as maybe I just did something wrong?
To be clear, the goal is to stop the program no matter where it is in processing...
private JRadioButton blockButton, unblockButton;
private JButton btnCancel;
private ButtonGroup group;
private JLabel text;
private JButton enter;
public Gui(){
super("Download CORS files");
setLayout(null);
text = new JLabel("Would you like to download data in a block of days or intermittently over time?");
add(text);
blockButton = new JRadioButton("Block of Days", true);
unblockButton = new JRadioButton("Intermittent Days", false);
btnCancel = new JButton("Cancel run");
add(blockButton);
add(unblockButton);
add(btnCancel);
group = new ButtonGroup();
group.add(blockButton);
group.add(unblockButton);
// Get the size of the screen
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
// Determine the new location of the window
int w = this.getSize().width;
int h = this.getSize().height;
int x = ((dim.width-w)/2)-200;
int y = ((dim.height-h)/2)-200;
// Move the window
this.setLocation(x, y);
enter = new JButton("Enter");
enter.addActionListener(this);
add(enter);
text.setBounds(5,5,700,25);
blockButton.setBounds(5, 25, 300, 25);
unblockButton.setBounds(5,50, 300, 25);
enter.setBounds(75,100,100,20);
btnCancel.setBounds(300,100,100,20);
btnCancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}});
Two ways to stop processing, depending on the situation
Stop processing I/O: If you need to break out of an I/O process, IMO the best way to do this is to close the Stream(s), especially for Reader threads. You may get an IOException thrown, but this is what Exceptions are for
Intense computation/processing: If you want to stop an intense processing loop, you should call Thread.interrupt() on the processing Thread. If you have written the processing code, you can check on Thread.interrupted() status somewhere in your loop/code. On the other hand, if you are using 3rd party code, this may or may not work
In my program, there is a button, "Display", and another button, "Reset".
The user enters the number of prime numbers they want in the text field and then clicks the "Display" button. Then, the first x prime numbers will appear in the text area.
In the code, I have:
Declarations:
Thread go;
Thread newThread;
JLabel howManyLabel;
JTextField howMany;
JButton display;
JButton reset;
JTextArea primes;
Action Event:
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == display) {
display.setEnabled(false);
if (go == null) {
go = new Thread(this);
go.start();
} else {
newThread = new Thread(this);
newThread.start();
}
} else if (source == reset) {
display.setEnabled(true);
howMany.setText(" ");
primes.setText(" ");
}
}
Run method:
public void run() {
int quantity = Integer.parseInt(howMany.getText());
int numPrimes = 0;
int candidate = 2; // candidate = the number that MIGHT be prime
primes.append("First " + quantity + " primes:");
while(numPrimes < quantity) {
if (isPrime(candidate)) {
primes.append(candidate + ", ");
numPrimes++;
}
candidate++;
}
}
The run() method is in the same class, and simply calculates the first x amount of prime numbers.
I am trying to create a new thread every time the "Reset" button is called. The thread runs the first time, but then does not run again after I click "Reset". Can the run() method only work once?
Thanks in advance.
The run() method is just like any other method and can be invoked any number of times. The method that cannot be invoked multiple times is start()(according to Thread).
Your explanation does not seem to fit with the code you gave. You say you want to spawn a new thread when a user clicks reset, yet you only construct or start threads if the source is Display. Did you mean, rather, that you want to cancel the last thread and enable controls for the user to start again? In that case you should use a Future, not a generic thread.
Another thing is that UI components are generally not thread-safe. Swing explicitly warns against it on every components JavaDoc. What you may be seeing is just components not updating their visible state when they are changed from a different thread. Have you tried using a debugger to see if a thread is actually not getting spawned, or it is being spawned, but not having the result you want?
I've implemented a count down timer(in function) which updates a label in swing panel every second this is the code:
public void DefineTimer()
{
Action updateClockAction = new AbstractAction() {
public void actionPerformed(ActionEvent e){
JPanelMainGame.this.jLabelSeconds.setText(Integer.toString(JPanelMainGame.this.m_TimerTotalSeconds));
JPanelMainGame.this.jLabelSeconds.setFont(new java.awt.Font("Lucida Handwriting", 1, 36));
JPanelMainGame.this.jLabelSeconds.setForeground(Color.red);
JPanelMainGame.this.jLabelSeconds.setVisible(true);
if( JPanelMainGame.this.m_TimerTotalSeconds >0)
{
JPanelMainGame.this.m_TimerTotalSeconds--;
}
else if ( JPanelMainGame.this.m_TimerTotalSeconds == 0)
{
JPanelMainGame.this.m_Timer.stop();
JPanelMainGame.this.jLabelSeconds.setText("0");
System.out.println("!m_WasGameDecisived: "+!m_WasGameDecisived);
JPanelGameApplet gameApplet = (JPanelGameApplet) getTopLevelAncestor();
//Checking whether time ended for both players and no solution was recieved
if(gameApplet.GetJPanelChooseGame().GetGameType() == eGameType.Net)
{
gameApplet.GetClinetThread().UpdateServerOfTimeEnded();
if (!m_WasGameDecisived)
{
//
System.out.println("Tie - No one had a solution in the given time");
System.out.println("Before send request to solve - Is Socket Closed:"+((JPanelGameApplet)
gameApplet.GetClinetThread().SendRequestToClosePlayerThreadAndRemoveItFromPlayersOnServer();
((JPanelGameApplet)getTopLevelAncestor()).GetDJ().stop();
Menu.BrowseTo(PanelMenuNumber.k_ChooseGame, JPanelMainGame.this.getParent());
((JPanelGameApplet)getTopLevelAncestor()).GetDJ().play(0);
}
}
else if(gameApplet.GetJPanelChooseGame().GetGameType() == eGameType.Single)
{
JPanelMainGame.this.showPopUpSelectionBar();
}
}
((JPanelGameApplet)getTopLevelAncestor()).GetNetMainGame().Initialize();
}
};
m_Timer = new Timer(1000, updateClockAction);
}
Now my problem is in another part of my code when I want to to the following things:
case ProtocolMessages.k_StartGame:
m_GameApplet.GetJpanelStartNetGame().DefineTimer();
m_GameApplet.GetJpanelStartNetGame().GetTimer().start();
m_GameApplet.ShowBoardToSolve();
Menu.BrowseTo(PanelMenuNumber.k_NetPlayersGameStart,m_GameApplet.GetJPanelNetGameSetting().getParent());
m_GameApplet.GetDJ().Next();
break;
So The problem is when I want to start a game, I'm defining my timer and allocating it,
give it start command and going to the screen that I should see there the timer (JLabel updating).
And still although it should be already counting (even before that screen that shows the timer) I still got delay: I get the panel that show the timer, and after about two seconds the Jlabel appear and start to count down.
I think that it is because the event dispatch thread that is not updating immediately the Jlabel in the time I'm doing Jlabel.setText()
Any suggestions of how can I start a game without delay in showing the Jlabel?
Thanks
Call SwingUtilities.invokeAndWait frm the thread to set the label text.