2013-07-24 52 views
11

Tôi hiện đang sử dụng mã này để tạo một JDialog;Hiển thị JDialog dưới dạng trang tính không hoạt động

package com.kamuara.reposync.window; 

import java.awt.Dialog; 
import java.awt.Font; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.UIManager; 

public class SheetDialog { 

    private JFrame _windowFrame; 

    public static void main(String[] args) { 
     System.setProperty("apple.awt.documentModalSheet", "true"); 
     System.setProperty("apple.awt.brushMetalLook", "true"); 

     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
      new SheetDialog(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public SheetDialog() { 
     _windowFrame = new JFrame(); 
     _windowFrame.setResizable(false); 
     _windowFrame.setBounds(100, 100, 451, 320); 
     _windowFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     _windowFrame.getContentPane().setLayout(null); 
     _windowFrame.setVisible(true); 

     JButton showDialogButton = new JButton("Show Dialog"); 
     showDialogButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       showSheetDialog(_windowFrame, "Test", "This should be a sheet dialog", "Oke"); 
      } 
     }); 
     showDialogButton.setBounds(328, 263, 117, 29); 
     _windowFrame.getContentPane().add(showDialogButton); 
    } 

    public void showSheetDialog(JFrame owner, String title, String message, String button) { 
     final JDialog messageDialog = new JDialog(owner, title, Dialog.ModalityType.DOCUMENT_MODAL); 
     messageDialog.setBounds(30, 0, owner.getWidth() - 60, 130); 

     // TODO: only when os is osx 
     messageDialog.getRootPane().putClientProperty("apple.awt.documentModalSheet", "true"); 
     messageDialog.setLayout(null); 

     int offsetX = 25; 

     JLabel titleLabel = new JLabel(title); 
     titleLabel.setFont(new Font("Lucida Grande", Font.BOLD, 13)); 
     titleLabel.setBounds(offsetX, 10, 100, 25); 
     messageDialog.getContentPane().add(titleLabel); 

     JLabel messageLabel = new JLabel(message); 
     messageLabel.setVerticalTextPosition(JLabel.TOP); 
     messageLabel.setHorizontalTextPosition(JLabel.LEFT); 
     messageLabel.setFont(new Font("Lucida Grande", Font.PLAIN, 11)); 
     messageLabel.setBounds(offsetX, 10, messageDialog.getWidth() - 10, messageDialog.getHeight() - 60); 
     messageDialog.getContentPane().add(messageLabel); 

     JButton okButton = new JButton(button); 
     okButton.setBounds(messageDialog.getWidth() - 105, messageDialog.getHeight() - 35, 100, 25); 
     okButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       messageDialog.dispose(); 
      } 
     }); 
     messageDialog.getContentPane().add(okButton); 

     messageDialog.setVisible(true); 
    } 
} 

trước đây tôi đã sử dụng Java 6 để biên dịch các ứng dụng và thiết lập các clientProperty apple.awt.documentModalSheet đang làm việc một cách hoàn hảo để hiển thị hộp thoại như là một "Sheet" trên OSX nhưng bây giờ tôi bắt đầu sử dụng Java 7 (cập nhật 25) và hộp thoại không còn được hiển thị dưới dạng Trang tính. Tôi không thể tìm thấy bất kỳ tài liệu cập nhật về điều này. Họ đã thay đổi bất cứ điều gì về điều này? Làm sao tôi có thể giải quyết việc này? Thiết kế giao diện hiện tại trông tốt hơn với một Sheet hơn là một hộp thoại.

Cập nhật

tôi thấy báo cáo lỗi sau đây mà có vẻ là vấn đề tương tự như tôi đang trải qua;

http://bugs.sun.com/view_bug.do?bug_id=8010197

Có ai biết cách giải quyết vấn đề này không? Tôi đã xem xét các thư viện như QuaQua nhưng tôi không muốn sử dụng bất kỳ thư viện nào vì tôi chỉ muốn chức năng Trang tính.

Cập nhật 2

tôi đã cố gắng QuaQua, nhưng thư viện hiện có vấn đề chính xác tương tự khi soạn thảo với Java 7. Bất kỳ cách giải quyết?

Cập nhật 3

đang thay thế với mẫu làm việc (http://pastebin.com/PJ8VGdPb)

Cập nhật 4

Tìm thấy ra SWT có một phong cách cho lớp Shell tên SWT.SHEET của họ mà vẫn hoạt động trong Java7, tôi không thích sử dụng một thư viện như SWT, nhưng nó có vẻ là giải pháp duy nhất.

+0

Để được trợ giúp tốt hơn sớm hơn, hãy đăng [SSCCE] (http://sscce.org/). –

+0

Theo yêu cầu của bạn; xem liên kết pastbin cho mẫu đang hoạt động. – Thys

+0

Nếu đó là SSCCE, nó đủ ngắn để đăng trực tiếp trong câu hỏi .. –

Trả lời

2

Theo như tôi biết, Apple đã không chính thức phát hành phiên bản JDK của họ 7. Phiên bản mới nhất của JDK Apple đã tối ưu hóa cho OS X của họ vẫn là JDK 6. Đó cũng là lý do tại sao các bản cập nhật cho Java đi qua Tab cập nhật AppStore. Những cập nhật này không xuất phát trực tiếp từ Oracle.

Nếu bạn tải xuống JDK 7 trực tiếp từ Oracle, đây là phiên bản tổng quát hơn, không được tinh chỉnh.

Vì vậy, tôi nghĩ rằng bạn sẽ chỉ phải chờ cho Apple phát hành OS X của họ tối ưu hóa JDK 7.

tôi đã trải qua rất nhiều OS X có tính năng không được làm việc khi tôi tải về từ Oracle:

  • Cử chỉ trên bàn di chuột
  • Native Aqua Look'n'Feel không hoạt động, ngay cả khi cố gắng đặt thủ công qua UIManager.
  • Biểu tượng ứng dụng không hoạt động khi sử dụng JOptionPane.
  • JMenu sẽ tự dính vào JFrame thay vì di chuyển lên đầu màn hình.
+0

Bạn có thể chờ một thời gian cho Apple JDK. :) – Trejkaz

1

Dường như trước khi JDK sửa lỗi, bạn phải tự mình triển khai Bảng.

Những điểm chính là:

  1. Sử dụng cửa sổ kính của khung cửa sổ để giữ tấm thoại
  2. Sử dụng GridBagLayout (với NORTH neo) để đặt hộp thoại ở đầu trang | trung tâm của cửa sổ
  3. Animate Sheet khi chương trình/disappeare bằng cách sơn thoại nhiều lần, mỗi lần sơn hơn/ít hơn một phần của hộp thoại

sau đây là exampl e đang

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GraphicsConfiguration; 
import java.awt.GraphicsEnvironment; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 

import javax.swing.Box; 
import javax.swing.JComponent; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.border.LineBorder; 

public class SheetableJFrame extends JFrame implements ActionListener { 

    public static final int INCOMING = 1; 
    public static final int OUTGOING = -1; 
    public static final float ANIMATION_DURATION = 1000f; 
    public static final int ANIMATION_SLEEP = 50; 

    JComponent sheet; 
    JPanel glass; 
    Sheet animatingSheet; 
    boolean animating; 
    int animationDirection; 
    Timer animationTimer; 
    long animationStart; 
    BufferedImage offscreenImage; 

    public SheetableJFrame() { 
     super(); 
     glass = (JPanel) getGlassPane(); 
     glass.setLayout(new GridBagLayout()); 
     animatingSheet = new Sheet(); 
     animatingSheet.setBorder(new LineBorder(Color.black, 1)); 
    } 

    public JComponent showJDialogAsSheet(JDialog dialog) { 
     sheet = (JComponent) dialog.getContentPane(); 
     sheet.setBorder(new LineBorder(Color.black, 1)); 
     glass.removeAll(); 
     animationDirection = INCOMING; 
     startAnimation(); 
     return sheet; 
    } 

    public void hideSheet() { 
     animationDirection = OUTGOING; 
     startAnimation(); 
    } 

    private void startAnimation() { 
     glass.repaint(); 
     // clear glasspane and set up animatingSheet 
     animatingSheet.setSource(sheet); 
     glass.removeAll(); 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.anchor = GridBagConstraints.NORTH; 
     glass.add(animatingSheet, gbc); 
     gbc.gridy = 1; 
     gbc.weighty = Integer.MAX_VALUE; 
     glass.add(Box.createGlue(), gbc); 
     glass.setVisible(true); 

     // start animation timer 
     animationStart = System.currentTimeMillis(); 
     if (animationTimer == null) animationTimer = new Timer(ANIMATION_SLEEP, this); 
     animating = true; 
     animationTimer.start(); 
    } 

    private void stopAnimation() { 
     animationTimer.stop(); 
     animating = false; 
    } 

    // used by the Timer 
    public void actionPerformed(ActionEvent e) { 
     if (animating) { 
      // calculate height to show 
      float animationPercent = (System.currentTimeMillis() - animationStart)/ANIMATION_DURATION; 
      animationPercent = Math.min(1.0f, animationPercent); 
      int animatingHeight = 0; 

      if (animationDirection == INCOMING) { 
       animatingHeight = (int) (animationPercent * sheet.getHeight()); 
      } else { 
       animatingHeight = (int) ((1.0f - animationPercent) * sheet.getHeight()); 
      } 
      // clip off that much from sheet and put it into animatingSheet 
      animatingSheet.setAnimatingHeight(animatingHeight); 
      animatingSheet.repaint(); 

      if (animationPercent >= 1.0f) { 
       stopAnimation(); 
       if (animationDirection == INCOMING) { 
        finishShowingSheet(); 
       } else { 
        glass.removeAll(); 
        glass.setVisible(false); 
       } 
      } 
     } 
    } 

    private void finishShowingSheet() { 
     glass.removeAll(); 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.anchor = GridBagConstraints.NORTH; 
     glass.add(sheet, gbc); 
     gbc.gridy = 1; 
     gbc.weighty = Integer.MAX_VALUE; 
     glass.add(Box.createGlue(), gbc); 
     glass.revalidate(); 
     glass.repaint(); 
    } 

    class Sheet extends JPanel { 
     Dimension animatingSize = new Dimension(0, 1); 
     JComponent source; 
     BufferedImage offscreenImage; 

     public Sheet() { 
      super(); 
      setOpaque(true); 
     } 

     public void setSource(JComponent source) { 
      this.source = source; 
      animatingSize.width = source.getWidth(); 
      makeOffscreenImage(source); 
     } 

     public void setAnimatingHeight(int height) { 
      animatingSize.height = height; 
      setSize(animatingSize); 
     } 

     private void makeOffscreenImage(JComponent source) { 
      GraphicsConfiguration gfxConfig = GraphicsEnvironment.getLocalGraphicsEnvironment() 
        .getDefaultScreenDevice().getDefaultConfiguration(); 
      offscreenImage = gfxConfig.createCompatibleImage(source.getWidth(), source.getHeight()); 
      Graphics2D offscreenGraphics = (Graphics2D) offscreenImage.getGraphics(); 
      source.paint(offscreenGraphics); 
     } 

     public Dimension getPreferredSize() { 
      return animatingSize; 
     } 

     public Dimension getMinimumSize() { 
      return animatingSize; 
     } 

     public Dimension getMaximumSize() { 
      return animatingSize; 
     } 

     public void paint(Graphics g) { 
      // get the bottom-most n pixels of source and paint them into g, where n is height 
      BufferedImage fragment = offscreenImage.getSubimage(0, offscreenImage.getHeight() - animatingSize.height, 
        source.getWidth(), animatingSize.height); 
      g.drawImage(fragment, 0, 0, this); 
     } 
    } 
} 

Các mã kiểm tra

import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.JDialog; 
import javax.swing.JOptionPane; 

public class SheetTest extends Object implements PropertyChangeListener { 

    JOptionPane optionPane; 
    SheetableJFrame frame; 

    public static void main(String[] args) { 
     new SheetTest(); 
    } 

    public SheetTest() { 
     frame = new SheetableJFrame(); 
     // build JOptionPane dialog and hold onto it 
     optionPane = new JOptionPane("Do you want to close?", JOptionPane.QUESTION_MESSAGE, JOptionPane.CANCEL_OPTION); 
     frame.setSize(640, 480); 
     frame.setVisible(true); 
     optionPane.addPropertyChangeListener(this); 

     JDialog dialog = optionPane.createDialog(frame, "irrelevant"); 
     frame.showJDialogAsSheet(dialog); 
    } 

    public void propertyChange(PropertyChangeEvent pce) { 
     if (pce.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) { 
      System.out.println("Selected option " + pce.getNewValue()); 
      frame.hideSheet(); 
     } 
    } 
} 

tham khảo
http://oreilly.com/pub/h/4852
http://book.javanb.com/swing-hacks/swinghacks-chp-6-sect-6.html

0

Dưới đây là một hack siêu tinh ranh tôi đã đưa ra mà đặt cờ mà JDK tại dường như bị quên đặt và đặt vị trí theo cách thủ công cửa sổ ở đúng nơi. Vẫn còn một cái bóng còn thiếu, nên tôi tự hỏi liệu có ai có thể cải thiện nó không. ;)

Điều này gây rối với các lớp nội bộ và các trường riêng tư, vì vậy nó có thể phá vỡ trong bất kỳ bản phát hành mới nhất định nào của JDK, nhưng nó vẫn hoạt động trên 8u5. Có lẽ nó sẽ cung cấp cho một số cái nhìn sâu sắc vào cách thức các lớp AWT nội bộ được cấu trúc.

public static void makeSheet(Dialog dialog) { 
    dialog.addNotify(); 
    ComponentPeer peer = dialog.getPeer(); 

    // File dialogs are CFileDialog instead. Unfortunately this means this hack 
    // can't work for those. :(
    if (peer instanceof LWWindowPeer) { 
     LWWindowPeer windowPeer = (LWWindowPeer) dialog.getPeer(); 
     //XXX: Should check this before casting too. 
     CPlatformWindow platformWindow = (CPlatformWindow) windowPeer.getPlatformWindow(); 
     try { 
      Method method = CPlatformWindow.class.getDeclaredMethod(
       "setStyleBits", int.class, boolean.class); 
      method.setAccessible(true); 
      method.invoke(platformWindow, 64 /* CPlatformWindow.SHEET */, true); 

      Window parent = dialog.getOwner(); 
      dialog.setLocation(dialog.getLocation().x, 
           parent.getLocation().y + parent.getInsets().top); 
     } catch (Exception e) { 
      Logger.getLogger(SheetHack.class.getName()) 
       .log(Level.WARNING, "Couldn't call setStyleBits", e); 
     } 
    } 
} 
Các vấn đề liên quan