Tải bản đầy đủ - 0 (trang)
Hack 68. Handling Dropped Picts on Mac OS X

Hack 68. Handling Dropped Picts on Mac OS X

Tải bản đầy đủ - 0trang

handingofftonon-Javacodethatmightbeabletoconvertthe

Picttosomethingthatcanhandletheformatmoregracefully.

Fortunately,thereisaJavasolutiontotheproblem,andit's

calledQuickTimeforJava(QTJ).ThisAPIisaJavawrapper

aroundthenativeQuickTimemultimediaAPI.It'savailablefor

MacOSXandWindows,butsinceaWindowsapplicationisn't

goingtopassyouaPict,youonlyneedtoworryabouttheMac

OSXcase.OneadvantageofallthisAPI-wrangling:QTJis

installedbydefaultonMacOSX,soyoucancountonitbeing

there.



EverythinginthishackisMac-specific.SincePictsareonlygoingtobe

anissueonMacOSX,don'tbotherwiththisonprogramsthatyou're

surewon'tneedtodealwithMacOSXdrops.



First,you'llneedtodefineaDataFlavorforPictdatainJavainput

streams:







macPictStreamFlavor=



newDataFlavor("image/x-pict;class=java.io.In



Next,takethecodefromthehackonhandlingstandard

droppedimages[Hack#67]andgivedrop()anewelseif()

{…}blocktodealwiththisflavor.Thisblockwillusea

QTJPictHelperclass,soyouneedtomakethatavailable(I'llshow

youthishelperclasssoon).Sinceyoudon'twanttoneedto

havethisclassatcompiletimethatwouldmakelifeharderfor

WindowsandLinuxusers,whomightnothavetheQTJava.zip

filetocompileagainstthiscodeusesreflectiontoloadthe

QTJPictHelperclassandinvokeitspictStreamToJavaImage():



















}elseif(trans.isDataFlavorSupported(macPictStreamFl



System.out.println("macpictstreamflavoris



InputStreamin=





(InputStream)trans.getTransferData(ma



//forthebenefitofthenon-maccrowd,thisi



//donewithreflection.directly,itwouldbe:



//Imageimg=QTJPictHelper.pictStreamToJavaIm











ClassqtjphClass=Class.forName("QTJPictHelpe







































}



Class[]methodParamTypes={java.io.InputStrea

Methodmethod=



qtjphClass.getDeclaredMethod("











metho

InputStream[]methodParams={in};

Imageimg=(Image)method.invoke(null,method

showImageInNewFrame(img);

gotData=true;



OK,nowforthefunpart:convertingtheinputstreamfromPict

datatoaJavaimage.Thiscodeisdrawnfromtechniquesinthe

bookQuickTimeforJava:ADeveloper'sNotebook(O'Reilly),

whichhasawholechapteronQuickDrawandhowtocallitfrom

Java.ThegistofthetechniqueistouseaGraphicsImporter,which

handlesvarioustypesofimagedata,toreadthePict.Fromthis

youcangetaGraphicsImporterDrawerthatallowsyoutogeta

QTImageProducer,whichisanAWTImageProducerand,ofcourse,can

produceanormaljava.awt.Image.

Example9-6showstheQTJPictHelperhelperclassImentioned

earlier.Unlikemostexamplesinthebook,thislistingincludes

theimportstatementsbecausetheQTJstuffwillbenewtomost

readers.



Example9-6.UsingQTJtohandleMacPictdatain

aTransferable

















































importjava.awt.*;

importjava.io.*;

importquicktime.*;

importquicktime.qd.*;

importquicktime.std.*;

importquicktime.std.image.*;

importquicktime.std.movies.media.*;

importquicktime.app.view.*;

publicclassQTJPictHelperextendsObject{





staticImagepictStreamToJavaImage(InputStream





throwsIOException{





Imageimage=null;





//createabufferforbytesreadfrom





byte[]buffy=newbyte[2048];





//musthaveempty512-byteheadersoG





//willthinkit'safile





intoff=512;





inttotalRead=0;





//loop,attemptingtoreadasmanybyt





//inthearray,growingarrayasneces





intbytesRead=0;





while((bytesRead=in.read(buffy,off



























































}



totalRead+=bytesRead;

off+=bytesRead;

if(off==buffy.length){



//reallocatenewarray



byte[]buffy2=newbyte[buffy



System.arraycopy(buffy,0,buf



buffy=buffy2;

}



































































try{































//handittoQTJGraphicsImporter

QTSession.open();

Pictpict=newPict(buffy);

DataRefref=newDataRef(pict,







StdQTConstant







"PICT");

GraphicsImportergi=



newGraphicsImporter(StdQTCons

gi.setDataReference(ref);

QDRectrect=gi.getSourceRect();

Dimensiondim=newDimension(rect.get







rect.getHeig



newGraphicsImporterDrawer(gi)

QTImageProducerip=newQTImageProduce





















//createAWTimage

image=Toolkit.getDefaultToolkit().cr

















}















}



}catch(QTExceptionqte){



qte.printStackTrace();

}finally{



QTSession.close();

}

returnimage;



Tocompilethiscode,youneedtheQTJava.zipfile(yes,QTJis

oldenoughtopre-dateJARfiles)inyourclasspath.OnMacOS

X,you'dcompilewithsomethinglikethis:







javac-classpath/System/Library/Java/Extensions/QTJava



QTJPictHelper.java



TheimplicitQTJhackinthiscodeisthattheGraphicsImporterhas

tobefooledintobelievingthatablockofmemoryisactuallya

Pictfileasitwouldappearondisk,andPictfileshavea512byteheaderthattheimporterskipsover.So,thefirstthingthis

codedoesistobuildabytearrayfromtheinputstream,

startingwith512emptybytes.

NextistheQTJstuff.It'sOKifyoudon'ttotallyunderstand

itQTJcodeisprettytwisted.That'swhythere'sawholebookon

it.First,youopenaQTSession,whichinitializesQuickTimeand

allocatesresources.YouhavetodothisbeforeanyQTJcall.It

canthrowaQTException,ascanmostotherQTJcalls,sothe

wholethingiswrappedinatry-catchblock.

Next,youcreateaPictobjectfromthebytearrayandpassthat

toDataRef,whichisasortofgenericmediareference.Inthis

case,youpassinflagstotelltheDataRefexactlywhatit's

pointingto.Thesecondandthirdargumentsindicatethatwe're

usingtheold-styleMacOSfiletypeandthatitsvalueisPICT.

YoumightbewonderingwhybeingaPictobjectisn'tselfdescriptiveenough.It'sbecausemanyQTJobjectsarejust

pointerstoblocksofmemoryandthefunctionsthatworkwith

them.TheDataRefsignatureusedheretakesaQTHandleRefasan

argument.QTHandleRefissubclassedbyPict,butitislittlemore

thanapointer;theonlylevelonwhichtheDataRefunderstands

thePict,infact,isasablockofmemory.Mypointhere:QTJ

codeisweirdandoftenC-like.

CreateaGraphicsImporterforthePictformat,andpointittothe

DataRef.YouhavenowreadthePict"file"frommemory.Now,

youcangetthesizeoftheimportedimageandcreatea

QTImageProducer,withhelpfromaGraphicsImporterDrawer(asortof

QT-to-Javabridgeforstillimages,alsousedbyQTJ'sSwing

JComponents).Sincethisisanormal,everydayImageProducer,you

cancreateanimagewithComponent.createImage()or



Toolkit.createImage().



Finally,youneedtocallQTSession.close()todeallocate

QuickTimeresources.It'sOKtodoitmanytimesinaprogram,

althoughit'sprobablymoreefficienttoopen()itonceandclose(

)itonce;e.g.,inyourquithandlerorashut-downhook.



9.5.1.TakeaBreathandRun

Thecodeworksexactlyasintheprevioushackallyou'vedone

issupportonemoreDataFlavor.InFigure9-6,I'vedroppedtwo

imagesfromQuickTimePlayerontotheJavaapp,andbothare

shownintheirownwindows.

Actually,thisisalittlemoreinterestingthanitlooksbecause

thelargerimageisn'tastillimage;it'sthecurrentframeofan

MPEG-4moviethatIdraggedanddroppedintotheJavaapp.

ThesingleframeistransportedasaPict,andusingQTJletsyou

getitintotheJavaworld.Thishackonlyscratchesthesurface

ofQTJ'spotentialifyouwanttodoJavaMediaontheMac,you

shouldcheckoutQuickTimeforJava:ADeveloper'sNotebook,

byChrisAdamson(yourstruly),publishedbyO'Reilly.



Figure9-6.Handlingdroppedimagesby

supportingPictformat



Hack69.TranslucentDrag-and-Drop



TheJavaimplementationofdrag-and-dropofferspoor

visualfeedback.Thishackshowshowtoprovidemore

informationandabetter-lookingresponsetotheuser.

Agoodwaytocreateuser-friendlyinterfacesistoprovidethe

abilitytodrag-and-dropalmostanythingfrom,within,andonto

thoseinterfaces.MacOSXisaperfectexampleofagooddragand-dropuse.EverytimeItrytodragsomethingtodropit

ontosomethingelse,itjustworks.AWT,andthereforeSwing,

letapplicationsimplementdrag-and-dropbutlacksomething

MacOSXalreadyoffers:reallycoolvisualfeedbacktoletthe

userknowwhat'sgoingon.



9.6.1.ARatherBoringCursor

J2SEhasoffereddrag-and-dropfacilitiessinceversion1.2.All

thenecessaryclassesandinterfacescanbefoundinthe

packagejava.awt.dnd.Althoughnotveryeasytouseatfirst,this

packageprovidespowerfulfeaturesyoucanusetogreatly

improvetheusabilityofyourapplications.Unfortunately,the

Javadrag-and-dropframeworkofferslittlevisualfeedback.In

fact,theonlyfeedbacktheusercangetisasimplemouse

cursor.Forinstance,youcanshowthatadrag-and-drop

operationisinprogresswiththefollowinglineofcode:





dropTarget.setCursor(DragSource.DefaultMoveDrop);



Figure9-7showswhatthevisualfeedbacklookslikeon



Windows.



Figure9-7.Defaultdrag-and-dropvisualfeedback

onWindows



Notonlydoesthislookbad,italsoconveysverylittle

information.MacOSXusersareusedtoamuchricher

environment,andwhyshouldWindowsorLinuxusersexpect

less?Asanexampleofwhatcanbedone,SafariMacOSX's

defaultwebbrowsershowsatranslucentthumbnailofthe

pictureyouaredragging.Figure9-8showswhatthislookslike

inaction.



Figure9-8.MacOSXprovidesgreatlooking

visualfeedbackfordrag-and-drop



Thequalityoftheinteractionisgreatlyenhancedbythe

quantityofinformationprovidedbythevisualfeedback.

Anotherexampleisdraggingalinkfromthewebbrowsertothe

desktop,whereatranslucenttextboxcontainingthelinktitle

andtheURLisshown.Wouldn'titbegreattobeabletodothe

sameinyourapplication?Thankfully,Swingisperfectlysuited

forthatkindofjob.



9.6.2.TranslucenceRocks

Implementingastylishdrag-and-droprequiresbeingableto

drawatranslucentpictureoveranycomponent.EverySwing

framecontainsseverallayersonwhichcomponentsarepainted.

Theselayersservemanypurposes,amongwhichisthedrawing

ofpop-upmenusovertheregularcomponents.Thehigher-level

layeriscalledtheglasspane.Aglasspaneisatransparent

containeryoucanusetodrawovertheentireUI,asseeninthe

hackthatturneddialogsintoframe-anchored"sheets"[Hack

#44].Youwilluseittodisplaytranslucentpicturesduringa



drag-and-dropoperation,asseeninFigure9-9.



Figure9-9.Atranslucentpictureasvisual

feedbackfordrag-and-drop



Yet,translucentpicturesdonotcoveralltheneedsofeffective

drag-and-dropvisualfeedback.Whentheuserdropsafileon

yourapplication,youcanuseapicturetoindicatewhatthetype

ofthefileis.However,whatpicturewillyouusewhentheuser

wantstodragatextboxintoanotherbox,andexpectthe

contentsofthefirstboxtobecopiedtothesecond?Thebest

solutionissimplytodisplayatranslucentcopyofthe

componentitself,referredtoasaghostinthecode.Figure9-10

showsaghostinmid-drag.



Figure9-10.Aghostisatranslucentcopyofa

Swingcomponent



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Hack 68. Handling Dropped Picts on Mac OS X

Tải bản đầy đủ ngay(0 tr)

×