2015-07-30 2 views
4

У меня проблема с Java Swing и JPanel. Я могу сказать, что я - неопытный программист на Java, но не совсем новый для программирования.Должны ли все графические объекты наследовать от JPanel?

Моя проблема заключается в том, что у меня есть класс с именем RandomParticle,

public class RandomParticle extends Ellipse2D.Double { 

    private Ellipse2D.Double circle; 

    public RandomParticle(double xPos , double yPos,double rad) { 
     setCircle(new Ellipse2D.Double(xPos, yPos, rad, rad)); 
    } 

    public Ellipse2D.Double getCircle() { 
     return circle; 
    } 

    public void setCircle(Ellipse2D.Double circle) { 
     this.circle = circle; 
    } 
} 

, который я хочу, чтобы перейти на экран (в JFrame, конечно). Частица - это объект по умолчанию, чтобы просто поднять графику. Однако во многих местах говорят, например, here, что для того, чтобы рисовать круг, он должен переопределить метод paintComponent в JPanel. Это действительно разумно, что, чтобы нарисовать что-то в JFrame, это должно быть JPanel. Однако это может вызвать проблемы, поскольку Java не поддерживает множественное наследование.

В этом случае я не нуждаюсь в RandomParticle, чтобы быть дочерним элементом ellipse2D, но по мере того, как мои классы становятся более сложными, в какой-то момент мне, скорее всего, понадобится присущий другому классу. Тем не менее, я чувствовал, что этот уровень вопроса имеет хороший уровень для SO, поскольку он не требует каких-либо конкретных знаний о моей программе. Так что я задаюсь вопросом: Можно ли нарисовать круг без того, чтобы класс был ребенком для JPanel?

+1

Ответ MadProgrammer объясняет Swing довольно хорошо, но ответ на ваш вопрос: «Можно ли рисовать круг без класса, являющегося ребенком в JPanel? " Да. Создайте класс модели Circle и создайте Swing DrawingPanel из JPanel, чтобы нарисовать класс модели Circle в методе paintComponent. Вы можете создать несколько классов моделей и нарисовать их в том порядке, в котором вы хотите, на панели рисования. –

ответ

8

Можно ли нарисовать круг без класса, являющегося ребенком для JPanel?

Вид, но это связано с проблемами. Я попытаюсь объяснить

Если вы хотите, чтобы выполнить собственную картину в свинг, вы должны переопределить метод paintComponent любого компонента, который простирается от JComponent, JPanel обычно быть самым простым решением, это как картина работает

Посмотрите на Painting in AWT and Swing и Performing Custom Painting для получения более подробной информации о том, как работает живопись.

Вообще говоря, это нецелесообразно пытаться рисовать непосредственно в верхний контейнер уровня, как JFrame, поскольку он содержит ряд других компонентов детей, которые нарисованы на вершине его (JRootPane, contentPane, glassPane, menuBar, и т.д.), которые могли бы окрашиваться независимо от рамы, вызывают некоторые странные артефакты.

Более подробное представление, что такое JFrame на самом деле выглядит ...

RootPane

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

сам свинг использует пассивный движок рендеринга, это означает, что вы на самом деле не контролировать процесс рисования, вы просто уведомление, когда ваш компонент должен быть окрашен (с помощью метода paintComponent). Swing может выбрать окраску дочерних компонентов, не требуя уведомления родительского контейнера, что является одной из причин, почему обычно рекомендуется paintComponent. Он также может объединять несколько запросов краски как можно меньше вызовов, чтобы оптимизировать процесс.

Все это делается без вашего ведома или контроля.

Если вам требуется больше контроля над процессом обработки краски, вы можете рассмотреть возможность использования BufferStrategy, который дает вам прямое (двойное буферизированное) управление процессом рисования, поэтому вы можете решить, когда и что должно быть окрашено. Но даже это потребует от вас использовать java.awt.Canvas в качестве базы, с помощью которой можно создать свой вывод.

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

+0

Хорошо, теперь я понимаю, почему полезно использовать «JPanel». Итак, что вы имеете в виду, тогда я должен попытаться отключить другие классы от его графической реализации? Например, если у всех классов есть поле 'JPanel', которое можно нарисовать? – patrik

+2

Трудно знать, основываясь на вашем примере кода, но было бы более вероятно, что у вас будет одна «JPanel»/поверхность, на которую будут нарисованы все остальные элементы (они не должны знать о самой панели). FYI 'Graphics2D' (экземпляр которого передается' paintComponent') может рисовать 'Ellipse2D', используя' Graphics2D # draw' или 'Graphics2D # fill'. Прямо сейчас, все «RandomParticle» представляет собой концепцию формы, она не может отображать себя. Взгляните на [2D-графика] (https://docs.oracle.com/javase/tutorial/2d/) – MadProgrammer

+0

Спасибо, это было поучительно. Я имею в виду, что мне может понадобиться класс 'public MyClass extends ComplicatedAndLongClass {...'. Представление может быть, например, желтым. Однако в отношении вашего комментария и некоторых распространенных я подозреваю, что это не тривиально, и мне нужно выяснить, как наилучшим образом подойти к дизайну моей программы. Спасибо за хороший и поучительный ответ. Теперь я знаю гораздо больше о некоторых компонентах swing, и ссылки были полезны. – patrik

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