2011-08-01 16 views
6

Jakie są zasadnicze różnice między używaniem ramki AWT i Swing JFrame podczas implementacji własnego renderowania, a nie przy użyciu standardowych komponentów Java GUI?Swing/JFrame vs AWT/Frame dla renderowania poza EDT

To jest kontynuacją poprzedniego pytania:

AWT custom rendering - capture smooth resizes and eliminate resize flicker

Typowe punkty rozmawiać na Swing vs AWT nie wydają się zastosować, ponieważ używamy tylko ramek. Heavyweight vs Lightweight wychodzi przez okno (i JFrame rozszerza Frame), na przykład.

Więc co jest najlepsze, JFrame lub Frame dla tej sytuacji? Czy ma jakąś znaczącą różnicę?

Uwaga: ten scenariusz to taki, w którym renderowanie w EDT nie jest pożądane. Istnieje przepływ pracy aplikacji, który nie jest powiązany z EDT, a renderowanie odbywa się zgodnie z potrzebami poza EDT. Synchronizowanie renderowania z EDT spowodowałoby opóźnienie renderowania. Nie renderujemy żadnych komponentów Swing ani AWT innych niż Frame lub JFrame (lub dołączonego JPanel/Component/etc, jeśli jest najlepszy).

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Insets; 
import java.awt.Toolkit; 
import java.awt.image.BufferStrategy; 
import java.awt.Frame; 

public class SmoothResize extends Frame { 

public static void main(String[] args) { 
    Toolkit.getDefaultToolkit().setDynamicLayout(true); 
    System.setProperty("sun.awt.noerasebackground", "true"); 
    SmoothResize srtest = new SmoothResize(); 
    //srtest.setIgnoreRepaint(true); 
    srtest.setSize(100, 100); 
    srtest.setVisible(true); 
} 

public SmoothResize() { 
    render(); 
} 

private Dimension old_size = new Dimension(0, 0); 
private Dimension new_size = new Dimension(0, 0); 

public void validate() { 
    super.validate(); 
    new_size.width = getWidth(); 
    new_size.height = getHeight(); 
    if (old_size.equals(new_size)) { 
     return; 
    } else { 
     render(); 
    } 
} 

public void paint(Graphics g) { 
    validate(); 
} 

public void update(Graphics g) { 
    paint(g); 
} 

public void addNotify() { 
    super.addNotify(); 
    createBufferStrategy(2); 
} 

protected synchronized void render() { 
    BufferStrategy strategy = getBufferStrategy(); 
    if (strategy == null) { 
     return; 
    } 
    // Render single frame 
    do { 
     // The following loop ensures that the contents of the drawing buffer 
     // are consistent in case the underlying surface was recreated 
     do { 
      Graphics draw = strategy.getDrawGraphics(); 
      Insets i = getInsets(); 
      int w = (int)(((double)(getWidth() - i.left - i.right))/2+0.5); 
      int h = (int)(((double)(getHeight() - i.top - i.bottom))/2+0.5); 
      draw.setColor(Color.YELLOW); 
      draw.fillRect(i.left, i.top + h, w,h); 
      draw.fillRect(i.left + w, i.top, w,h); 
      draw.setColor(Color.BLACK); 
      draw.fillRect(i.left, i.top, w, h); 
      draw.fillRect(i.left + w, i.top + h, w,h); 
      draw.dispose(); 

      // Repeat the rendering if the drawing buffer contents 
      // were restored 
     } while (strategy.contentsRestored()); 

     // Display the buffer 
     strategy.show(); 

     // Repeat the rendering if the drawing buffer was lost 
    } while (strategy.contentsLost()); 
} 

} 
+0

Niektóre metody 'Nested and Inherit' z' Frame' są zaimplementowane bezpośrednio w 'JFrame API' http://download.oracle.com/javase/6/docs/api/javax/swing/JFrame.html, – mKorbel

+0

Nie widzę żadnych różnic między 'Frame' i' JFrame' oraz 'MsExcell' i' MozillaFirefox', należy usunąć 'notify' jeśli jest to zrobione (i3/530/3,43 Gb RAM, WinXP, OnBoard GPU/no sharedMemory/compiled JDK1.6.22) – mKorbel

+0

@mKorbel: Co MsExcel i MozillaFirefox mają wspólnego z czymkolwiek? –

Odpowiedz

2

Rozszerzając @ camickr na answer The "missing detail" jest JRootPane, który zarządza contentPane. Zauważ, że dla JFrame "add i jego wariantów, remove i setLayout zostały nadpisane, aby w razie potrzeby były przekazywane do contentPane." JRootPane#createContentPane() "tworzy nowy JComponent a [n] d ustawia BorderLayout jako jego LayoutManager." Jako szczegół implementacji, ten JComponent ma być new JPanel(). Ma to kilka konsekwencji dla contentPane z JFrame:

  • The contentPane jest podwójnie buforowane domyślnie.
  • Urządzenie contentPane ma BorderLayout, choć zazwyczaj domyślnie jest to .
  • Obiekt contentPane ma specyficzną dla użytkownika delegację U, typowo pochodną od PanelUI, która może wpływać na wygląd i geometrię.
+0

Sądzę, że byłem dwuznaczny, ale jest to całkowicie niestandardowy cykl renderowania. Żadnych delegatów, żadnych L & F, nic poza ramką do zawijania (lub JFrame lub czegokolwiek innego jest pożądane) i renderowaniem * poza * EDT, ponieważ wykonanie go w EDT wymagałoby opóźnienia lub hackery albo obu. –

+0

[* Malowanie w AWT i Swing: Obsługa podwójnego buforowania *] (http://java.sun.com/products/jfc/tsc/articles/painting/index.html#db) może być odpowiednie: "ustawienie, które naprawdę liczy się opcja 'JRootPane', ponieważ to ustawienie skutecznie włącza podwójne buforowanie wszystkiego pod komponentem Swing najwyższego poziomu." Nigdy nie miałem powodu, żeby to wyłączyć. AFAIK, wszystkie istniejące silniki renderujące hosta są jednowątkowe. Dlaczego _nie_ używać EDT? – trashgod

+0

Struktura aplikacji i opóźnienie. Aplikacja, o której mowa, ma własny skrypt i mechanizm układu, które są zintegrowane i renderują napęd. Pomyśl o tym jako o grze, a nie o aplikacji (chociaż jest to druga) pod względem wymagań renderowania. Jest renderowany do backbuffera na żądanie, który jest następnie malowany na ekranie. Zarówno EDT, jak i wątek aplikacji działający z tym samym obrazem (backbuffer) powodują niewielkie problemy. –

2

Swing jest domyślnie podwójnie buforowany, więc zazwyczaj wystarczy skoncentrować się na swoim obrazie.

Oto wersja Swing:

import java.awt.*; 
import javax.swing.*; 

public class SwingResize extends JPanel 
{ 
    protected void paintComponent(Graphics g) 
    { 
     int w = (int)(((double)(getWidth()))/2+0.5); 
     int h = (int)(((double)(getHeight()))/2+0.5); 
     g.setColor(Color.YELLOW); 
     g.fillRect(0, h, w,h); 
     g.fillRect(w, 0, w,h); 
     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, w, h); 
     g.fillRect(w, h, w,h); 
    } 

    public static void main(String[] args) 
    { 
//  Toolkit.getDefaultToolkit().setDynamicLayout(true); 
//  System.setProperty("sun.awt.noerasebackground", "true"); 

     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new SwingResize()); 
     frame.setSize(100, 100); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

} 
+0

Moja wina, ale zadałem to pytanie zbyt wieloznacznie, a kolejne odpowiedzi pomijają punkt, zmuszając cię do paradygmatu renderowania w EDT Swinga. Ma to na celu całkowity niestandardowy interfejs użytkownika, bez konieczności stosowania Swing lub AWT.Malowanie w EDT nie jest pożądane, ponieważ wymaga tego scenariusz, ponieważ wymaga żonglowania cyklem aplikacji i renderowania, gdzie renderowanie jest całkowicie niestandardowe. –

Powiązane problemy