2012-01-30 3 views
0

Я пытаюсь добавить возможность запуска веб URL в основной SUN (Oracle) Java Swing ImageIcon галерея демо: http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html#exampleКлиринговый ImageIcon и связанные с ними действия в GUI свинг

Требование Цель состоит в том, чтобы создать панель запуска веб-ссылки Swing GUI, которая имеет возможность запускать ссылку через веб-браузер пользователя по умолчанию, используя возможность запуска JRE 1.6+ Desktop API, и открывать другой URL-адрес в зависимости от того, какое изображение было нажата последним.

Проблема Проблема, которую я, кажется, имея то, что каждый раз, когда новый ImageIcon создается в конструкторе ThumbnailAction, это, кажется, не разрушая предыдущее изображение и просто закрашивать поверх него. Нежелательный побочный эффект заключается в том, что старые MouseListeners и метаданные старого образа по-прежнему активны, поэтому попытка щелчка по запуску URL-адреса фактически загружает URL ранее загруженного изображения, а также URL-адрес текущего фокусного изображения. Если вы посмотрите на консольные журналы печати, вы также можете увидеть MouseEntered и Exited fire несколько раз, один раз для каждого изображения, которое было заменено до сих пор. Поэтому, если пользователь делает 3 или 4 свопа, он запустит много URL-адресов. Не желаемый эффект.

Если кто-нибудь знает, что это проблема была бы оценена, вот мои изменения в файле «IconDemoApp.java» (Обновлено 2012-01-31):

/* 
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions 
* are met: 
* 
* - Redistributions of source code must retain the above copyright 
*  notice, this list of conditions and the following disclaimer. 
* 
* - Redistributions in binary form must reproduce the above copyright 
*  notice, this list of conditions and the following disclaimer in the 
*  documentation and/or other materials provided with the distribution. 
* 
* - Neither the name of Oracle or the names of its 
*  contributors may be used to endorse or promote products derived 
*  from this software without specific prior written permission. 
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
*/ 

package components; 

import java.awt.BasicStroke; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Desktop; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.net.URI; 
import java.net.URISyntaxException; 
import java.util.ArrayList; 
import java.util.Collection; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 
import java.util.TreeSet; 
import javax.swing.AbstractAction; 

import javax.swing.BorderFactory; 
import javax.swing.Box; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JToolBar; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

/** 
* This application is intended to demonstrate the loading of image files into icons 
* for use in a Swing user interface. It creates a toolbar with a thumbnail preview 
* of each image. Clicking on the thumbnail will show the full image 
* in the main display area. 
* 
* IconDemoApp.java requires the following files: <br> 
* The following files are copyright 2006 spriggs.net and licensed under a 
* Creative Commons License (http://creativecommons.org/licenses/by-sa/3.0/) 
* <br> 
* images/sunw01.jpg <br> 
* images/sunw02.jpg <br> 
* images/sunw03.jpg <br> 
* images/sunw04.jpg <br> 
* images/sunw05.jpg <br> 
* 
* @author Collin Fagan 
* @date 7/25/2007 
* @version 2.0 
*/ 
public class IconDemoApp extends JFrame { 

    /** 
    * Main entry point to the demo. Loads the Swing elements on the "Event 
    * Dispatch Thread". 
    * 
    * @param args 
    */ 
    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       IconDemoApp app = new IconDemoApp(); 
       app.setVisible(true); 
      } 
     }); 
    } 

     /* 
    * MissingIcon 
    * Internal class for how to recover from missing icons. 
    * (displays empty image placeholder with red X and white background) 
    */ 
    class MissingIcon implements Icon { 

     private int width = 32; 
     private int height = 32; 

     private BasicStroke stroke = new BasicStroke(4); 

     public void paintIcon(Component c, Graphics g, int x, int y) { 
      Graphics2D g2d = (Graphics2D) g.create(); 

      g2d.setColor(Color.WHITE); 
      g2d.fillRect(x +1 ,y + 1,width -2 ,height -2); 

      g2d.setColor(Color.BLACK); 
      g2d.drawRect(x +1 ,y + 1,width -2 ,height -2); 

      g2d.setColor(Color.RED); 

      g2d.setStroke(stroke); 
      g2d.drawLine(x +10, y + 10, x + width -10, y + height -10); 
      g2d.drawLine(x +10, y + height -10, x + width -10, y + 10); 

      g2d.dispose(); 
     } 

     public int getIconWidth() { 
      return width; 
     } 

     public int getIconHeight() { 
      return height; 
     } 
    } 

    /** 
    * Default constructor for the demo. 
    */ 
    public IconDemoApp() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setTitle("Icon Demo: Please Select an Image"); 

     // A label for displaying the pictures 
     photographLabel.setVerticalTextPosition(JLabel.BOTTOM); 
     photographLabel.setHorizontalTextPosition(JLabel.CENTER); 
     photographLabel.setHorizontalAlignment(JLabel.CENTER); 
     photographLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 

     // We add two glue components. Later in process() we will add thumbnail buttons 
     // to the toolbar inbetween thease glue compoents. This will center the 
     // buttons in the toolbar. 
     buttonBar.add(Box.createGlue()); 
     buttonBar.add(Box.createGlue()); 

     add(buttonBar, BorderLayout.SOUTH); 
     add(photographLabel, BorderLayout.CENTER); 

     setSize(400, 300); 

     // this centers the frame on the screen 
     setLocationRelativeTo(null); 

     // start the image loading SwingWorker in a background thread 
     loadimages.execute(); 
    } 

    /** 
    * SwingWorker class that loads the images a background thread and calls publish 
    * when a new one is ready to be displayed. 
    * 
    * We use Void as the first SwingWroker param as we do not need to return 
    * anything from doInBackground(). 
    */ 
    private SwingWorker<Void, ThumbnailAction> loadimages = new SwingWorker<Void, ThumbnailAction>() { 

     /** 
     * Creates full size and thumbnail versions of the target image files. 
     */ 
     @Override 
     protected Void doInBackground() throws Exception { 
      for (int i = 0; i < titles.length; i++) { 
       ImageIcon icon; 
       icon = createImageIcon(imagedir + thumbs[i], titles[i]); 

       ThumbnailAction thumbAction; 
       if(icon != null){ 

        ImageIcon thumbnailIcon = new ImageIcon(getScaledImage(icon.getImage(), 32, 32)); 

        thumbAction = new ThumbnailAction(icon, thumbnailIcon, titles[i], descs[i], links[i]); 

       }else{ 
        // the image failed to load for some reason 
        // so load a placeholder instead 
        thumbAction = new ThumbnailAction(placeholderIcon, placeholderIcon, titles[i], descs[i], links[i]); 
       } 
       publish(thumbAction); 
      } 
      // unfortunately we must return something, and only null is valid to 
      // return when the return type is void. 
      return null; 
     } 

     /** 
     * Process all loaded images. 
     */ 
     @Override 
     protected void process(List<ThumbnailAction> chunks) { 
      for (ThumbnailAction thumbAction : chunks) { 
       JButton thumbButton = new JButton(thumbAction); 
       // add the new button BEFORE the last glue 
       // this centers the buttons in the toolbar 
       buttonBar.add(thumbButton, buttonBar.getComponentCount() - 1); 
      } 
     } 
    }; 

    /** 
    * Creates an ImageIcon if the path is valid. 
    * @param String - resource path 
    * @param String - description of the file 
    */ 
    protected ImageIcon createImageIcon(String path, String description) { 
     java.net.URL imgURL = getClass().getResource(path); 
     if (imgURL != null) { 
      return new ImageIcon(imgURL, description); 
     } 
     else { 
      System.err.println("Couldn't find file: " + path); 
      return null; 
     } 
    } 

    /** 
    * Resizes an image using a Graphics2D object backed by a BufferedImage. 
    * @param srcImg - source image to scale 
    * @param w - desired width 
    * @param h - desired height 
    * @return - the new resized image 
    */ 
    private Image getScaledImage(Image srcImg, int w, int h) { 
     BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
     Graphics2D g2 = resizedImg.createGraphics(); 
     g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
     g2.drawImage(srcImg, 0, 0, w, h, null); 
     g2.dispose(); 
     return resizedImg; 
    }  

    /** 
    * Action class that shows the image specified in it's constructor. 
    */ 
    private class ThumbnailAction extends AbstractAction implements MouseListener { 

     private Icon displayPhoto; // The icon if the full image we want to display. 

     /** 
     * @param Icon - The full size photo to show in the button. 
     * @param Icon - The thumbnail to show in the button. 
     * @param String - The descriptioon of the icon. 
     */ 
     public ThumbnailAction(Icon photo, Icon thumb, String title, String desc, String link) { 
      displayPhoto = photo; 

      // The short description becomes the title of the window. 
      putValue(SHORT_DESCRIPTION, title); 

      // The long description becomes the tooltip of a button. 
      putValue(LONG_DESCRIPTION, desc); 

      // The DEFAULT action on click is to launch this URL 
      putValue(DEFAULT, link);    

      // The LARGE_ICON_KEY is the key for setting the icon when an Action is applied to a button. 
      putValue(LARGE_ICON_KEY, thumb);    
     } 

     /** 
     * Shows the full image in the main area and sets the application title. 
     */ 
     public void actionPerformed(ActionEvent e) { 
      photographLabel.setIcon(displayPhoto); 
      setTitle("Icon Demo - " + getValue(SHORT_DESCRIPTION).toString()); 
      photographLabel.setToolTipText("<html>" + getValue(LONG_DESCRIPTION) + "</html>"); 

      photographLabel.validate(); 
      photographLabel.updateUI(); 
      photographLabel.repaint(); 

      photographLabel.addMouseListener(this); 
     } 

     /** 
     * Listen for clicks to send user to a URL or launch an application 
     * @param e 
     */    
     @Override 
     public void mouseClicked(MouseEvent e) {     
      int clicked = e.getClickCount(); 
      if (clicked > 0) { 
       /*************************************/ 
       /* Code for launching Browser BEGIN */ 
       Desktop desktop = null; 
       if (Desktop.isDesktopSupported()) { 
        desktop = Desktop.getDesktop(); 
       }   
       URI uri = null; 
       try { 
        uri = new URI((String)this.getValue(DEFAULT)); //pass the URL from ImageIcon to Browser 
        if (desktop.isSupported(Desktop.Action.BROWSE)) { 
         desktop.browse(uri); //url passed 
        } 
        else { 
         System.out.println("Unable to open default browser to: "+uri); 
        } 
       } 
       catch(IOException ioe) { 
        ioe.printStackTrace(); 
       } 
       catch(URISyntaxException use) { 
        use.printStackTrace(); 
       } 
       /* Code for launching Browser END */ 
       /*************************************/ 
      } 
      else { 
       System.out.println("Clicked: " + clicked); 
      } 
     }   

     @Override 
     public void mousePressed(MouseEvent e) { 
      System.out.println("Mouse pressed (# of clicks: " + e.getClickCount() + ") " + e); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      System.out.println("Mouse released (# of clicks: " + e.getClickCount() + ") " + e); 
     } 

     @Override 
     public void mouseEntered(MouseEvent e) { 
      System.out.println("Mouse entered: " + e); 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
      System.out.println("Mouse exited: " + e); 
     }   
    } 



    private JLabel photographLabel = new JLabel(); 
    private JToolBar buttonBar = new JToolBar(); 

    private String imagedir = "images/"; 

    private MissingIcon placeholderIcon = new MissingIcon();  

    // List of all the image files to load. 
    private String[] thumbs = { "sunw01.jpg", "sunw02.jpg", "sunw03.jpg", "sunw04.jpg", "sunw05.jpg"}; 

    // List of all the descriptions of the image files. These correspond one to one with the image file names 
    private String[] titles = { "SunLogo", "Clocktower", "ClocktowerWest", "Mansion", "SunAuditorium" }; 

    // List of all descriptions (descs) to use as tooltips. 
    private String[] descs = { "The Original SUNW Logo", "The Clocktower frontal view", "The Clocktower from the West", "The Mansion on the hill!", "The infamouse Sun campus auditorium"}; 

    // List of all links to send a user to on click action. 
    private String[] links = { "http://example.com/#1", "http://example.com/#2", "http://example.com/#3", "http://example.com/#4", "http://example.com/#5"}; 

} 
+1

Пожалуйста, отредактируйте свой вопрос, включив в него [sscce] (http://sscce.org/), который показывает проблему, которую вы описываете. – trashgod

+0

Отредактированный образец кода, чтобы быть более автономным (т. Е. MissingIcon теперь является внутренним классом). Единственная зависимость заключается в загрузке изображений с теми же именами, что и в образцах кода, а затем поместить их в ваш проект под папкой «images». Я успешно создал этот пример с помощью NetBeans. Если кто-то хочет получить дополнительную информацию о том, как увидеть поведение, пожалуйста, сообщите здесь. Но в основном просто Новый проект -> «IconDemoApp» перемещает указанные изображения в ваш новый проект, вставлять в образец код, править и запускать. Затем щелкните значок в графическом интерфейсе Swing, который появится и просмотрите описанное поведение. – bcmoney

+0

'MissingIcon' уже включен в проект; имя пакета должно быть «компонентами». – trashgod

ответ

1

Настройка изображения не проблема. Но когда действие выполняется добавление MouseListener к photographLabel, что вы никогда не удалить в строке 267. Простого хак для этого примера, чтобы удалить все зарегистрированные Слушатель перед добавлением нового:

for(MouseListener listener : photographLabel.getMouseListeners()) { 
    photographLabel.removeMouseListener(listener); 
} 
photographLabel.addMouseListener(this); 

Теперь все работает аспектированы.

+0

Awesome ... еще раз спасибо за это. FYI: несколько месяцев спустя я объединил эту концепцию с [WebRenderer] (http://www.webrenderer.com/) и имел большой успех в анализе рекомендуемых сайтов и отображении их в графическом интерфейсе рабочего стола Java Swing. Кроме того, то же самое можно было бы сделать и в базовом (не судоходном) способе, используя что-то вроде отключенного [JEditorPane] (http://docs.oracle.com/javase/tutorial/uiswing/components/editorpane.html#editorpane) , [JScrollPane] (http://www.rgagnon.com/javadetails/java-0205.html) или [JavaFX WebView] (http://docs.oracle.com/javafx/2/webview/jfxpub-webview.htm) – bcmoney

1

1) Я не могу генерирующего ваш вопрос, потому что это описание, сможет говорить о un_healt драйверов GPU

2), но вы можете проверить, что за счет уменьшения вторичной проблемы с quickiest использования картины флеша() из буфера, и следующие шаги могут помочь вам

создать Icon

myIcon.getImage().flush(); 

поставил Icon в JLabel

myLabel.setIcon(myIcon); 
+0

Хм, я пробовал это, но, похоже, это не повлияло на результат. Несколько окон по-прежнему запускаются, когда я нажимаю несколько фотографий. Я обновил источник, чтобы вы могли запускать его как автономный пример. – bcmoney

Смежные вопросы