2012-09-14 8 views
6

Mam aplikacji pulpitu Java, który działa między innymi na OS X.Swing i bitmapy na siatkówce wyświetla

Teraz nowy MacBook Pro posiada wyświetlacz siatkówki i jestem zaniepokojony: jak to się dzieje pracować nad Swingiem?

Co gdy aplikacja Java wykorzystuje oba składniki swing i niektóre grafiki bitmapowej (jak niestandardowe ikony/ImageIcon)?

Czy wszystkie aplikacje Java na komputer muszą być automatycznie zmieniane (na przykład czterokrotnie zwiększając każdy piksel) lub czy będę potrzebować utworzyć dwie wersje zestawu ikon (na przykład jeden z ikonami 24x24, a drugi z ikonami 96 x 96) i jakoś ustalić, czy aplikacja działa na wyświetlaczu siatkówki?

+3

Edytuj swoje pytanie, dołączając [sscce] (http://sscce.org/), które ilustruje twój obszar zainteresowania; nowy właściciel wyświetlaczy Retina MacBook Pro może opublikować zrzut ekranu (http://meta.stackexchange.com/questions/99734/how-do-i-create-a-screenshot-to-illustrate-a-post). – trashgod

+0

BTW, twoja ikona 24x24 musi tylko stać się ikoną 48x48. Retina podwaja rozdzielczość w każdym wymiarze, który zamienia każdy piksel na cztery piksele. – MiguelMunoz

Odpowiedz

0

To jak ikony wyglądają na mojej siatkówki macbook '12:

enter image description here

po lewej stronie ikony ubocznych w IntelliJ IDEA 11 (app huśtawka), a po prawej stronie IDEA 12, która jest uważana za retinized. Jak widać, automatycznie skalowane ikony (po lewej) wyglądają dość brzydko.

O ile wiem, oni just like the guys from Chrome team, zrobiłem to poprzez zapewnienie podwójnej wielkości ikon.

4

W Apple 6 Java można zapewnić wiele wersji tego samego obrazu. W zależności od ekranu (siatkówki lub nie) jeden lub drugi obraz jest wybierany i rysowany.

Jednak te obrazy mają do załadowany w sposób szczególny:

Toolkit.getDefaultToolkit().getImage("NSImage://your_image_name_without_extension"); 

Na przykład, jeśli (regularne rozdzielczości) obrazu nazywa się: „scissor.png”, trzeba stworzyć wysokiej rozdzielczości wersji "[email protected]" (po Apple naming conventions) i umieść oba obrazy w katalogu Resources pakietu aplikacji (tak, musisz bundle your app). Następnie zadzwonić:

Image img = Toolkit.getDefaultToolkit().getImage("NSImage://scissor"); 

Można użyć obraz wynikowy w przycisków i będzie wyciągnąć z prawej rozdzielczości magicznie.

Istnieją dwa inne "sztuczki" można użyć:

  1. Korzystanie AffineTransform z (0.5, 0.5) na swoim obiekcie Graphics2D przed rysunek obraz. Zobacz także this java-dev message
  2. Tworzenie wysokiej wersji DPI obrazu programowo przy użyciu this hack

Pierwszy „trick” (0,5 skalowania) teraz działa również na Oracle Java 7/8. tj. jeśli narysujesz obraz z 0.5 skalowaniem bezpośrednio do obiektu Graphics komponentu, będzie on renderowany w wysokiej rozdzielczości na wyświetlaczach Retina (a także o połowę w stosunku do oryginalnego rozmiaru).

+0

Czy ktoś inny niż osoba udzielająca odpowiedzi może zagłosować na to lub zaakceptować, jeśli faktycznie działa, nie można zamknąć duplikatów na to pytanie, dopóki to nie zostanie zrobione. –

1

Mogę potwierdzić, że skalowanie obrazów działa na Oracle Java 1.8. Nie mogę uzyskać hackowania NSImage do pracy w java 1.7 lub 1.8.Myślę, że to działa tylko z Java 6 z Mac ...

Chyba że ktoś ma lepsze rozwiązanie, co robię jest następujący:

Utwórz dwa zestawy ikon. Jeśli masz ikonę szerokości 48pixel, utwórz jedną 48px @normal DPI, a drugą na 96px z 2x DPI. Zmień nazwę obrazu 2xDPI na @2x.png, aby była zgodna ze standardami nazewnictwa Apple.

Podklasa ImageIcon i nazwać ją RetinaIcon lub coś podobnego. można przetestować na wyświetlaczu Retina następująco:

public static boolean isRetina() { 

boolean isRetina = false; 
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); 

try { 
       Field field = graphicsDevice.getClass().getDeclaredField("scale"); 
     if (field != null) { 
      field.setAccessible(true); 
      Object scale = field.get(graphicsDevice); 
      if(scale instanceof Integer && ((Integer) scale).intValue() == 2) { 
       isRetina = true; 
      } 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return isRetina; 
} 

Upewnij się @Override szerokość i wysokość nowego ImageIcon klasy następująco:

@Override 
public int getIconWidth() 
{ 
    if(isRetina()) 
    { 
     return super.getIconWidth()/2; 
    } 
    return super.getIconWidth(); 
} 

@Override 
public int getIconHeight() 
{ 
    if(isRetina()) 
    { 
     return super.getIconHeight()/2; 
    } 
    return super.getIconHeight(); 
} 

Gdy masz test na ekranie siatkówki i niestandardowe metody szerokość/wysokość nadpisane można dostosować metodę painIcon następująco:

@Override 
public synchronized void paintIcon(Component c, Graphics g, int x, int y) 
{ 
    ImageObserver observer = getImageObserver(); 

    if (observer == null) 
    { 
     observer = c; 
    } 

    Image image = getImage(); 
    int width = image.getWidth(observer); 
    int height = image.getHeight(observer); 
    final Graphics2D g2d = (Graphics2D)g.create(x, y, width, height); 

    if(isRetina()) 
    { 
     g2d.scale(0.5, 0.5); 
    } 
    else 
    { 

    } 
    g2d.drawImage(image, 0, 0, observer); 
    g2d.scale(1, 1); 
    g2d.dispose(); 
} 

i nie wiem, jak to będzie działać z wieloma ekranami - czy jest ktoś, kto może w tym pomóc?

Mam nadzieję, że ten kod i tak pomoże!

Jason Barraclough.

Oto przykład użycia skalowanie jak wspomniano powyżej: RetinaIcon is on the left. ImageIcon is on the right

+0

Dzięki za to rozwiązanie. Działa ładnie. – user3396583

0

Oto rozwiązanie, które działa także wtedy, gdy są używane ikony w menu Apple. Tam ikona jest automatycznie szara. Więc wdrożyliśmy klasy DenseIcon który maluje gęsto:

public synchronized void paintIcon(Component c, Graphics g, int x, int y) { 
    if(getImageObserver() == null) { 
     g.drawImage(getImage0(), x, y, getIconWidth(), getIconHeight(), c); 
    } else { 
     g.drawImage(getImage0(), x, y, getIconWidth(), getIconHeight(), getImageObserver()); 
    } 
} 

jak podłączyć do siwienie jeszcze nie zorientowali się. Tak kludge wracamy niskim res obraz tak, że menu może zrobić jego modyfikacji:

public Image getImage() { 
    Image image = getImage0().getScaledInstance(
      getIconWidth(), 
      getIconHeight(), 
      Image.SCALE_SMOOTH); 
    ImageIcon icon = new ImageIcon(image, getDescription()); 
    return icon.getImage(); 
} 

znaleźć kod pełnej klasy tutaj na gist. Należy utworzyć instancję klasy ikony z adresem URL do obrazu, który jest dwukrotnie większy. Działa na wyświetlaczach 2K.