Swing компонент setSize () / setBounds () проблема - PullRequest
4 голосов
/ 02 февраля 2012

Содержание


  1. Обзор
  2. Пример кода
  3. Скриншоты Проблем

1. Обзор проблемы


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

Сначала я использовал несколько макетов внутри jframe, и каждый jpanel пытался правильно расположить компоненты и соответствующим образом масштабировать их. Естественно, я сыт по горло ими, и я начал пытаться динамически масштабировать и устанавливать x, y позиции компонентов (это намного проще: D).

В основном я пытаюсь разделить экран на три части: левое поле (JSplitPane), центр (JTabbedPane) и правое поле (JSplitPane). Я не думаю, что внутренние компоненты имеют значение в этот момент. Основная проблема в : правая JSplitPane масштабируется по всему окну, несмотря на то, что я использовал setBounds (), чтобы поместить x, y справа и установить размер 21% от общей ширины. Кажется, странно взаимодействовать с другими панелями.


2. Пример кода


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;

import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.Dimension;

@SuppressWarnings("deprecation")
public class test extends JFrame implements WindowListener {

/* Constants =========================================================================*/
    private         final   double      LEFT_SIZE           =   .21;
    private         final   double      CENTER_SIZE         =   .58;
    private         final   double      RIGHT_SIZE          =   .21;
    private         final   int         TOP_PADDING         =   50;
    private         final   int         LEFT_PADDING        =   4;
    private         final   int         RIGHT_PADDING       =   4;
    private         final   int         BOTTOM_PADDING      =   4;
    private         final   int         MIN_WIDTH           =   640;
    private         final   int         MIN_HEIGHT          =   480;

    public  static  final   String      INIT_TITLE          =   "TestFrame v0.01";
/* End Constants =====================================================================*/

/* Instance Variables ================================================================*/
    private                 int         contentWidth;
    private                 int         contentHeight;
/* End Instance Variables ============================================================*/

/* Objects ===========================================================================*/        
    public  static  test        window;     

    /* Begin Frame Design =========================================================== */
        private         JSplitPane      left;
        private         JButton           button1;  private     JButton     button2;            
        private         JTabbedPane     center;
        private         JPanel            panel1;       private     JPanel      panel2;         
        private         JSplitPane      right;
        private         JButton           button3;  private     JButton     button4;
    /* End Frame Design ============================================================= */

/* End Objects ====================================================================== */

/** Initializes and Places all GUI elements **/
public test ( String windowName ) {
    super(windowName);              //call parent constructor
    this.addWindowListener(this);   //adds window event functionality such as close

    this.setExtendedState(this.getExtendedState() | JFrame.MAXIMIZED_BOTH); //Starts program maximized
    this.setMinimumSize(new Dimension(MIN_WIDTH,MIN_HEIGHT));
    this.setVisible(true);
    this.setMaximumSize(this.getSize());        

    /* Begin Init JFrame this ------------------------------------------------------------ */       
            button1 = new JButton("button1");               
            button2 = new JButton("button2");               
        left = new JSplitPane(JSplitPane.VERTICAL_SPLIT, button1, button2);
        left.setResizeWeight(1);

            button3 = new JButton("button3");               
            button4 = new JButton("button4");               
        right = new JSplitPane(JSplitPane.VERTICAL_SPLIT, button3, button4);
        right.setResizeWeight(.25);

            panel1 = new JPanel();              
            panel2 = new JPanel();              
        center = new JTabbedPane();
        center.addTab("Panel1", panel1);
        center.addTab("Panel2", panel2);

        this.add(left);
        this.add(center);
        this.add(right);

        this.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized    (ComponentEvent e) {
                window.contentWidth = window.getWidth() - window.LEFT_PADDING - window.RIGHT_PADDING;
                window.contentHeight = window.getHeight() - window.TOP_PADDING - window.BOTTOM_PADDING;

                window.left.setBounds               (   0,                                                  0,  (int)(window.contentWidth * window.LEFT_SIZE),      window.contentHeight);
                window.center.setBounds             (   window.left.getWidth(),                             0,  (int)(window.contentWidth * window.CENTER_SIZE),    window.contentHeight);
                window.panel1.setBounds             (   0,                                                  0,  (int)(window.contentWidth * window.CENTER_SIZE),    window.contentHeight);
                window.panel2.setBounds             (   0,                                                  0,  (int)(window.contentWidth * window.CENTER_SIZE),    window.contentHeight);
                window.right.setBounds              (   window.left.getWidth() + window.center.getWidth(),  0,  (int)(window.contentWidth * window.RIGHT_SIZE),     window.contentHeight);
             }
            public void componentHidden     (ComponentEvent e) {}
            public void componentMoved      (ComponentEvent e) {}
            public void componentShown      (ComponentEvent e) {}    

        });
        /* End Init JFrame this -------------------------------------------------------------- */
}

// window event abstracts
@Override
public void windowClosing       (WindowEvent event)     { window.dispose(); System.exit(0); } 
public void windowClosed        (WindowEvent event)     {}
public void windowDeiconified   (WindowEvent event)     {} 
public void windowIconified     (WindowEvent event)     {} 
public void windowActivated     (WindowEvent event)     {} 
public void windowDeactivated   (WindowEvent event)     {} 
public void windowOpened        (WindowEvent event)     {}

public static void main(String[] args){     
    window = new test(INIT_TITLE); 
    window.setVisible(true);
}
}

3. Скриншоты


Screenshot1 Screenshot2

1 Ответ

3 голосов
/ 02 февраля 2012

Я не думаю, что внутренние компоненты имеют значение в этот момент.

Как обсуждено в Если я не буду использовать методы set [Preferred | Maximum | Minimum] Size в Java Swing? , ничто не может быть дальше от истины. Правильное использование макетов зависит от предпочтительного размера компонента. Этот размер тщательно рассчитывается на основе содержимого. Второе предположение, как показано в вашем примере, обречено на провал.

Вместо этого добавьте компоненты и pack() фрейм. В приведенном ниже примере центральная панель возвращает произвольный результат, чтобы показать, как pack() работает.

Приложение: Два дополнительных пункта, которые @mKorbel предлагает с умом:

  • Объекты Swing GUI должны создаваться и управляться только в потоке диспетчеризации событий .

  • См. Также этот пример , который показывает, как использовать setDividerLocation() в invokeLater().

enter image description here

import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import java.awt.Dimension;
import java.awt.EventQueue;

public class Test extends JFrame {

    public static final String INIT_TITLE = "TestFrame v0.02";
    public static Test window;
    private JSplitPane left;
    private JTabbedPane center;
    private JSplitPane right;

    public Test(String windowName) {
        super(windowName);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        left = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
            new JButton("button1"), new JButton("button2"));
        left.setResizeWeight(0.5);

        right = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
            new JButton("button3"), new JButton("button4"));
        right.setResizeWeight(0.5);

        center = new JTabbedPane();
        center.addTab("Panel1", new MyPanel());
        center.addTab("Panel2", new MyPanel());

        this.add(left, BorderLayout.WEST);
        this.add(center, BorderLayout.CENTER);
        this.add(right, BorderLayout.EAST);

        this.pack();
        this.setLocationByPlatform(true);
        this.setVisible(true);
    }

    private static class MyPanel extends JPanel {

        private Dimension d = new Dimension(320, 240);

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

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

            @Override
            public void run() {
                window = new Test(INIT_TITLE);
                window.setVisible(true);
            }
        });
    }
}
...