2011-10-11 73 views
5

我都在彼此的一個JPanel設置爲一個網格佈局下面一系列的組件。 我需要暫時隱藏組件,但setVisible(false)不會削減它,因爲組件所在的空隙仍然存在。隱形組件仍然佔用空間的JPanel

是否有一個快速簡便的方法來做到這一點?或者我必須保存JPanel的狀態,刪除組件,然後恢復它?

SSCCE:

[GridLayout2.java]

import java.awt.Component; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.Insets; 

public class GridLayout2 extends GridLayout 
{ 
    public GridLayout2() { 
    this(1, 0, 0, 0); 
    } 

    public GridLayout2(int rows, int cols) { 
    this(rows, cols, 0, 0); 
    } 

    public GridLayout2(int rows, int cols, int hgap, int vgap) { 
    super(rows, cols, hgap, vgap); 
    } 

    public Dimension preferredLayoutSize(Container parent) { 
    //System.err.println("preferredLayoutSize"); 
    synchronized (parent.getTreeLock()) { 
     Insets insets = parent.getInsets(); 
     int ncomponents = parent.getComponentCount(); 
     int nrows = getRows(); 
     int ncols = getColumns(); 
     if (nrows > 0) { 
     ncols = (ncomponents + nrows - 1)/nrows; 
     } 
     else { 
     nrows = (ncomponents + ncols - 1)/ncols; 
     } 
     int[] w = new int[ncols]; 
     int[] h = new int[nrows]; 
     for (int i = 0; i < ncomponents; i ++) { 
     int r = i/ncols; 
     int c = i % ncols; 
     Component comp = parent.getComponent(i); 
     Dimension d = comp.getPreferredSize(); 
     if (w[c] < d.width) { 
      w[c] = d.width; 
     } 
     if (h[r] < d.height) { 
      h[r] = d.height; 
     } 
     } 
     int nw = 0; 
     for (int j = 0; j < ncols; j ++) { 
     nw += w[j]; 
     } 
     int nh = 0; 
     for (int i = 0; i < nrows; i ++) { 
     nh += h[i]; 
     } 
     return new Dimension(insets.left + insets.right + nw + (ncols-1)*getHgap(), 
      insets.top + insets.bottom + nh + (nrows-1)*getVgap()); 
    } 
    } 

    public Dimension minimumLayoutSize(Container parent) { 
    System.err.println("minimumLayoutSize"); 
    synchronized (parent.getTreeLock()) { 
     Insets insets = parent.getInsets(); 
     int ncomponents = parent.getComponentCount(); 
     int nrows = getRows(); 
     int ncols = getColumns(); 
     if (nrows > 0) { 
     ncols = (ncomponents + nrows - 1)/nrows; 
     } 
     else { 
     nrows = (ncomponents + ncols - 1)/ncols; 
     } 
     int[] w = new int[ncols]; 
     int[] h = new int[nrows]; 
     for (int i = 0; i < ncomponents; i ++) { 
     int r = i/ncols; 
     int c = i % ncols; 
     Component comp = parent.getComponent(i); 
     Dimension d = comp.getMinimumSize(); 
     if (w[c] < d.width) { 
      w[c] = d.width; 
     } 
     if (h[r] < d.height) { 
      h[r] = d.height; 
     } 
     } 
     int nw = 0; 
     for (int j = 0; j < ncols; j ++) { 
     nw += w[j]; 
     } 
     int nh = 0; 
     for (int i = 0; i < nrows; i ++) { 
     nh += h[i]; 
     } 
     return new Dimension(insets.left + insets.right + nw + (ncols-1)*getHgap(), 
      insets.top + insets.bottom + nh + (nrows-1)*getVgap()); 
    } 
    } 

    public void layoutContainer(Container parent) { 
    //System.err.println("layoutContainer"); 
    synchronized (parent.getTreeLock()) { 
     Insets insets = parent.getInsets(); 
     int ncomponents = parent.getComponentCount(); 
     int nrows = getRows(); 
     int ncols = getColumns(); 
     if (ncomponents == 0) { 
     return; 
     } 
     if (nrows > 0) { 
     ncols = (ncomponents + nrows - 1)/nrows; 
     } 
     else { 
     nrows = (ncomponents + ncols - 1)/ncols; 
     } 
     int hgap = getHgap(); 
     int vgap = getVgap(); 
     // scaling factors  
     Dimension pd = preferredLayoutSize(parent); 
     double sw = (1.0 * parent.getWidth())/pd.width; 
     double sh = (1.0 * parent.getHeight())/pd.height; 
     // scale 
     int[] w = new int[ncols]; 
     int[] h = new int[nrows]; 
     for (int i = 0; i < ncomponents; i ++) { 
     int r = i/ncols; 
     int c = i % ncols; 
     Component comp = parent.getComponent(i); 
     Dimension d = comp.getPreferredSize(); 
     d.width = (int) (sw * d.width); 
     d.height = (int) (sh * d.height); 
     if (w[c] < d.width) { 
      w[c] = d.width; 
     } 
     if (h[r] < d.height) { 
      h[r] = d.height; 
     } 
     } 
     for (int c = 0, x = insets.left; c < ncols; C++) { 
     for (int r = 0, y = insets.top; r < nrows; r ++) { 
      int i = r * ncols + c; 
      if (i < ncomponents) { 
      parent.getComponent(i).setBounds(x, y, w[c], h[r]); 
      } 
      y += h[r] + vgap; 
     } 
     x += w[c] + hgap; 
     } 
    } 
    } 
} 

[SSCCE.java]

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

public class SSCCE extends JFrame{ 

    JPanel innerPane = new JPanel(); 
    JScrollPane scr = new JScrollPane(innerPane); 

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


    public SSCCE() { 

     setSize(400, 800); 
     innerPane.setLayout(new GridLayout2(0, 1)); 

     add(scr); 

     for (int i = 0; i < 30; i++) 
     { 
      innerPane.add(getPane()); 
     } 

     setVisible(true); 

     try { 
      Thread.sleep(2000); 
     } catch (InterruptedException e) {} 

     for (int i = 0; i < 30; i++) 
     { 
      if (i%2==0) 
       innerPane.getComponent(i).setVisible(false); 
     } 

    } 


    private JPanel getPane() 
    { 
     JPanel ret = new JPanel(); 
     JLabel lbl = new JLabel("This is a pane."); 

     ret.add(lbl); 
     ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); 
     ret.setBackground(Color.gray); 

     return ret; 

    } 

} 

screenshot

+2

您的問題*可能*是由於您使用網格佈局中可以就此網格點取決於它如何建立開放的,但心裏很不舒服,我只是在猜測這就是全部人能做到給予迄今給出的信息。如果您很快就沒有得到正確的答案,我建議您創建併發布[SSCCE](http://sscce.org),供我們測試,修改和幫助修復。 –

+0

您可能想看看比GridLayout功能強大的第三方LayoutManagers,它取決於您需要的佈局(看起來您僅暴露了部分問題)。我建議你看看DesignGridLayout,它可以處理你想要的東西(但是使用特定的API);其主要優勢是其學習曲線非常短(與其他LayoutManagers相比)。 – jfpoilpret

回答

9

,因爲組件所在的空隙仍然存在。

是,網格佈局是不是聰明。它只是使用組件的總數來確定行/列的數量。

是否有一個快速簡便的方法來做到這一點?

我想創建一個自定義佈局管理器。只需複製GridLayout代碼並進行一些更改即可。基本的變化將是:

  1. 重寫ncomponents變量。而不是僅使用面板上的組件數量,您需要循環使用所有組件並計數可見的組件。

  2. 在佈局代碼,你需要添加一個if (visible)檢查。

編輯:

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

public class InvisibleGridLayout implements LayoutManager, java.io.Serializable 
{ 
    int hgap; 
    int vgap; 
    int rows; 
    int cols; 

    public InvisibleGridLayout() { 
    this(1, 0, 0, 0); 
    } 

    public InvisibleGridLayout(int rows, int cols) { 
    this(rows, cols, 0, 0); 
    } 

    public InvisibleGridLayout(int rows, int cols, int hgap, int vgap) { 
    if ((rows == 0) && (cols == 0)) { 
     throw new IllegalArgumentException("rows and cols cannot both be zero"); 
    } 
    this.rows = rows; 
    this.cols = cols; 
    this.hgap = hgap; 
    this.vgap = vgap; 
    } 

    public int getRows() { 
    return rows; 
    } 

    public void setRows(int rows) { 
    if ((rows == 0) && (this.cols == 0)) { 
     throw new IllegalArgumentException("rows and cols cannot both be zero"); 
    } 
    this.rows = rows; 
    } 

    public int getColumns() { 
    return cols; 
    } 

    public void setColumns(int cols) { 
    if ((cols == 0) && (this.rows == 0)) { 
     throw new IllegalArgumentException("rows and cols cannot both be zero"); 
    } 
    this.cols = cols; 
    } 

    public int getHgap() { 
    return hgap; 
    } 

    public void setHgap(int hgap) { 
    this.hgap = hgap; 
    } 

    public int getVgap() { 
    return vgap; 
    } 

    public void setVgap(int vgap) { 
    this.vgap = vgap; 
    } 

    public void addLayoutComponent(String name, Component comp) { 
    } 

    public void removeLayoutComponent(Component comp) { 
    } 

    public Dimension preferredLayoutSize(Container parent) { 
     synchronized (parent.getTreeLock()) { 
    Insets insets = parent.getInsets(); 
// int ncomponents = parent.getComponentCount(); 
    int ncomponents = getVisibleComponents(parent); 
    int nrows = rows; 
    int ncols = cols; 

    if (nrows > 0) { 
     ncols = (ncomponents + nrows - 1)/nrows; 
    } else { 
     nrows = (ncomponents + ncols - 1)/ncols; 
    } 
    int w = 0; 
    int h = 0; 
// for (int i = 0 ; i < ncomponents ; i++) { 
    for (int i = 0 ; i < parent.getComponentCount(); i++) { 
     Component comp = parent.getComponent(i); 

     if (!comp.isVisible()) continue; // added 

     Dimension d = comp.getPreferredSize(); 
     if (w < d.width) { 
     w = d.width; 
     } 
     if (h < d.height) { 
     h = d.height; 
     } 
    } 

    Dimension d = new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap, 
       insets.top + insets.bottom + nrows*h + (nrows-1)*vgap); 

    return d; 
     } 
    } 

    public Dimension minimumLayoutSize(Container parent) { 
     synchronized (parent.getTreeLock()) { 
     Insets insets = parent.getInsets(); 
// int ncomponents = parent.getComponentCount(); 
    int ncomponents = getVisibleComponents(parent); 
    int nrows = rows; 
    int ncols = cols; 

    if (nrows > 0) { 
     ncols = (ncomponents + nrows - 1)/nrows; 
    } else { 
     nrows = (ncomponents + ncols - 1)/ncols; 
    } 
    int w = 0; 
    int h = 0; 
// for (int i = 0 ; i < ncomponents ; i++) { 
    for (int i = 0 ; i < parent.getComponentCount(); i++) { 
     Component comp = parent.getComponent(i); 

     if (!comp.isVisible()) continue; // added 

     Dimension d = comp.getMinimumSize(); 
     if (w < d.width) { 
     w = d.width; 
     } 
     if (h < d.height) { 
     h = d.height; 
     } 
    } 

    Dimension d = new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap, 
       insets.top + insets.bottom + nrows*h + (nrows-1)*vgap); 

    return d; 
     } 
    } 

    public void layoutContainer(Container parent) { 
     synchronized (parent.getTreeLock()) { 
    Insets insets = parent.getInsets(); 
// int ncomponents = parent.getComponentCount(); 
    int ncomponents = getVisibleComponents(parent); 
    int nrows = rows; 
    int ncols = cols; 
    boolean ltr = parent.getComponentOrientation().isLeftToRight(); 

    if (ncomponents == 0) { 
     return; 
    } 
    if (nrows > 0) { 
     ncols = (ncomponents + nrows - 1)/nrows; 
    } else { 
     nrows = (ncomponents + ncols - 1)/ncols; 
    } 

// int w = parent.width - (insets.left + insets.right); 
// int h = parent.height - (insets.top + insets.bottom); 
    int w = parent.getSize().width - (insets.left + insets.right); 
    int h = parent.getSize().height - (insets.top + insets.bottom); 
    w = (w - (ncols - 1) * hgap)/ncols; 
    h = (h - (nrows - 1) * vgap)/nrows; 
/* 
    if (ltr) { 
     for (int c = 0, x = insets.left ; c < ncols ; c++, x += w + hgap) { 
     for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) { 
      int i = r * ncols + c; 
      if (i < ncomponents) { 
      parent.getComponent(i).setBounds(x, y, w, h); 
      } 
     } 
     } 
    } else { 
//  for (int c = 0, x = parent.width - insets.right - w; c < ncols ; c++, x -= w + hgap) { 
     for (int c = 0, x = parent.getSize().width - insets.right - w; c < ncols ; c++, x -= w + hgap) { 
     for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) { 
      int i = r * ncols + c; 
      if (i < ncomponents) { 
      parent.getComponent(i).setBounds(x, y, w, h); 
      } 
     } 
     } 
    } 
     } 
*/ 

     int i = 0; 

     if (ltr) 
     { 
      for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) 
      { 
       int c = 0; 
       int x = insets.left; 

       while (c < ncols) 
       { 
        if (i >= parent.getComponentCount()) break; 

        Component component = parent.getComponent(i); 

        if (component.isVisible()) 
        { 
         parent.getComponent(i).setBounds(x, y, w, h); 
         c++; 
         x += w + hgap; 
        } 

        i++; 
       } 
      } 
     } 

    }} 

    private int getVisibleComponents(Container parent) 
    { 
     int visible = 0; 

     for (Component c: parent.getComponents()) 
     { 
      if (c.isVisible()) 
       visible++; 
     } 

     return visible; 
    } 

    public String toString() { 
    return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + 
          ",rows=" + rows + ",cols=" + cols + "]"; 
    } 



    public static void main(String[] args) 
    { 
     final JPanel innerPane = new JPanel(); 
     JScrollPane scr = new JScrollPane(innerPane); 

     innerPane.setLayout(new InvisibleGridLayout(0, 3)); 


     for (int i = 0; i < 30; i++) 
     { 
      JPanel ret = new JPanel(); 
      JLabel lbl = new JLabel("This is pane " + i); 

      ret.add(lbl); 
      ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); 
      ret.setBackground(Color.gray); 

      innerPane.add(ret); 
     } 

     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(scr); 
     frame.setBounds(400, 0, 400, 700); 
     frame.setVisible(true); 

     javax.swing.Timer timer = new javax.swing.Timer(2000, new ActionListener() 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       for (int i = 0; i < 30; i++) 
       { 
        if (i%2==0) 
         innerPane.getComponent(i).setVisible(false); 
       } 

      } 
     }); 
     timer.setRepeats(false); 
     timer.start(); 

    } 
} 
+0

我編輯了這個問題。我已經(偶然)需要修改GridLayout,因爲我需要不同大小的行。我添加了類代碼。我已經按照你的說法嘗試過了,但這不是微不足道的(對我來說)。我一直在for循環中獲取arrayIndexOutOfBoundsException。當你發現一個不可見的組件時,你會做什麼? – David

+0

我不知道你是什麼意思的「不同大小的行」。在你的SSCCE中,他們都和我看起來一樣大小。當你檢測到一個不可見的組件時,你可以忽略它。基本上你只需要調用continue語句。 – camickr

+0

SSCCE不顯示完整的問題。最初,我有多行可能會有所不同的大小。我放棄了嘗試。我只是將所有內容都存儲在Arraylist中,然後在最後重新添加所有刪除的行。我嘗試完全按照您的指示進行操作,但我的技能不足以實現它。 '1.'沒有問題,但是2.我總是得到一個ArrayIndexOutOfBounds異常,因爲組件在for循環中不能被忽略。即使我重寫「nComponents」,它仍然使用comp.getComponent(i),這是一個問題。它需要增加循環或類似的工作。 – David

2

我真的不喜歡的網格佈局。我建議你不要編寫自己的佈局管理器,而應該看看TableLayout。我用它所有的時間。

最初的學習曲線比網格佈局更陡了一點,但很容易得到它的行爲您想要的方式。

http://java.sun.com/products/jfc/tsc/articles/tablelayout/

+0

@RiaanCornelius它是一個GridLayout的修改版本,不是Gridbaglayout :)儘管如此,謝謝。 – David

+0

對不起,我錯誤輸入了......我的意思是GridLayout。我對我不喜歡Gridbag的描述會更形象:) –

4

這裏是我的頭頂部3種方式。

Hide Components

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

class HideComponents { 

    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JPanel gui = new JPanel(new BorderLayout()); 
       JToolBar tb = new JToolBar(); 
       gui.add(tb, BorderLayout.NORTH); 
       final JButton openTool = new JButton("Open"); 
       final JButton saveTool = new JButton("Save"); 
       tb.add(openTool); 
       tb.add(saveTool); 

       JPanel buttonFlow = new JPanel(new FlowLayout(3)); 
       gui.add(buttonFlow, BorderLayout.CENTER); 
       final JButton openFlow = new JButton("Open"); 
       final JButton saveFlow = new JButton("Save"); 
       buttonFlow.add(openFlow); 
       buttonFlow.add(saveFlow); 

       JPanel buttonBox = new JPanel(); 
       gui.add(buttonBox, BorderLayout.EAST); 
       BoxLayout bl = new BoxLayout(buttonBox, BoxLayout.Y_AXIS); 
       buttonBox.setLayout(bl); 
       final JButton openBox = new JButton("Open"); 
       final JButton saveBox = new JButton("Save"); 
       buttonBox.add(openBox); 
       buttonBox.add(saveBox); 

       final JCheckBox openChoice = new JCheckBox("Show open", true); 
       openChoice.addActionListener(new ActionListener() { 
        public void actionPerformed(ActionEvent ae) { 
         openTool.setVisible(openChoice.isSelected()); 
         openFlow.setVisible(openChoice.isSelected()); 
         openBox.setVisible(openChoice.isSelected()); 
        } 
       }); 
       gui.add(openChoice, BorderLayout.SOUTH); 

       JOptionPane.showMessageDialog(null, gui); 
      } 
     }); 
    } 
} 

在反射

請考慮換:

button.setVisible(false); 

爲:

button.setEnabled(false); 

這對於查看GUI的大多數用戶來說會更直觀,並且具有相同的最終效果。

可見:

Disable Components

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

class DisableComponents { 

    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JPanel gui = new JPanel(new BorderLayout()); 
       JToolBar tb = new JToolBar(); 
       gui.add(tb, BorderLayout.NORTH); 
       final JButton openTool = new JButton("Open"); 
       final JButton saveTool = new JButton("Save"); 
       tb.add(openTool); 
       tb.add(saveTool); 

       JPanel buttonFlow = new JPanel(new FlowLayout(3)); 
       gui.add(buttonFlow, BorderLayout.CENTER); 
       final JButton openFlow = new JButton("Open"); 
       final JButton saveFlow = new JButton("Save"); 
       buttonFlow.add(openFlow); 
       buttonFlow.add(saveFlow); 

       JPanel buttonBox = new JPanel(); 
       gui.add(buttonBox, BorderLayout.EAST); 
       BoxLayout bl = new BoxLayout(buttonBox, BoxLayout.Y_AXIS); 
       buttonBox.setLayout(bl); 
       final JButton openBox = new JButton("Open"); 
       final JButton saveBox = new JButton("Save"); 
       buttonBox.add(openBox); 
       buttonBox.add(saveBox); 

       final JCheckBox openChoice = new JCheckBox("Enable open", true); 
       openChoice.addActionListener(new ActionListener() { 
        public void actionPerformed(ActionEvent ae) { 
         openTool.setEnabled(openChoice.isSelected()); 
         openFlow.setEnabled(openChoice.isSelected()); 
         openBox.setEnabled(openChoice.isSelected()); 
        } 
       }); 
       gui.add(openChoice, BorderLayout.SOUTH); 

       JOptionPane.showMessageDialog(null, gui); 
      } 
     }); 
    } 
} 
+1

您錯過了整個觀點。我正在使用一個帶有行的gridLayout。現在程序即將準備就緒,現在要做的工作太多了。 – David

+0

不幸的是我需要隱藏組件而不刪除它:(我需要清理雜亂而不會使用戶界面變得醜陋,只需將它設置爲隱形就可以了,但是感謝您的建議,儘管如此 – David

3

EDT時不叫Thread.sleep(int);,因爲塊EDT,使用javax.swing.Timer

例如

import java.awt.Color; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import javax.swing.*; 
import javax.swing.border.*; 

public class SSCCE extends JFrame { 

    private static final long serialVersionUID = 1L; 
    private JPanel innerPane = new JPanel(); 
    private JScrollPane scr = new JScrollPane(innerPane); 
    private Timer timer; 

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

      @Override 
      public void run() { 
       SSCCE sSCCE = new SSCCE(); 
      } 
     }); 
    } 

    private JPanel getPane() { 
     JPanel ret = new JPanel(); 
     JLabel lbl = new JLabel("This is a pane."); 
     ret.add(lbl); 
     ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); 
     ret.setBackground(Color.gray); 
     return ret; 
    } 

    public SSCCE() { 
     innerPane.setLayout(new GridLayout(0, 1)); 
     add(scr); 
     for (int i = 0; i < 30; i++) { 
      innerPane.add(getPane()); 
     } 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
     start(); 
    } 

    private void start() { 
     timer = new javax.swing.Timer(2000, updateCol()); 
     timer.start(); 
     timer.setRepeats(false); 
    } 

    private Action updateCol() { 
     return new AbstractAction("Hide Row Action") { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       for (int i = 0; i < 30; i++) { 
        if (i % 2 == 0) { 
         innerPane.getComponent(i).setVisible(false); 
        } 
       } 
      } 
     }; 
    } 
} 
+0

我試圖保持簡短儘可能用代碼來證明這個問題,你的建議儘管表明了一種好的做法,但並不能解決已定義的問題 – David

+1

你的代碼證明只是亂七八糟的,順便說一句你的問題已經被另外的海報回答了,那麼沒有理由再重複一遍,感謝您的低調投票 – mKorbel

+0

對不起,我沒有回答,否則我會選擇一個答案,我在Camickr的建議中仍然有問題,我會用我試過的方法更新代碼。 – David

0

嘗試使用BoxLayout的用組件對齊。例如:

JPanel innerPane = new JPanel(); 
BoxLayout innerPaneLayout = new BoxLayout(innerPane,BoxLayout.Y_AXIS); 
innerPane.setLayout(innerPaneLayout); 

for (int i = 0; i < 30; i++) 
{ 
    JPane newPane = getPane(); 
    innerPane.add(newPane); 
    newPane.setAlignmentY(Component.TOP_ALIGNMENT); 
} 

for (int i = 0; i < 30; i++) 
{ 
     if (i%2==0) 
     innerPane.getComponent(i).setVisible(false); 
}