IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SWT/JFace Java Discussion :

GC et copyArea


Sujet :

SWT/JFace Java

  1. #1
    Candidat au Club
    Inscrit en
    Octobre 2011
    Messages
    2
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 2
    Par défaut GC et copyArea
    Bonjour,

    Je cherche à réaliser une capture d'écran en utilisant les composants SWT. plus précisément en utilisant le GraphicControl.
    Je rencontre quelques problèmes :
    En utilisant un code proche de celui-ci : http://www.java2s.com/Tutorial/Java/...eenCapture.htm
    ou de celui-ci :
    http://www.java2s.com/Tutorial/Java/...agewithaGC.htm

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
     
    public class SWTScreeShotDaemon implements Runnable {
    	/** The active Shell to capture */
    	Shell applicationShell;
    	private LinkedList<Image> imagesQueue;
    	/** ImageLoader to save capture on disk */
    	private ImageLoader imLoader;
     
    	/** The number of frame per second */
    	public static final int FRAME_RATE = 30;
    	/** TODO: change max size correctly */
    	public static final int MAX_QUEUE_SIZE = 100;
     
    	public SWTScreeShotDaemon() {
    		imLoader = new ImageLoader();
    		imagesQueue = new LinkedList<Image>();
    	}
     
    	@Override
    	public void run() {
    		Display.getDefault().asyncExec(new Runnable() {
    			@Override
    			public void run() {
    				GC gcControl = new GC(applicationShell);
    				while (true) {
    					Image screenCapture = new Image(applicationShell
    							.getDisplay(), applicationShell.getBounds());
    					gcControl.copyArea(screenCapture, 0, 0);
    					synchronized (imagesQueue) {
    						imagesQueue.add(screenCapture);
    						if (imagesQueue.size() >= MAX_QUEUE_SIZE) {
    							System.out.println("Capture process has ended");
    							stop();
    							return;
    						}
    						try {
    							Thread.sleep(1000 / FRAME_RATE);
    						} catch (InterruptedException e) {
    						}
    					}
    				}
    			}
     
    		});
     
    	}
     
    	public void stop() {
    		if (!imagesQueue.isEmpty()) {
    			flushImageQueueOnDisk();
    		}
    	}
     
    	protected void flushImageQueueOnDisk() {
    		synchronized (imagesQueue) {
    			Display.getDefault().asyncExec(new Runnable() {
    				@Override
    				public void run() {
    					Iterator<Image> i = imagesQueue.iterator();
    					int count = 0;
    					long startTime = System.currentTimeMillis();
    					System.out.println("Starting dumping images");
    					while (i.hasNext()) {
    						imLoader.data = new ImageData[] { i.next()
    								.getImageData() };
    						imLoader.save("C:\\temp\\capture-" + count++ + ".jpg",
    								SWT.IMAGE_JPEG);
    					}
    					long endTime = System.currentTimeMillis();
    					System.out.println("Took +" + (endTime - startTime)
    							+ "ms to record Image queue on disk.");
    					imagesQueue.clear();
    				}
    			});
    		}
    	}
     
    	public synchronized void setActiveShell(Shell shell) {
    		this.applicationShell = shell;
    	}
    }
    et le viewpart associé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Override
    	public void createPartControl(Composite parent) {
     
    		screenshotButton= new Button(parent, SWT.NONE);
    		screenshotButton.setText("Take ScreenShot");
    		screenshotButton.addSelectionListener(new SelectionListener() {
     
    			@Override
    			public void widgetSelected(SelectionEvent e) {
    				if (e.getSource() instanceof Button) {
    					//Rectangle currentWindow = ((Button)e.getSource()).getDisplay().getActiveShell().getBounds();
    					//new ScreenShotDaemon(currentWindow.x, currentWindow.y, currentWindow.width, currentWindow.height).run();
    					SWTScreeShotDaemon scDaemon = new SWTScreeShotDaemon();
    					scDaemon.setActiveShell(((Button)e.getSource()).getDisplay().getActiveShell());
    					scDaemon.run();
    				}
     
    			}
    Le résultat obtenu n'est pas celui que j'attends :



    Je voudrais obtenir la fenêtre principale, comme j'ai réussi à faire avec un la classe java.awt.Robot :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    @Override
    	public void run() {
     
    		System.out.println("Starting capture process");
    		Display.getDefault().asyncExec(new Runnable() {
    			public void run() {
    				try {
    					Robot robot = new Robot();
    					while (true) {
    						BufferedImage currentFrame = robot
    								.createScreenCapture(screenCaptureArea);
    						synchronized (imagesQueue) {
    							imagesQueue.add(currentFrame);
    							if (imagesQueue.size() >= MAX_QUEUE_SIZE) {
    								System.out.println("Capture process has ended");
    								stop();
    								return;
    							}
    						}
    						Thread.sleep(1000 / FRAME_RATE);
    					}
    				} catch (AWTException e) {
    					e.printStackTrace();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
     
    			}
    		});
    	}
     
    	public synchronized void setScreenCaptureArea(int x, int y, int width,
    			int height) {
    		screenCaptureArea = new Rectangle(x, y, width, height);
    	}
    Ma question est donc comment faire en sorte d'avoir le bon rectangle correspondant exactement aux dimensions du shell (et à sa position) ?

    Question subsidiaire la fenêtre ne réagit pas aux déplacements ni aux click pendant la prise des screenshot. J'ai loupé des étapes avec le asynExec ?

    Merci pour vos suggestions.
    Images attachées Images attachées  

  2. #2
    Membre Expert
    Avatar de Gueritarish
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mai 2007
    Messages
    1 800
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 800
    Par défaut
    Salut,

    Tu pourrais nous donner ton attendu?
    Si tu désires faire une capture de ton Shell entier (avec la barre de titre et les boutons de fermetures), il te faut faire comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    GC gc = new GC(display);
    Rectangle shellBounds = shell.getBounds();
    final Image image = new Image(shell.getDisplay(), shellBounds);
    gc.copyArea(image, shellBounds.x, shellBounds.y);
    gc.dispose();
    Par contre, pour ce qui est de ton second soucis, je te recommande de ne pas utiliser de code métier dans le Thread IHM...
    Quand tu fais un Display.(a)synchExec() tu exécutes ton code dans le Thread IHM. Or, dans ce cas présent, tu n'as absolument pas besoin de ce Thread IHM. Donc, tu peux tout à fait garder ton Runnable, mais tu le lances plutôt dans un thread séparé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ExecutorService service = Executors.newSingleThreadExecutor();
    service.execute(new Runnable() {
        @Override
        public void run() {
            Iterator<Image> i = imagesQueue.iterator();
    	int count = 0;
    	long startTime = System.currentTimeMillis();
    	System.out.println("Starting dumping images");
    	while (i.hasNext()) {
    		imLoader.data = new ImageData[] { i.next()
    				.getImageData() };
    		imLoader.save("C:\\temp\\capture-" + count++ + ".jpg",
    				SWT.IMAGE_JPEG);
    	}
    	long endTime = System.currentTimeMillis();
    	System.out.println("Took +" + (endTime - startTime)
    			+ "ms to record Image queue on disk.");
    	imagesQueue.clear();
        }
    });
    service.shutdown();
    Puisque, quand tu es dans un listener, tu es toujours dans le thread IHM...

    Voilà, à+
    Gueritarish

  3. #3
    Candidat au Club
    Inscrit en
    Octobre 2011
    Messages
    2
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 2
    Par défaut
    Merci beaucoup c'est effectivement la capture du shell entier que je cherchais à faire.

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo