2011-06-29 55 views
1

我試圖讓內部框架包含選項卡式窗格。但是,我的代碼似乎並未將窗格加載到內部框架中。我有我的代碼在java文件中,稱爲InternalFrame.java和TabbedPaneSample.java。兩個文件的代碼都包含在下面。任何人都可以告訴我如何修復下面的代碼,以便在運行InternalFrame.java時加載選項卡式窗格?內部框架內的Java選項卡式窗格

這裏是我的代碼:

爲InternalFrame.java的代碼是:

package test; 

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.Panel; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import javax.swing.JButton; 
import javax.swing.JDesktopPane; 
import javax.swing.JFrame; 
import javax.swing.JInternalFrame; 
import javax.swing.JLayeredPane; 

public class InternalFrame extends JFrame { 
    JButton openButton; 
JLayeredPane desktop; 
JInternalFrame internalFrame; 
TabbedPaneSample myTabbedPaneSample = new TabbedPaneSample(); 

public InternalFrame() { 
    super("Click button to open internal frame with two panels."); 
    setSize(500, 400); 
    openButton = new JButton("Open"); 
    Panel p = new Panel(); 
    p.add(openButton); 
    add(p, BorderLayout.SOUTH); 
    addWindowListener(new WindowAdapter() { 
     public void windowClosing(WindowEvent e) { 
      System.exit(0); 
     } 
    }); 
    openButton.addActionListener(new OpenListener()); 
    desktop = new JDesktopPane(); 
    desktop.setOpaque(true); 
    add(desktop, BorderLayout.CENTER); 
} 
class OpenListener implements ActionListener { 
    public void actionPerformed(ActionEvent e) { 
     if ((internalFrame == null) || (internalFrame.isClosed())) { 
      internalFrame = new JInternalFrame("Internal Frame", true, true, true, true); 
      internalFrame.setBounds(50, 50, 200, 100); 
      internalFrame.add(myTabbedPaneSample, BorderLayout.CENTER); 
      internalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      internalFrame.pack(); 
      internalFrame.setMinimumSize(new Dimension(300, 300)); 
      desktop.add(internalFrame, new Integer(1)); 
      internalFrame.setVisible(true); 
     } 
    } 
} 
public static void main(String args[]) { 
    InternalFrame myInternalFrame = new InternalFrame(); 
    myInternalFrame.setVisible(true); 
} 
} 

而對於TabbedPaneSample.java代碼:

package test; 

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTabbedPane; 

public class TabbedPaneSample extends JTabbedPane { 
private JTabbedPane tabbedPane = new JTabbedPane(); 
private ImageIcon closeImage = new ImageIcon("C:/test/shipIcon.gif"); 
private Dimension closeButtonSize; 
private int tabCounter = 0; 

public TabbedPaneSample() { 
    closeButtonSize = new Dimension(closeImage.getIconWidth() + 2, closeImage.getIconHeight() + 2); 
    } 
public void add() { 
    final JPanel content = new JPanel(); 
    JPanel tab = new JPanel(); 
    tab.setOpaque(false); 
    JLabel tabLabel = new JLabel("Tab " + (++tabCounter)); 
    JButton tabCloseButton = new JButton(closeImage); 
    tabCloseButton.setPreferredSize(closeButtonSize); 
    tabCloseButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      int closeTabNumber = tabbedPane.indexOfComponent(content); 
      tabbedPane.removeTabAt(closeTabNumber); 
     } 
    }); 
    tab.add(tabLabel, BorderLayout.WEST); 
    tab.add(tabCloseButton, BorderLayout.EAST); 
    this.addTab(null, content); 
    this.setTabComponentAt(this.getTabCount() - 1, tab); 
} 
public static void main(String[] args) { 
    TabbedPaneSample main = new TabbedPaneSample(); 
    main.add(); 
    main.add(); 
} 
} 
+1

是否有任何理由爲什麼你在使用'javax.swing.JPanel'的地方使用'java.awt.Panel'?如果你沒有很好的理由這樣做,你應該避免混合AWT和Swing組件。 – jfpoilpret

+0

非常感謝您的幫助。我將在明天詳細回顧這些代碼,並在那個時候專門回覆。 – CodeMed

回答

3

這裏有一個方法,如下圖所示。使用Action的更靈活的方法標記爲here。如圖所示,您應該讓各種佈局管理器和組件首選大小執行更多的工作。特別是,this.setPreferredSize()用於演示目的。在實際的應用程序中,您可以恢復用戶大小和位置首選項。

Desktop pane with internal frames

package overflow; 

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JDesktopPane; 
import javax.swing.JFrame; 
import javax.swing.JInternalFrame; 
import javax.swing.JLabel; 
import javax.swing.JLayeredPane; 
import javax.swing.JPanel; 
import javax.swing.JTabbedPane; 

/** @see https://stackoverflow.com/posts/6514889 */ 
public class InternalFrame extends JFrame { 

    JButton openButton; 
    JLayeredPane desktop; 
    JInternalFrame internalFrame; 

    public InternalFrame() { 
     super("Click button to open internal frame with two tabs."); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.setPreferredSize(new Dimension(400, 400)); 
     openButton = new JButton("Open"); 
     JPanel p = new JPanel(); 
     p.add(openButton); 
     this.add(p, BorderLayout.SOUTH); 
     openButton.addActionListener(new OpenListener()); 
     desktop = new JDesktopPane(); 
     this.add(desktop, BorderLayout.CENTER); 
     this.pack(); 
     this.setLocationRelativeTo(null); 
    } 

    class OpenListener implements ActionListener { 

     private static final int DELTA = 40; 
     private int offset = DELTA; 

     public void actionPerformed(ActionEvent e) { 
      internalFrame = new JInternalFrame(
       "Internal Frame", true, true, true, true); 
      internalFrame.setLocation(offset, offset); 
      offset += DELTA; 
      internalFrame.add(createTabbedPane()); 
      desktop.add(internalFrame); 
      internalFrame.pack(); 
      internalFrame.setVisible(true); 
     } 
    } 

    private JTabbedPane createTabbedPane() { 
     JTabbedPane jtp = new JTabbedPane(); 
     createTab(jtp, "One"); 
     createTab(jtp, "Two"); 
     return jtp; 
    } 

    private void createTab(JTabbedPane jtp, String s) { 
     jtp.add(s, new JLabel("TabbedPane " + s, JLabel.CENTER)); 
    } 

    public static void main(String args[]) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       InternalFrame myInternalFrame = new InternalFrame(); 
       myInternalFrame.setVisible(true); 
      } 
     }); 
    } 
} 
+1

我沒有看到任何理由來擴展'JTabbedPane'。當然,也沒有理由擴展'JFrame'。 :-) – trashgod

+0

@trashgod good +1 – mKorbel

+0

再次感謝您。我嘗試了這一點,它主要工作,但每個內部框架的大小太小。我試着添加this.setMinimumSize(new Dimension(300,300));和this.setSize(300,300);緊隨你的this.setPreferredSize(new Dimension(400,400)); 。但是,內部框架的大小沒有改變。對於如何解決這個問題,你有任何建議,以便內部框架的大小默認爲某些定義的最小值,例如(300,300)?我應該注意到我正在使用Windows 7,當然這需要跨平臺。 – CodeMed

2

首先,我覺得最後,我認爲你不應該使用desktop.add(internalFrame, new Integer(1))而是desktop.add(internalFrame)相反,原因是JDesktopPane使用其層(它是一個JLayeredPane子類)內部,我不認爲你應該自己玩。

然後,以下this problemJInternalFrame曾經,我勸你打電話pack()後加入內部框架到桌面窗格。

因此,你應該嘗試用你的OpenListener類看起來像這樣:

class OpenListener implements ActionListener { 
    public void actionPerformed(ActionEvent e) { 
     if ((internalFrame == null) || (internalFrame.isClosed())) { 
      internalFrame = new JInternalFrame("Internal Frame", true, true, true, true); 
      internalFrame.setBounds(50, 50, 200, 100); 
      internalFrame.add(myTabbedPaneSample, BorderLayout.CENTER); 
      internalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
//   internalFrame.pack(); 
      internalFrame.setMinimumSize(new Dimension(300, 300)); 
//   desktop.add(internalFrame, new Integer(1)); 
      desktop.add(internalFrame); 
      internalFrame.pack(); 
      internalFrame.setVisible(true); 
     } 
    } 
} 

此外,我還對課程的Action trashgod意見和簡化返修他已經在你的代碼段完成同意。

+0

偉大的國家(博客)+1 for Java – mKorbel

+0

+1感謝您對此進行擴展; 'add()'後跟'pack()'是有經驗的,但我不知道爲什麼。 – trashgod

+0

@mKorbel:您的+1似乎已丟失。 :-) – trashgod

1

我優選在我的主框架類(其延伸的JFrame)來創建下面的函數:

private void showIntFrame(Class intFrameClass) { 
    JInternalFrame targetFrame = null; 
    int xoff = 0, yoff = 0; 
    for(JInternalFrame jif : jdp.getAllFrames()) { 
     if(jif.getClass().equals(intFrameClass)) 
      targetFrame = jif; 
     if(jif.getLocation().x > xoff) 
      xoff = jif.getLocation().x; 
     if(jif.getLocation().y > yoff) 
      yoff = jif.getLocation().y; 
     } 
     if(targetFrame == null) { 
      try { 
       Constructor<JInternalFrame> c = intFrameClass.getConstructor(MainFrame.class); 
       targetFrame = c.newInstance(MainFrame.this); 
      } catch (Exception ex) { 
       System.err.println("Exception in MainFrame.showIntFrame() while creating new JInternalFrame instance. " + ex.getLocalizedMessage()); 
       ex.printStackTrace(); 
       return; 
      } 
      jdp.add(targetFrame); 
      targetFrame.setLocation(xoff + 30, yoff + 30); 
     } 
     targetFrame.setVisible(true); 
     try { 
      targetFrame.setSelected(true); 
     } catch (PropertyVetoException ex) { 
      System.err.println("PropertyVetoException in MainFrame.showIntFrame() while activating JInternalFrame instance. " + ex.getLocalizedMessage()); 
     } 
} 

這裏JDP JDesktopPane的是,這在以前設定爲我的主要JFrame的contentPane而實例。

因爲我的程序通常包含從JInternalFrame繼承的不同類的數量,所以從事件處理程序調用此函數可以更容易地顯示JInternalFrame的新子類。

我的程序中的JInternalFrame的每個子類都有一個帶有一個參數的構造函數 - MainFrame(main JFrame)。