Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

QuickTime MovieController-like swing implementation



(Cross-posted to java-dev and quicktime-java.)

I have had problems in the past related to getting a MovieController to display consistently in certain situations. I wanted to use MovieController because I wanted the QT-standard widget, to confuse newbie users of my software as little as possible.

After much trying and many suggestions from the helpful, I gave up. Perhaps I could make it work if I tried just the right AWT voodoo (other people seem to have no trouble, albeit not in as tight a situation as I face); perhaps not. Either way, the problem became a concord fallacy and I decided to cut my losses.

My workaround is to not use MovieController, which is an AWT widget; instead I wrote my own widget using regular Swing widgets. This works perfectly. I give my code here in case it might help someone someday searching the archives. Code notes follow.


private class EnhancedMovieController extends JPanel { private final Thread movieWatcher; private boolean keepWatchingMovie = true; private int watchHowOften = 100;

private final Movie movie;
private final JProgressBar mProgress = new JProgressBar( 0, 100 );
private final LabelButton bReset = new LabelButton( "<<" );
private final LabelButton bPlay = new LabelButton( ">" );



public EnhancedMovieController( Movie m ) { this.movie = m;

// set up the progress bar
this.mProgress.setBorder( BorderFactory.createEtchedBorder() );
try {
this.mProgress.setMaximum( movie.getDuration() );
} catch( QTException qte ) {}


// set up the listeners which map mouse input on the progress bar
// to changes in movie play
MouseInputAdapter lineProc = new MouseInputAdapter() {
private float savedRate = 0.0f;
public void mousePressed( MouseEvent e ) {
try {
this.savedRate = movie.getRate();
movie.stop();


                    double clickPlace = e.getX();
                    double barWidth = mProgress.getSize().width;
                    double widthRatio = clickPlace / barWidth;
                    int movieDur = movie.getDuration();
                    double durClickResult = widthRatio * movieDur;
                    int resultAsInt = (int) durClickResult;

                    mProgress.setValue( resultAsInt );
                    movie.setTimeValue( resultAsInt );
                    } catch( QTException qte ) {}
                }

public void mouseDragged( MouseEvent e ) {
// i can't fucking believe how stupidly hard it is to do arithmatic in java
// i mean seriously this should be trivial
// totally fucking unbelievable
try {
double clickPlace = e.getX();
double barWidth = mProgress.getSize().width;
double widthRatio = clickPlace / barWidth;
int movieDur = movie.getDuration();
double durClickResult = widthRatio * movieDur;
int resultAsInt = (int) durClickResult;


                    mProgress.setValue( resultAsInt );
                    movie.setTimeValue( resultAsInt );
                    } catch( QTException qte ) {}
                }

                public void mouseReleased( MouseEvent e ) {
                    try {
                    movie.setRate( this.savedRate );
                    } catch( QTException qte ) {}
                }
            };
            this.mProgress.addMouseListener( lineProc );
            this.mProgress.addMouseMotionListener( lineProc );

            // set up the movie watching thread
            this.movieWatcher = new Thread() {
                public void run() {
                    while( keepWatchingMovie ) {
                        try {

                        if( movie.getRate() > 0 ) {
                            watchHowOften = 10;
                            mProgress.setValue( movie.getTime() );
                        }

                        if( movie.isDone() ) {
                            watchHowOften = 100;
                            mProgress.setValue( movie.getDuration() );
                            movie.stop();
                            bPlay.setText( ">" );
                        }

                        this.sleep( watchHowOften );

                        } catch( QTException qte ) {
                        } catch( InterruptedException qte ) {
                        }
                    }
                }
            };
            this.movieWatcher.start();

            // set up the reset and play buttons
            Font f = new Font( null, Font.BOLD, 9 );
            this.bReset.setFont( f );
            this.bPlay.setFont( f );

            this.bReset.addActionListener( new ActionListener() {
                public void actionPerformed( ActionEvent e ) {
                    try {
                        movie.goToBeginning();
                        mProgress.setValue( 0 );
                    } catch( Exception exc ) {}
                }
            } );

this.bPlay.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
try {
if( bPlay.getText().equals( "||" ) ) {
movie.stop();
bPlay.setText( ">" );
} else {
if( movie.getTime() >= movie.getDuration() ) {
movie.goToBeginning();
}
movie.start();
bPlay.setText( "||" );
}
} catch( Exception exc ) {}
}
} );


int squareSide = Math.max( Math.max( bReset.getPreferredSize().width, bReset.getPreferredSize().height ),
Math.max( bPlay.getPreferredSize().width, bPlay.getPreferredSize().height ) );
Dimension d = new Dimension( squareSide, squareSide );


            this.bReset.setMinimumSize( d.getSize() );
            this.bReset.setPreferredSize( d.getSize() );
            this.bReset.setMaximumSize( d.getSize() );
            this.bPlay.setMinimumSize( d.getSize() );
            this.bPlay.setPreferredSize( d.getSize() );
            this.bPlay.setMaximumSize( d.getSize() );

            this.bReset.setHorizontalAlignment( SwingConstants.CENTER );
            this.bPlay.setHorizontalAlignment( SwingConstants.CENTER );

            // lay everything out
            this.setLayout( new GridBagLayout() );
            GridBagConstraints c = new GridBagConstraints();
            c.fill = c.BOTH;

            this.add( this.bPlay, c );
            c.weightx = 1;
            this.add( this.mProgress, c );
            c.weightx = 0;
            this.add( this.bReset, c );

            this.setBorder( BorderFactory.createEtchedBorder() );

try {
int width = this.movie.getBounds().getWidth();
if( width <= 20 ) {
width = 180;
}
Dimension size = new Dimension( width, this.getPreferredSize().height );
this.setMinimumSize( size.getSize() );
this.setPreferredSize( size.getSize() );
this.setMaximumSize( size.getSize() );
} catch( QTException qte ) {}
}


        public void play( float rate ) {
            try {
                this.movie.setRate( rate );
            } catch( QTException qte ) {}
        }
    }




This could be improved to provide volume control. EnhancedMovieController does not display the actual movie, it only controls the movie. You must lay out the movie in a MoviePlayer somewhere. Note that a LabelButton is another custom class which is simply a Label which behaves like a button. Here, I'll give that code too.




/**
* This is a cheater button. It's just a label with clickability. We use this
* because Aqua buttons are ugly when lots are grouped close together.
*/
public class LabelButton
extends JLabel
implements MouseListener {


// ---- v a r i a b l e d e c l a r a t i o n s ---------------------- //

    private EventListenerList actionListeners = new EventListenerList();

// ---- p u b l i c a p i -------------------------------------------- //

    /**
     * Returns a LabelButton which displays s.
     */
    public LabelButton( String s ) {
        super( s );
        this.setBorder( BorderFactory.createEtchedBorder() );
        this.addMouseListener( this );
    }

    /**
     * Returns a LabelButton which displays s.
     */
    public LabelButton( char c ) {
        this( String.valueOf(c) );
    }

    /**
     * Returns a LabelButton which displays i.
     */
    public LabelButton( Icon i ) {
        super( i );
        this.setBorder( BorderFactory.createEtchedBorder() );
        this.addMouseListener( this );
    }

    public void addActionListener( ActionListener listener ) {
        actionListeners.add( ActionListener.class, listener );
    }

    // MouseListener

    public void mouseClicked( MouseEvent e ) {
        fireActionPerformed();
    }

    public void mouseEntered( MouseEvent e ) {
        this.setForeground( SystemColor.textHighlightText );
        this.setBorder( BorderFactory.createRaisedBevelBorder() );
    }

    public void mouseExited( MouseEvent e ) {
        this.setForeground( SystemColor.BLACK );
        this.setBorder( BorderFactory.createEtchedBorder() );
    }

    public void mousePressed( MouseEvent e ) {
        this.setBorder( BorderFactory.createLoweredBevelBorder() );
    }

    public void mouseReleased( MouseEvent e ) {
        this.setBorder( BorderFactory.createRaisedBevelBorder() );
    }

// ---- p r i v a t e c o n v e n i e n c e m e t h o d s ---------- //

protected void fireActionPerformed() {
EventListener [] listeners = this.actionListeners.getListeners( ActionListener.class );
for( int i = 0; i < listeners.length; i++ ) {
ActionListener listener = (ActionListener) listeners[ i ];
listener.actionPerformed( new ActionEvent( this, 0, "LabelButton-Pressed" ) );
}
}


}


peace Nicholas

_______________________________________________
Do not post admin requests to the list. They will be ignored.
QuickTime-java mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/quicktime-java/email@hidden

This email sent to email@hidden


Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.