Java 2D и свинг - PullRequest
       44

Java 2D и свинг

0 голосов
/ 02 января 2011

У меня проблемы с пониманием фундаментальной концепции в Java 2D.
Чтобы привести конкретный пример:
Можно настроить компонент Swing, реализовав собственную версию метода paintComponent(Graphics g)
Графика доступна для тела метода.
Вопрос:
Что именно это графический объект, я имею в виду, как он связан с объектом, который имеет метод paintComponent? Хорошо, я понимаю, что вы можете сделать что-то вроде:

g.setColor(Color.GRAY);
g.fillOval(0, 0, getWidth(), getHeight());

Чтобы получить серый овал Что я не могу понять, так это как объект Graphics связан с компонентом и холстом. Как на самом деле делается этот рисунок?
Другой пример:

public class MyComponent extends JComponent {

     protected void paintComponent(Graphics g) {

                System.out.println("Width:"+getWidth()+", Height:"+getHeight());

            }

    public static void main(String args[]) {

                JFrame f = new JFrame("Some frame");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(200, 90);
                MyComponent  component = new MyComponent  ();
                f.add(component);
                f.setVisible(true);       
          }
 }

Это печатает

Ширина: 184, Высота: 52

Что означает этот размер? Я ничего не добавил в кадр размера (200,90).

UPDATE:
Я понимаю, что должен переопределить краску, чтобы дать объекту Graphics g подсказки, необходимые для перерисовки, и что мне не нужно создавать объект Graphics, поскольку он будет предоставлен платформой.
То, что происходит после этого, я не могу понять.
Например. Graphics представляет экран, и объект соответственно отображается на экране, как только я начинаю вызывать различные g.setXXX методы?
Сохраняется ли он в очереди и существует ли связь 1-1 среди g и каждого component? Таким образом, фреймворк использует каждый g каждого компонента для рисования по одному за раз?
Как это работает? Любая помощь в этом очень приветствуется

Спасибо

Ответы [ 4 ]

2 голосов
/ 02 января 2011

Что означает этот размер? Я ничего не добавил в кадр размера (200,90).

Вы добавили компонент в рамку и установили размер рамки (200, 90). Диспетчером макета по умолчанию для панели содержимого фрейма является BorderLayout, что означает, что добавленный компонент получает все доступное пространство. Для фрейма требуется некоторое пространство для строки заголовка и границ, поэтому ваш компонент получает оставшееся пространство.

2 голосов
/ 02 января 2011

Я понимаю вашу проблему, так как я боролся с ней некоторое время, когда изучал графику Java.Это не просто Java 2D-графика - это часть AWT.

Когда вы создаете JFrame или какой-либо другой объект верхнего уровня, он выполняет большую работу "за кулисами" - частью которой является созданиеГрафический объект.(Нет явного уведомления об этом, хотя если вы пошагово прошли через код с помощью отладчика, вы можете увидеть классы, которые создают Graphics).

Затем вы создаете компоненты, которые добавляете или регистрируете в верхнемУровень объекта.Все они должны реализовывать метод обратного вызова, включая

paint(Graphics g);

. Затем вы переопределяете эти методы @Override, чтобы при визуализации компонента использовать ВАШ метод рисования.

Не пытайтесь сохранить рисунок или создать новый.Думайте об этом как о структуре, которая снимает с вас ответственность.

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

Если вы исходите из процедурного императивного фона, у вас вполне могут быть проблемы (я из FORTRAN).Я бы посоветовал попробовать несколько учебных пособий, и на каком-то этапе просветление начнет наступать.

Общая документация по Java-графике плохая.Существует множество непрозрачных концепций (см. Как работает Java Graphics.drawImage () и какова роль ImageObserver ).Ранняя реализация была поспешной и имела много ошибок.Даже сейчас часто неясно, следует ли и в каком порядке вызывать такие методы, как setPack() и setVisible().

Это не означает, что вы не должны его использовать!Просто кривая обучения немного длиннее, чем у IMO.

БОЛЬШЕ: Кроме того, ВЫ не решаете, когда что-то нарисовано, делает каркас.paint(g) действительно означает «framweork перерисовывает свои компоненты. Что вы хотите, чтобы этот компонент предоставил на данном этапе».

Возможно, providePaintingInstructionsWhenRequiredForComponentGraphics(Graphics g) будет полезным именем.

Аналогично repaint() не перекрашивает по вашим заказам, но когда система считает, что это необходимо.Я не нашел это полезным.

Если вы, скажем, изменяете размер компонента в интерактивном режиме, каждое небольшое изменение обычно вызывает paint(g).попробуйте поместить LOG.debug () в код рисования и посмотреть, когда он вызывается.

1 голос
/ 02 января 2011

Представьте себе Graphics как лист бумаги, на котором вы рисуете, чтобы показать, как Component выглядит в этот момент .После того, как вы нарисовали его, инструментарий фреймворка обрежет края и покажет, что вы нарисовали для отображения компонента.Более того, в следующий раз, когда вы нарисуете компонент, вы будете рисовать на другом листе бумаги, так что не оставляйте старый Graphics вокруг.

1 голос
/ 02 января 2011

Компонент не создает статическую ассоциацию графического объекта.

Графический объект - это оболочка для дескриптора платформы, предоставляющая доступ к физическому устройству, например к экрану. Это действительно для времени, когда выполняется «рисование», вы не можете сохранить его и использовать позже. Это ресурс, управляемый "инструментарием".

Сам компонент является абстракцией поверх оконной системы, которая вскоре связывается с этим устройством для рендеринга.

EDIT

Вы можете вызвать такую ​​ассоциацию, называемую «getGraphics», если чувствуете необходимость вычеркнуть обратный вызов «paint». Это должно быть очень редким случаем, и вы ВСЕГДА должны распоряжаться графикой впоследствии.

...