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