Почему getWidth() и getHeight() возвращают 0 до вызова paintComponent()?

Изменить: основная проблема решена. Я использовал SwingUtilities.invokeLater() для решения проблемы. Мой другой вопрос содержит дополнительную информацию для тех, кто заинтересован.

У меня есть графический интерфейс, который отображает изображение на JPanel в paintComponent() с g.drawImage(). Я написал подкласс JPanel под названием CanvasPanelView, чтобы переопределить paintComponent() и сделать несколько других вещей, например установить границы того, где рисуется изображение. Проблема в том, что мне нужно получить ширину и высоту JPanel, и когда я вызываю this.getWidth() и this.getHeight() в классе, расширяющем JPanel, они оба возвращают 0.

Процесс начинается во внутреннем классе прослушивателя действий:

class MenuBarFileOpenListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {
        File fileChooserReturnValue = view.showAndGetValueOfFileChooser();

        if (fileChooserReturnValue != null) {
            try {
                DocumentModel newDocument = new DocumentModel(ImageIO.read(fileChooserReturnValue), fileChooserReturnValue.getAbsolutePath(), fileChooserReturnValue.getName());
                model.addDocument(newDocument);
                view.addDocument(newDocument);
            } catch(IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

Затем вызывается addDocument():

public void addDocument(DocumentModel document) {
    menuBar_file_close.setEnabled(true);

    DocumentView newDocumentView = new DocumentView(document.getTitle(), documentsTabbedPaneCloseButtonListener);

    documentViews.add(newDocumentView); // add newDocumentView to ArrayList<DocumentView>
    newDocumentView.setDocument(document);
    documentsTabbedPane.add(newDocumentView.getCanvasPanelView());

    int newDocumentIndex = documentsTabbedPane.indexOfComponent(newDocumentView.getCanvasPanelView());

    documentsTabbedPane.setTabComponentAt(newDocumentIndex, newDocumentView.getTabPanel());
    documentsTabbedPane.setSelectedIndex(newDocumentIndex);
    newDocumentView.setBounds(document.getImageWidth(), document.getImageHeight());
}

public DocumentView(String title, ActionListener listener) {
    canvas = new CanvasPanelView();
    // more code...
}

setBounds() называется:

public void setBounds(int imageWidth, int imageHeight) {
    sourceX1 = 0;
    sourceY1 = 0;
    sourceX2 = imageWidth;
    sourceY2 = imageHeight;

    // some math...

    destinationX1 = 0 + xMargin;
    destinationY1 = 0 + yMargin;
    destinationX2 = drawWidth - xMargin;
    destinationY2 = drawHeight - yMargin;
}

DocumentView — это класс-оболочка для CanvasPanel и некоторых других вещей — он просто группирует вещи, которые идут с каждым открытым документом.

Кажется, что все создается и используется или добавляется к JTabbedPane, поэтому я не знаю, почему this.getWidth() и this.getHeight() возвращают 0. Может быть, что-то происходит между концом setBounds() и paintComponent().

Почему this.getWidth() и this.getHeight() возвращают 0?


person joshreesjones    schedule 11.05.2013    source источник
comment
getWith() возвращает 0, потому что компонент в это время имеет нулевой размер, но почему, я не уверен. Я не думаю, что вы задали вопрос, на который можно ответить, поскольку вы, возможно, упустили слишком много того, что было бы необходимо для понимания того, почему вы видите свою ошибку, а также оставили много кода, не связанного с проблемой. Если вы не получите хорошего ответа в ближайшее время, рассмотрите возможность создания и публикации sscce.   -  person Hovercraft Full Of Eels    schedule 11.05.2013
comment
Уместные вещи, которые следует упомянуть и показать с вашим sscce, включают макет контейнера, который содержит ваш компонент, отображающий изображение, и то, как вы добавляете компонент в контейнер.   -  person Hovercraft Full Of Eels    schedule 11.05.2013
comment
согласен, правильно, тогда ответ может быть простым   -  person mKorbel    schedule 11.05.2013
comment
Я должен предположить, что два ответа, которые вы получили, адекватно ответили на ваш вопрос. Удачи.   -  person Hovercraft Full Of Eels    schedule 11.05.2013
comment
В вашем sscce получите доступ к опубликованным изображениям через URL, как показано здесь или используйте синтетические изображения, как показано здесь.   -  person trashgod    schedule 11.05.2013


Ответы (2)


Почему бы вам не поместить свой documentView внутрь Panel(BorderLayout) вместо установки setBounds в такое положение, как BorderLayout.CENTER?

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

person rimero    schedule 11.05.2013

Вы написали класс, CanvasPanelView. Этот класс расширяет JPanel. Похоже, что в вашей реализации setBounds вы не ссылаетесь на элементы JPanel, на которые ссылаются getHeight() и getWidth(). Следовательно, базовый объект имеет 0 высоты и 0 ширины.

Если вы хотите использовать значения JPanel для высоты и ширины, вам просто нужно убедиться, что вы присваиваете им значения.

person christopher    schedule 11.05.2013