2011-01-02 3 views
0

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

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 объект как один будет предоставлена ​​платформой.
Что происходит после этого, я не могу понять.
E.g. Graphics представляет экран, и объект окрашивается соответствующим образом на экране, как только я начинаю называть различные методы g.setXXX?
Сохраняется ли она в очереди и существует ассоциация 1-1 между g и каждый component? Итак, структура использует каждый из g каждого компонента для рисования по одному за раз?
Как это работает? Любая помощь по этому вопросу весьма приветствуется

Благодаря

ответ

1

Компонент не создает ассоциацию статических объектов Graphics.

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

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

EDIT

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

+0

Итак, когда вызов 'paintComponent' в конечном итоге вызывается, когда вызываются различные методы объекта« Graphics », они выполняются непосредственно на экране? – Cratylus

+0

Они выполняются на устройстве позади (см. Component.print, вызывающая краска, которая должна использовать устройство принтера). Это более или менее отображает непосредственно на графических примитивах платформы. – mtraut

+0

Еще точнее: это может быть автономное устройство (битмап-дескриптор) тоже - как в случае двойной буферизации. – mtraut

2

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

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

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

paint(Graphics g); 

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

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

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

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

Общая документация для графики Java оставляет желать лучшего. Существует много концепций, которые непрозрачны (см. How does Java Graphics.drawImage() work and what is the role of ImageObserver). Ранняя реализация была опрокинута и имела множество ошибок. Даже сейчас часто неясно, следует ли и в каком порядке вы должны называть такие методы, как setPack() и setVisible().

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

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

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

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

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

+0

@ peter.murray.rust: Когда вы говорите «уведомление», вы имеете в виду объяснение того, что такое Graphics на самом деле? Да, часть об переопределении «краски» я получаю. Я просто не понимаю, что такое отношение 'g' передано как аргумент с объектом, который переопределяет краску, и как именно' g' выполняет свою работу – Cratylus

+0

@ user384706 нет, я имею в виду, что он создает один, не указывая явно, что он это сделал или требуя от вас любого ввода. –

+0

@ peter.murray.rust: Я понимаю, что 'g' уже настроен для использования. G' представляет экран? Это новый 'g' передается каждому компоненту? Также в отношении размера в сообщении я использую 'getWidth' и' getHeight', унаследованные от JComponent. Почему существует размер? JComponent имеет некоторый размер по умолчанию? – Cratylus

1

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

+0

@ Дональные стипендиаты: если структура использует «Графика», чтобы показать, что я нарисовал для отображения компонента, как вам посоветовали в книгах: создать временный объект Graphics через «Graphics2D g2d = (Graphics2D) g.create(); 'внутри метода paintComponent' и использовать temp g2d для всех графических операций и в конце метода' paintComponent' вызывать 'g2d.dispose()'? Инструментарий Framework никогда не получит операции I установленный в 'g2d' (он был удален), если только то, что я делаю на' g2d', прямо на экране. Эта часть является головной болью для меня – Cratylus

+0

Эта внутренняя 'Графика' делегирует соответствующие части тому, кто ее создал, и это то, где аналогия немного ломается. Это не кусок бумаги, а абстрактная поверхность с областью клипа, применяемая к ней, и которая, возможно, не будет экраном из-за двойной буферизации, и тот, который вы получили, вполне может оказаться не самой лучшей графикой '. Спасите себя, не пытаясь понять это чрезмерно. :-) Что вы * знаете, так это то, что вы используете свои методы для рисования компонента, и вы не держите его вокруг. Вам нужно знать больше? –

+0

Если вам нужно знать больше, вы собираетесь стать пользователем инструментария, чтобы быть разработчиком инструментария. ** Набор инструментов **. В самом деле. Существует огромное количество ограничений, некоторые из которых действительно уродливы. Это также неудобно, так как вы довольно быстро перестаете работать с независимой от платформы абстракцией. –

2

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

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

Смежные вопросы