2017-03-31 10 views
0

일단 버튼을 누르면 JPanel에 임의의 숫자가 추가되는 기능을 구현하려고합니다. (나는 실제 프로그램에서 내부에 더 많은 항목이 있고 올바르게 표시되기 때문에 내가 가지고있는 레이아웃을 사용합니다.) 그러나 스크롤바가 보이면 (스크롤 바가 보이기 시작한 것을 인식 할 필요가있다. (약간의 지연이있다.) 지연이 나는 것은 스크롤바가 보이지 않으면 아무 것도하지 않고 버튼을 눌러 숫자를 추가한다는 것이다. 다음 번에 나는 원하는대로 단추를 누른다.) 내가 가지고있는 다른 문제는 (현재 집중하고있는 것 중 하나입니다.) JPanel의 크기를 동적으로 변경할 때 스크롤바가 보이면 너비를 스크롤 바의 너비로 변경하도록 설정했습니다. . 그러나 스크롤바가 보이면 새로 입력 된 숫자가 스크롤바 폭의 두 배가 넘는 것처럼 보입니다. 나는 하루 동안 내 프로그램의이 부분에 있었고 그것을 이해할 수 없다. 전체 코드와 스크린 샷을 추가하겠습니다. 스크롤 막대가 나타날 때 Java 동적으로 변경되는 구성 요소

enter image description here

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.Random; 

import javax.swing.BorderFactory; 
import javax.swing.BoxLayout; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.UIManager; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 


public class Main { 
    JFrame frame; 
    JPanel topPanel; 
    JPanel memoryPanel; 
    JScrollPane sPane; 
    JButton button; 
    ArrayList<Integer> list = new ArrayList<>(); 
    boolean isVScrollVisible = false; 
    int scrollBarSize = 0; 

    public class MyChangeListener implements ChangeListener { 
     @Override 
     public void stateChanged(ChangeEvent e) { 
      isVScrollVisible = (sPane.getVerticalScrollBar().isVisible()); 
     } 
    } 

    public class ButtonListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      Random random = new Random(); 
      int r = random.nextInt(10); 

      list.add(r); 

      int n; 
      if (isVScrollVisible) { 
       n = scrollBarSize; 
      } else { 
       n = 0; 
      } 

      JPanel nextPanel = new JPanel(); 
      nextPanel.setName("" + r); 
      nextPanel.setForeground(Color.BLACK); 
      nextPanel.setPreferredSize(new Dimension(200 - n, 55)); 
      nextPanel.setMinimumSize(new Dimension(200 - n, 55)); 
      nextPanel.setMaximumSize(new Dimension(200 - n, 55)); 

      JPanel labelPanel = new JPanel(); 
      labelPanel.setLayout(new BorderLayout()); 

      JLabel label = new JLabel(); 
      label.setText("" + r); 
      label.setPreferredSize(new Dimension(200 - n, 55)); 
      label.setMinimumSize(new Dimension(200 - n, 55)); 
      label.setMaximumSize(new Dimension(200 - n, 55)); 
      label.setHorizontalAlignment(JLabel.RIGHT); 
      label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 17)); 
      label.setFont(new Font("Sans-Serif", Font.BOLD, 20)); 
      labelPanel.add(label); 

      nextPanel.add(labelPanel, BorderLayout.LINE_START); 

      for (int i = 0; i < memoryPanel.getComponents().length; i++) { 
       memoryPanel.getComponent(i).setPreferredSize(new Dimension(200 - n, 55)); 
       memoryPanel.getComponent(i).revalidate(); 
       memoryPanel.getComponent(i).repaint(); 
      } 


      memoryPanel.add(nextPanel, 0); 

      memoryPanel.revalidate(); 
      memoryPanel.repaint(); 
      sPane.revalidate(); 
      sPane.repaint(); 
     } 
    } 

    public Main() { 
     frame = new JFrame(); 

     topPanel = new JPanel(); 
     memoryPanel = new JPanel(); 
     memoryPanel.setLayout(new BoxLayout(memoryPanel, BoxLayout.Y_AXIS)); 

     sPane = new JScrollPane(memoryPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
     sPane.setPreferredSize(new Dimension(200, 300)); 
     sPane.getViewport().addChangeListener(new MyChangeListener()); 

     scrollBarSize = ((Integer)UIManager.get("ScrollBar.width")) + 1; 

     button = new JButton("Add Random Number"); 
     button.addActionListener(new ButtonListener()); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLayout(new BorderLayout()); 

     topPanel.add(button); 

     frame.add(topPanel, BorderLayout.PAGE_START); 
     frame.add(sPane, BorderLayout.CENTER); 

     frame.setResizable(false); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

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

나는 그들이 정확히 같은 볼 필요가있다. 내가 지금 가지고있는 코드를 갖기 전에 스크롤 막대가보기 흉한 숫자 위에 나타납니다. 그리고 내가 프레임을 크기를 조정할 수있는 이유는 실제 프로그램에서 모든 크기를 하드 코딩했기 때문입니다. 미래에는 프레임의 크기에 따라 올바른 크기를 계산할 것이므로 지금 크기를 재조정 할 수있는 설정이 부족합니다. 질문. 무엇에 대한 제안?

enter image description here

이 내가 accompolish하기 위해 노력하고있어 것입니다.

+0

1)이 사용 사례는'ListCellRenderer'를 사용하는'JScrollPane'의'JList'에 훨씬 더 적합합니다.2) 정의 된 상수가있을 때 폰트 이름을 추측하지 마십시오. ("Sans-Serif", Font.BOLD, 20)'새로운 글꼴 (Font.SANS_SERIF, Font.BOLD, 20)'이어야합니다. –

+0

실제 프로그램에는 버튼이 있기 때문에 JList를 사용하지 않았습니다. 모든 라벨에 대해. – Vince

+0

버튼의 기능은 무엇입니까? –

답변

1

선호/최소/최대 크기를 설정하는 모든 논리를 제거하십시오. 각 구성 요소는 크기가 무엇인지 알고 있습니다. 각 레이아웃 관리자는 패널의 기본 크기를 결정해야합니다. 레이아웃 관리자가 정보를 사용하여 작업을 수행하게하십시오.

동적으로 추가 구성 요소에 대한 기본 논리는 다음과 같습니다 필요할 때

panel.add(...); 
panel.revalidate(); 
panel.repaint(); 

그런 다음 스크롤바가 자동으로 나타납니다. 청취자 등은 필요 없습니다.

편집 : 다음 그들을 밖으로 가지고가는 경우에 모든

적절하고 효과적으로 레이아웃 매니저를 사용하는 방법에 대해 알아

을 중심으로 나타나기 때문에

나는 모든 크기를 설정 한 이유입니다. 예를 들어

사용하여 구성 요소의 배향을 제어 할 수있는 BoxLayout 사용 :

component.setAlignmentX(JLabel.RIGHT_ALIGNMENT); 

및 컴포넌트가 컴포넌트에 이용 가능한 공간의 오른쪽 가장자리로 정렬된다.

JLabel을 사용할 때 JLabel의 속성을 설정하여 텍스트를 레이블의 오른쪽 가장자리에 정렬해야 할 수도 있습니다. 해당 메소드에 대한 JLabel API를 읽으십시오.

+0

내가 모든 크기를 설정 한 이유는 모든 것을 꺼내면 모든 것이 가운데에 나타납니다. – Vince

+0

@Vince, edit를 참조하십시오. – camickr