2016-12-20 7 views
0

Я прочитал некоторые ответы на вопросы в этом форуме (например,), где строго рекомендуется избегать использования методов setXXXSize() для изменения размеров компонентов в приложениях swing.Лучшая практика для изменения размера JScrollPane

Итак, придя к моей проблеме, я хотел бы знать, как наилучшим образом изменить размер JScrollPane, чтобы избежать его родительской панели, чтобы увеличить ее размер без какого-либо контроля.

Прежде чем написать какой-то код, я хочу описать реальную ситуацию, так как я отправлю «игрушечный пример».

В моем JFrame я в настоящее время использую макет границы для своей области содержимого. В BorderLayout.CENTER есть JPanel, где я делаю какую-то обычную картину. В BorderLayout.EAST есть JPanel (скажем, eastPanel), содержащий некоторые компоненты внутри другой панели (эта панель будет добавлена ​​к eastPanel в BorderLayout.NORTH) и JScrollPane, которая содержит JTable (добавлена ​​в eastPanel на BorderLayout.CENTER). В этой таблице будет много строк. Поскольку высота EastPanel так же высока, как и высота центраPanel, мне нужно каким-то образом избежать JScrollPane, чтобы увеличить его размер, чтобы попытаться отобразить как можно больше строк.

На данный момент я не смог найти другое решение, кроме вызова setPreferredSize на eastPanel, содержащего scrollpane, но я должен признать, что я ненавижу такое решение.

Пример кода

В этом примере кода я добавил некоторые случайные метки на севере eastPanel и внутри JScrollPane, так как моя цель состояла в том, чтобы оставить короткий образец кода. Однако ситуация очень похожа на ситуацию, описанную выше. я не был в состоянии решить мою проблему без использования этой «страшной» строки кода:

eastPanel.setPreferredSize(new Dimension(eastPanel.getPreferredSize().width, centerPanel.getPreferredSize().height)); 

Я хотел бы избежать более сложного макета для простой ситуации, как это. Я что-то упускаю ? Кроме того, устанавливается, что пустая граница - приемлемый способ установить размер панели, где я сделаю какую-то обычную картину?

Код:

import java.awt.*; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
public class Test 
{ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       try {      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
        new TestFrame().setVisible(true); 
       } 
       catch(Exception exception) { 
        JOptionPane.showMessageDialog(null, "Fatal error while initialiing application", "Error", JOptionPane.ERROR_MESSAGE); 
       } 
      } 
     }); 
    } 
} 
class TestFrame extends JFrame 
{ 
    public TestFrame() { 
     super("Test"); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     JPanel pane = new JPanel(new BorderLayout(20, 0)); 
     pane.setBorder(new EmptyBorder(20, 20, 20, 20)); 
     JPanel centerPanel = new JPanel(); 
     centerPanel.setBackground(Color.WHITE); 
     centerPanel.setBorder(new EmptyBorder(400, 400, 0, 0)); 
     // centerPanel.setPreferredSize(new Dimension(400, 400)); 
     JPanel eastPanel = new JPanel(new BorderLayout(0, 20)); 
     JPanel labelsContainer = new JPanel(new GridLayout(0, 1)); 
     for(int i=0;i<7;i++) labelsContainer.add(new JLabel(String.valueOf(i))); 
     eastPanel.add(labelsContainer, BorderLayout.NORTH); 
     JPanel moreLabelsContainer = new JPanel(new GridLayout(0, 1)); 
     for(int i=7;i<70;i++) moreLabelsContainer.add(new JLabel(String.valueOf(i))); 
     JScrollPane scroll = new JScrollPane(moreLabelsContainer, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
     eastPanel.add(scroll, BorderLayout.CENTER); 
     eastPanel.setPreferredSize(new Dimension(eastPanel.getPreferredSize().width, centerPanel.getPreferredSize().height)); 
     pane.add(centerPanel, BorderLayout.CENTER); 
     pane.add(eastPanel, BorderLayout.EAST); 
     setContentPane(pane); 
     pack(); 
     setLocationRelativeTo(null); 
    } 
} 

Спасибо за вашу помощь!

ответ

3

Мне неизвестно диспетчер компоновки, который ограничивает высоту панели в зависимости от высоты конкретного компонента на панели.

Один из способов - настроить поведение родительской панели, содержащей два дочерних компонента.

Код может быть что-то вроде:

@Override 
public Dimension getPreferredSize() 
{ 
    Dimension d = super.getPreferredSize(); 

    BorderLayout layout = (BorderLayout)getLayout(); 
    Component center = layout.getLayoutComponent(BorderLayout.CENTER); 

    int centerHeight = center.getPreferreidSize().height; 

    if (d.height > centerHeight) 
     d.height = centerHeight; 

    return d; 
} 

Такой подход позволит для динамического расчета высоты на основе компонента в центре.

Другой вариант - написать собственный менеджер макетов. Затем вы можете управлять этим типом логики из диспетчера компоновки.

Кроме того, устанавливается, что пустая граница - приемлемый способ установить размер панели, где я сделаю какую-то обычную картину?

Я переопределяю getPreferredSize(), чтобы вернуть соответствующее измерение.

С помощью EmptyBorder вы теряете возможность добавить истинную границу к панели, поэтому я бы не рекомендовал ее.

+0

Спасибо за ваш ответ. Читая некоторые сообщения, я ошибочно предположил, что если setPreferredSize считается настолько «злым», практика переопределения метода getPreferredSize не была бы намного лучше. Я рад получить этот совет от такого эксперта, как вы! Спасибо, и извините за мой плохой английский: D – Ansharja