2016-10-30 5 views
1

現在、私が取り組んでいるプロジェクトの一環として、(暗号アルゴリズムの一部として)ビットの順列を視覚化するために使用できるコンポーネントを実装しています。私は、2つの行の「ピン」を作成し、ヒントの間に線を引いてそれらを接続し、それらの間に一種のウェブを作成することでそうしています。BoxLayoutを使用して、パネル間のスペースを0にしますか?

この重要な部分は、私がこの視覚化を他の視覚化(例えば私はS-Boxesを含めることができます)の一部と同様に使用しているため、ピンのオンとオフ。私の解決策は、JPanelを使用して、ピンの行を見えなくすることができるヘッダーとフッターのパネルに配置することでした。

私はBoxLayoutに垂直にレイアウトしていますが、ヘッダーの上とフッターの下にグルーを追加しても、それらの間にスペースがあります。

私の例初期化時に次のようになります。

Web without resizing.

そして、私はそれのサイズを変更すると、彼らは一緒に少し来るが、それでも片側だけに触れる:

Web after resizing.

私はこれがコンポーネントのサイズとレイアウトの面で私のユーザースペースをデバイススペースに変換する何らかの愚かな間違いだと思っていますが、私の人生にとってはそれを見つけることができません。私は混乱をお詫び申し上げますが、これは、私のコードです:ここ

import java.awt.BasicStroke; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.geom.Line2D; 
import java.awt.geom.Point2D; 
import java.awt.geom.Ellipse2D; 

import javax.swing.Box; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class PermutationWeb extends JPanel 
{ 
    private static enum EndPanelType 
    { 
     HEADER, FOOTER 
    } 

    private final JPanel header; 
    private final JPanel mainPanel; 
    private final JPanel footer; 

    private double widthFactor; 
    private double heightFactor; 
    private int  widthMax; 
    private int  heightMax; 
    private int[] indexMappings; 
    private Point2D.Double[] endpoints; 
    private Line2D.Double[] drawingLines; 

    public PermutationWeb(int indices, boolean endPanelsOn) 
    { 
     super(); 

     setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 

     widthMax = (indices + 1)*2; 
     heightMax = (int)Math.round(widthMax*(3.0/17.0)); 
     widthFactor = 1; 
     heightFactor = 1; 

     endpoints = new Point2D.Double[indices * 2]; 
     drawingLines = new Line2D.Double[indices]; 

     for(int i=0; i<indices; i++) 
     { 
      endpoints[i]   = new Point2D.Double(i*2+2, 0); 
      endpoints[i+indices] = new Point2D.Double(i*2+2, heightMax); 
      drawingLines[i] = new Line2D.Double(); 
     } 

     header = new WebEndPanel(EndPanelType.HEADER); 
     mainPanel = new WebMainPanel(); 
     footer = new WebEndPanel(EndPanelType.FOOTER); 

     add(Box.createVerticalGlue()); 
     add(header); 
     add(mainPanel); 
     add(footer); 
     add(Box.createVerticalGlue()); 

     setEndPanelsOn(endPanelsOn); 
    } 

    public Point2D getEndpoint(int index) 
    { 
     return endpoints[index]; 
    } 

    public void updateMappings(int[] mappings) 
    { 
     this.indexMappings = mappings; 

     for(int i=0; i<indexMappings.length; i++) 
     { 
      drawingLines[i].setLine(endpoints[i], endpoints[indexMappings.length + indexMappings[i]]); 
     } 

     //paint(); 
    } 

    public void setEndPanelsOn(boolean endPanelsOn) 
    { 
     header.setVisible(endPanelsOn); 
     footer.setVisible(endPanelsOn); 
    } 

    @Override 
    public Dimension getMaximumSize() 
    { 
     int height = mainPanel.getHeight(); 
     if(header.isVisible()) 
     { 
      height += (header.getHeight() * 2); 
     } 

     int width = mainPanel.getWidth(); 

     return new Dimension(width, height); 
    } 

    @Override 
    public Dimension getPreferredSize() 
    { 
     return getMaximumSize(); 
    } 

    public static void main(String[] args) 
    { 
     JFrame jf = new JFrame(); 
     jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     jf.setSize(800, 600); 

     int[] mappings = {0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15}; 

     PermutationWeb webTest = new PermutationWeb(16, true); 
     jf.add(webTest); 
     jf.setVisible(true); 
     webTest.setVisible(true); 

     webTest.updateMappings(mappings); 

     System.out.printf("Header: [%s]\nMainPanel: [%s]\nFooter: [%s]\n", 
       webTest.header.getSize().toString(), 
       webTest.mainPanel.getSize().toString(), 
       webTest.footer.getSize().toString()); 
    } 


    private class WebMainPanel extends WebSubPanel 
    { 
     private static final double HEIGHT_RATIO = 0.25; 

     @Override 
     public void paintComponent(Graphics g) 
     { 
      Graphics2D g2 = (Graphics2D)g; 
      super.paintComponent(g2); 

      scaleTo(getSize()); 
      g2.scale(widthFactor, widthFactor); 
      g2.setStroke(new BasicStroke((float)(2.0/widthFactor))); 

      for(Line2D line: drawingLines) 
      { 
       g2.draw(line); 
      } 
     } 

     @Override 
     public Dimension getMaximumSize() 
     { 
      return new Dimension(MAX_WIDTH_PX, (int)(MAX_WIDTH_PX*HEIGHT_RATIO)); 
     } 
    } 

    private class WebEndPanel extends WebSubPanel 
    { 
     private static final double HEIGHT_RATIO = 0.125; 
     private static final double PIN_RADIUS = 0.5; 

     private final EndPanelType endType; 
     private Line2D.Double[] edgeLines; 
     private Ellipse2D.Double[] pinHeads; 

     public WebEndPanel(EndPanelType endType) 
     { 
      super(); 
      this.endType = endType; 
      this.edgeLines = new Line2D.Double[endpoints.length/2]; 
      this.pinHeads = new Ellipse2D.Double[endpoints.length/2]; 

      for(int i=0; i<edgeLines.length; i++) 
      { 
       Point2D pointA; 
       Point2D pointB; 


       if(EndPanelType.HEADER.equals(this.endType)) 
       { 
        pointA = new Point2D.Double(i*2+2, 4); 
        pointB = new Point2D.Double(i*2+2, 2); 

        pinHeads[i] = new Ellipse2D.Double(
          pointB.getX()-PIN_RADIUS, 
          pointB.getY()-PIN_RADIUS*2, 
          PIN_RADIUS*2, 
          PIN_RADIUS*2); 
       } 
       else // FOOTER 
       { 
        pointA = new Point2D.Double(i*2+2, 0); 
        pointB = new Point2D.Double(i*2+2, 2); 

        pinHeads[i] = new Ellipse2D.Double(
          pointB.getX()-PIN_RADIUS, 
          3-PIN_RADIUS*2, 
          PIN_RADIUS*2, 
          PIN_RADIUS*2); 
       } 

       edgeLines[i] = new Line2D.Double(pointA, pointB); 
      } 
     } 

     @Override 
     public Dimension getMaximumSize() 
     { 
      return new Dimension(MAX_WIDTH_PX, (int)(MAX_WIDTH_PX*HEIGHT_RATIO)); 
     } 

     @Override 
     public void paintComponent(Graphics g) 
     { 
      Graphics2D g2 = (Graphics2D)g; 
      super.paintComponent(g2); 

      scaleTo(getSize()); 
      g2.scale(widthFactor, widthFactor); 
      g2.setStroke(new BasicStroke((float)(2.0/widthFactor))); 

      for(Line2D line: edgeLines) 
      { 
       g2.draw(line); 
      } 

      for(Ellipse2D pin: pinHeads) 
      { 
       g2.draw(pin); 
      } 
     } 
    } 

    private abstract class WebSubPanel extends JPanel 
    { 
     protected static final int MAX_WIDTH_PX = 800; 

     public WebSubPanel() 
     { 
      super(); 
      setBorder(null); 
      setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); 
     } 

     public void scaleTo(Dimension d) 
     { 
      widthFactor = d.getWidth()/(double)widthMax; 
      heightFactor = d.getHeight()/(double)heightMax; 
     } 

     @Override 
     public Dimension getPreferredSize() 
     { 
      return getMaximumSize(); 
     }   
    } 
} 

究極の目標は、(ヘッダーとフッターWebEndPanel sが見えなくすることができ、サイズ変更可能なウェブですが、示されたときに、それらとの間にWebMainPanel 0のスペースを持っています彼らが単一のエンティティであるかのように)。

+1

コードをもう少し調べる必要がありますが、一見すると、このすべてを*単一パネルにペイントすることを検討する必要があります。あなたは望みの効果をすべて達成することができ、レイアウトマネージャーには依存しません(「通常のGUI」ではうまくいくかもしれませんが、カスタムペイントのために壊れやすいかもしれません)。 – Marco13

+0

@ Marco13私は間違いなくすべてを描く簡単なソリューションこのプロジェクトでは、ユーザーが定義したオンデマンドで作成されたさまざまなカスタムシェイプの異なる設定が必要です。この問題に直面しなければ、後で直面することになりました。 –

答えて

2

BoxLayoutは、スペースが利用可能な場合、最大サイズまでコンポーネントのサイズを変更します。

まずコンポーネントのgetPreferredSize()メソッドを実装して、通常のサイズで表示されるようにパックすることができます。

次に拡大する能力がある場合(カスタムペイントでこれをサポートしている場合)は、getMaximumSize()メソッドをオーバーライドしてサイズを返します。

したがって、他のパネルと連続しているようにするには、パネルの実際のサイズに基づいてペイントする必要があります。

+0

関連する例がここに見られる(http://stackoverflow.com/a/34443937/230513)。 – trashgod

+0

私はBoxLayoutが最大サイズを尊重していると理解しましたが、あなたの答えは私の問題を最終的に解決しようとしました。getMaximumSize()は常にMAX_VALUEの幅を持ち、実際の幅に対する比率を用いてその好ましい高さを制限した。 –

関連する問題