Понимание менеджеров по расположению - я не, пожалуйста, просветите меня - PullRequest
2 голосов
/ 03 апреля 2011

Я просто не понимаю, почему вещи меняются, когда я вызываю методы validate () и repaint ().Я изо всех сил пытаюсь понять это.По сути, моя программа предназначена для отображения, как это.У меня есть основной кадр, в который я подключаю различные JPanels, которые я расширяю для различных функций моего фотоальбома.Класс ниже - это класс NewAlbum, который должен позволять пользователю выбирать файлы и создавать из них новый альбом.

Код для выбора файлов работает хорошо.После того, как файлы выбраны, изменение на панели NewAlbum должно состоять в том, что кнопка выбора файлов заменяется кнопкой ГотовоПод кнопкой «Готово» находится панель JSplitPane с горизонтальным сплиттером, смещенным от центра, причем правая сторона больше левой.Левая сторона в конечном итоге будет иметь миниатюру каждой фотографии, поскольку метаданные о ней будут введены в правую часть.

Правая панель должна быть JScrollPane с одной JPanel, которая в виде сетки имеет вид4 записи, о которых у пользователя запрашиваются данные.После добавления всего, размеры находятся там, где я хочу, чтобы они были, но когда я вызываю комбинацию проверки / перерисовки, измерения становятся «испорченными».Я почти уверен, что это потому, что я не понимаю, как менеджеры по умолчанию для различных классов, которые я использую или расширяю.Пожалуйста, помогите мне понять.Кроме того, скажите мне, нужен ли мне GridBagLayout, или я ищу другой.

Ниже приведен код NewAlbum.

Я прошу прощения за некомпилируемый код.Я подумал, что вы сможете просто посмотреть на класс и сказать мне: «О, да, это проблема».Ниже компилируется и демонстрирует проблему.После выбора файлов окно разделенной панели становится слишком тонким и слишком длинным.Я хочу, чтобы он вписался в рамку.На самом деле, он должен уместиться внутри JPanel, который находится внутри JFrame.

Спасибо, Энди

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

class Main extends JFrame {
   static JPanel transientPanel = null;

   public Main() {
      super();
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(640, 480);
      JMenuBar menuBar = new JMenuBar();
      JMenu menu = new JMenu("Example");
      JMenuItem albumMenu = new JMenuItem("New Album");
      albumMenu.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            transientPanel = new NewAlbum();
            add(transientPanel);
            validate();
            repaint();
         }
      });
      menu.add(albumMenu);
      menuBar.add(menu);

      setJMenuBar(menuBar);
      validate();
   }

   public static void main(String[] args) {
      final Main m = new Main();
      m.setVisible(true);
   }
}
/**
 * @description NewAlbum is the window that is presented to the user
 * to select new photographs for the album.  Once selected, the user
 * will be presented a form, of sorts, to complete the metadata for this
 * album.
 * @author Andy
 */
class NewAlbum extends JPanel {
    JButton selectFiles;
    JButton done;
    JButton nextButton = new JButton("Next Image");

    ArrayList<File> filesArray;

    JSplitPane splitWindow = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
    JScrollPane scrollWindow;
    JPanel rightSidePanel = new JPanel();
    JPanel leftSidePanel = new JPanel();

    JLabel subjectLabel = new JLabel("Image subject:");
    JLabel locationLabel = new JLabel("Image location:");
    JLabel commentLabel = new JLabel("Comments:");
    JLabel dateLabel = new JLabel("Date (mm/dd/yyyy):");

    JTextField subjectText = new JTextField(25);
    JTextField locationText = new JTextField(25);
    JTextArea commentText = new JTextArea(4, 25);
    JTextField dateText = new JTextField(10);

    public NewAlbum() {
        super();

        selectFiles = new JButton("Select Photos");

        selectFiles.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                selectFilesForAlbum();
            }
        });
        add(selectFiles);
    }

    private void configureRightPanel() {
        int jPanelX = getParent().getWidth();
        int jPanelY = getParent().getHeight() - 30; // this should account for buttons

        // now, resize this panel so that it will be the right size for the split pane
        jPanelX = jPanelX - (int)(jPanelX * .31);
        rightSidePanel.setSize(jPanelX, jPanelY);

        rightSidePanel.add(subjectLabel);
        rightSidePanel.add(subjectText);
        rightSidePanel.add(locationLabel);
        rightSidePanel.add(locationText);
        rightSidePanel.add(commentLabel);
        rightSidePanel.add(commentText);
        rightSidePanel.add(dateLabel);
        rightSidePanel.add(dateText);
        rightSidePanel.add(nextButton);

        // iterate over the photos selected, make bogus info for now
    }

    private ArrayList<File> makeFileIntoArrayList(File[] f) {
        ArrayList<File> a = new ArrayList<File>();
        a.addAll(Arrays.asList(f));

        return filesArray = a;
    }

    /**
     * selectFilesForAlbum
     * This method is private to the NewAlbum class.  It is the handler for
     * when the user clicks on the "select photos" button.  When the function
     * executes, it displays the JFileChooser so that the user may select
     * the desired photos.  The files selected are assigned to a class variable
     * of type File[] which is used by the enterPhotoInfo method.
     *
     * @return void
     */
    private void selectFilesForAlbum() {
        JFileChooser jfc = new JFileChooser();
        jfc.setMultiSelectionEnabled(true);
        jfc.showOpenDialog(this);
        makeFileIntoArrayList(jfc.getSelectedFiles());

        changeButtonToDone();
        enterPhotoInfo();

        // TODO write the photo album to the disk
    }

    private void changeButtonToDone() {
        remove(selectFiles);
        done = new JButton("Done");
        add(done);

        // by the time this gets called, we'll have a parent container
        getParent().validate();
        getParent().repaint();
    }

    private void enterPhotoInfo() {
        splitWindow.setSize(this.getWidth(), this.getHeight() - 30);

        // remove when the left side panel actually has something
        Dimension iewDims = splitWindow.getSize();
        int leftX = iewDims.width - (int)(iewDims.width * .69);
        int leftY = iewDims.height;

        leftSidePanel.setSize(leftX, leftY);

        configureRightPanel();

        scrollWindow = new JScrollPane(rightSidePanel);
        scrollWindow.setSize(rightSidePanel.getSize());

        splitWindow.setRightComponent(scrollWindow);
        splitWindow.setLeftComponent(leftSidePanel);
        splitWindow.setDividerLocation(.31);

        System.out.println("Printing dimensions of before validate/repaint: this, splitWindow, scrollWindow, LSP, RSP");
        debugPrintDimensions(this);
        debugPrintDimensions(splitWindow);
        debugPrintDimensions(scrollWindow);
        debugPrintDimensions(leftSidePanel);
        debugPrintDimensions(rightSidePanel);

        //infoEntryWindow.add(infoScroller);
        this.add(splitWindow);
        this.validate();
        this.repaint();

        System.out.println("Printing dimensions of: this, splitWindow, scrollWindow, LSP, RSP");
        debugPrintDimensions(this);
        debugPrintDimensions(splitWindow);
        debugPrintDimensions(scrollWindow);
        debugPrintDimensions(leftSidePanel);
        debugPrintDimensions(rightSidePanel);
    }

    private void debugPrintDimensions(Container c) {
        System.out.println("DEBUG: Containers (x,y): (" +
                String.valueOf(c.getWidth()) +
                "," +
                String.valueOf(c.getHeight()) +
                ")");
    }
}

Ответы [ 2 ]

2 голосов
/ 04 апреля 2011

Кроме того, скажите, является ли GridBagLayout тем, что я хочу, или я ищу другое.

Вы используете соответствующий менеджер компоновки для работы.Это также может означать использование разных менеджеров компоновки на разных панелях.

splitWindow.setSize(this.getWidth(), this.getHeight() - 30); 

Вы НИКОГДА не должны использовать setSize ().Это задача менеджера макета, определить размер компонента на основе правил менеджера макета.

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

2 голосов
/ 04 апреля 2011

Выбрав LayoutManager , вы передаете управление макетом этому менеджеру макета. Вы можете дать подсказки LayoutManager через ограничения и ограничения макета, задав предпочтительные размеры для компонентов, которые вы организуете, но, по сути, диспетчер макета вызовет снимки.

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

Раньше я использовал GridBagLayoutManager для всего, но потом я наткнулся на MigLayout , который действительно является огромным шагом вперед с точки зрения простоты конфигурации и согласованности макета. Я рекомендую вам посмотреть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...