public class SeekBar extends JProgressBar {
private int updatedValue = 0; //sharing between different scopes
/**
* Update SeekBar position
* @param progress in microseconds
* @param totalVal in seconds
*/
public void updateSeekBar(long progress, float totalVal)
{
BackgroundExecutor.get().execute(new UpdatingTask(progress, totalVal)); //Another thread will calculate the relative position
setValue(updatedValue);
}
/**
* Task used for updating the seek value in another thread.
* @author Pierluigi
*/
private class UpdatingTask implements Runnable {
long progress; float totalVal;
public UpdatingTask(long progress, float totalVal) {
this.progress = progress;
this.totalVal = totalVal;
}
@Override
public void run() {
int lp = (int) (progress / 1000); //progress comes in microseconds
int seekLenght = getMaximum();
int n = (int) ((lp/(totalVal*1000))*seekLenght);
updatedValue = lastSeekVal+n;
}
}
///////////////////////////////////////////////////////////
/**
* New Constructor, sets a mouseListener
* (extends JProgressBar)
*/
public SeekBar()
{
super();
setMaximum(10000); //it's smoother this way
addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
float val = ((float)e.getX()/getWidth()) * getMaximum();
returnValueToPlayer(val);
setValue((int)val);
log("SeekBar pressed: " + val + " x: " + e.getX());
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
}
/**
* Informs the player about the relative value selected in the seekbar
* @throws BasicPlayerException
*/
private void returnValueToPlayer(float val){
//TODO inform our player
}
private void log(String str)
{
System.out.println("SeekBar] " +str);
}
}
As you can see I've used a simple MouseListener to implement what the a slider have native, by clicking in a certain x relative to the component I can set a correct value thanks to the power of proportions.
Let's recall that we don't want the swing single thread do math, even when it's this easy, for this we call a new Task executed by one background executor, since I want to have a central use of this class, I've implemented the following singleton:
/**
* Using this for computing outside swing UI thread
* @author Pierluigi
*
*/
public class BackgroundExecutor {
private static ExecutorService backgroundEx = Executors.newCachedThreadPool(); //UI thread shouldn't do math
public BackgroundExecutor(){}
public static ExecutorService get() { return backgroundEx;}
}
For more information about this see how a thread executor works. Now we can add and test our seekbar, let's add it into init() method from the MainView class like every simple other component.
SeekBar seekbar = new SeekBar(); ... //SeekBar seekbar.setBounds(5, 10, _W-15, 10); container.add(seekbar);
Nessun commento:
Posta un commento