2016-05-11 2 views
0

Я пытаюсь понять, как Swings JButton/AbstractButton реализует роспись своих значков (defaultIcon, disabledIcon, pressIcon и т. Д.).Как JButton реализует свои значки?

Я нашел поля/геттеры/сеттеры для указанных значков в AbstractButton, но, судя по всему, различные методы рисования наследуются непосредственно от JComponent. Это вызывает вопрос о том, как иконы когда-либо нарисованы !? Очевидно, что они есть, но я не смог найти код, который это делает.

ответ

0

Надеюсь, я понимаю ваш вопрос: вы пытаетесь понять, как нарисовать иконку на JButton? Взгляните на метод рисования от JComponent (его супер супер класс). Я буду добавлять комментарии, чтобы сделать его проще объяснить:

public void paint(Graphics g) { 
    boolean shouldClearPaintFlags = false; 

    //Check the size of the component: don't draw anything with a negative width or height! 
    if ((getWidth() <= 0) || (getHeight() <= 0)) { 
     return; 
    } 

    //Create new Graphics objects (why? to create the images) 
    Graphics componentGraphics = getComponentGraphics(g); 
    Graphics co = componentGraphics.create(); 

    try { 
     RepaintManager repaintManager = RepaintManager.currentManager(this); 
     //Initialize a RepaintManager (JavaDoc says: "This class manages repaint requests, allowing the number of repaints to be minimized") 
     //Create a rectangle at the size of a graphics object 
     Rectangle clipRect = co.getClipBounds(); 
     int clipX; 
     int clipY; 
     int clipW; 
     int clipH; 

     //If the rectangle is null, then give it default values 
     if (clipRect == null) { 
      clipX = clipY = 0; 
      clipW = getWidth(); 
      clipH = getHeight(); 
     } else { //otherwise, use its coordinates 
      clipX = clipRect.x; 
      clipY = clipRect.y; 
      clipW = clipRect.width; 
      clipH = clipRect.height; 
     } 

     //Ajust the clip widths and heights 
     if(clipW > getWidth()) { 
      clipW = getWidth(); 
     } 
     if(clipH > getHeight()) { 
      clipH = getHeight(); 
     } 
     //If your Component is placed on a JComponent (or extended class), then make adjustments 
     if(getParent() != null && !(getParent() instanceof JComponent)) { 
      adjustPaintFlags(); 
      shouldClearPaintFlags = true; 
     } 

     //Check if the component is printing (private flag IS_PRINTING) 
     int bw,bh; 
     boolean printing = getFlag(IS_PRINTING); 

     //If the component is not printing its contents, and if the repain manager is double buffered, AND if not ancestor (subclass) is buffering AND if the components is buffered.... 
     //JavaDoc says for RepaintManager.isDoubleBufferingEnabled(): "Returns true if this RepaintManager is double buffered. The default value for this property may vary from platform to platform." 
     if(!printing && repaintManager.isDoubleBufferingEnabled() && 
      !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) { 
      //... then start painting the Graphics 
      repaintManager.beginPaint(); 
      try { 
       repaintManager.paint(this, this, co, clipX, clipY, clipW, clipH); 
      } finally { 
       repaintManager.endPaint(); 
      } 
      //if there is an exception, a try/finally is required to avoid the RepaintManager being "left in a state in which the screen is not updated" (JavaDoc) 
     } 
     else { 
      // Will ocassionaly happen in 1.2, especially when printing. 
      if (clipRect == null) { 
       co.setClip(clipX, clipY, clipW, clipH); 
      } 

      //Checks if the rectangle at the specified coordinates if obscured 
      if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) { 
       //Then paint the graphics (or print if printing is true) 
       if (!printing) { 
        paintComponent(co); 
        paintBorder(co); 
       } else { 
        printComponent(co); 
        printBorder(co); 
       } 
      } 

      //Also paint the children (eg: a JPanel has a JLabel and a JButton as children if you add them to the panel) (or print if printing is true) 
      if (!printing) { 
       paintChildren(co); 
      } else { 
       printChildren(co); 
      } 
     } 
    } finally { 
     //Clean up!! 
     co.dispose(); 
     if(shouldClearPaintFlags) { 
      setFlag(ANCESTOR_USING_BUFFER,false); 
      setFlag(IS_PAINTING_TILE,false); 
      setFlag(IS_PRINTING,false); 
      setFlag(IS_PRINTING_ALL,false); 
     } 
    } 
} 

Других слова, есть много кода, участвующих в живописи Graphics объектов, но шаги довольно просты, как только вы проанализировали код:

  • Создать новый Graphics объект с переданного в параметре;
  • Инициализировать RepaintManager для запросов на перерисовку;
  • Проверьте, можно ли покрасить графику и по возможности сделать это;
  • Завершить, перекрасив детей;
  • Все готово!

Если вы хотите узнать больше о том, как применяется процесс покраски, а затем в соответствии с Oracle's Java documentation:

  • В Swing, картина начинается с методом краски, который затем вызывает paintComponent, paintBorder и paintChildren. Система будет ссылаться на это автоматически, когда компонент будет сначала окрашен, изменен или будет открыт после того, как будет скрыто другим окном.

  • Программные перекраски выполняются путем вызова метода перекраски компонента; не вызывайте его paintComponent напрямую. Вызов repaint заставляет подсистему рисования предпринять необходимые шаги для обеспечения того, чтобы ваш метод paintComponent был вызван в соответствующее время.

  • Вы можете вызвать repaint несколько раз из одного и того же обработчика событий, но Swing примет эту информацию и перекрасит компонент всего за одну операцию.

  • Для компонентов с делегатом пользовательского интерфейса вы должны передать графический параметр с строкой super.paintComponent (g) в качестве первой строки кода в вашем переопределении paintComponent. Если вы этого не сделаете, ваш компонент будет нести ответственность за ручную окраску фона. Вы можете поэкспериментировать с этим, комментируя эту строку и перекомпилируя, чтобы увидеть, что фон больше не раскрашен.

Я принял код от here. Я надеюсь, что я был в состоянии помочь вам,

Приветствия

+0

Спасибо за ваши комментарии в коде. Это идет в сторону моего вопроса, но все же: как суперкласс (JComponent) знает, какие значки имеет подкласс (JButton), а какой из них должен быть окрашен в этот момент (т. Е. При наведении и т. Д.), ? – PeterE

+0

Я предполагаю, что когда суперкласс добавляет подкласс (например, jpanel.add (jbutton);), он проверяет графику подкласса и сохраняет его в памяти. Ссылка http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/awt/Container.java#Container.addImpl%28java.awt.Component%2Cjava. lang.Object% 2Cint% 29 показывает, как это работает. Что касается того, когда он нарисован в нужный момент, я не уверен, мне придется заглянуть в него –

+0

Привет, извините за задержку, я просто добавил несколько пояснений относительно того, как работают краски (и другие производные). Текст, который я публикую, берется прямо из примера, пожалуйста, просмотрите ссылку, которую я предоставил для более подробной информации. Дайте мне знать, если это имеет смысл сейчас! –

3

рисования компонентов в Swing, производятся Look-n-Feel. Поэтому, если вы хотите найти, как нарисована пиктограмма кнопки, просто посмотрите метод paintIcon класса BasicButtonUI.Но каждый Look-n-Feel, который вы используете, может обеспечить различную картину.

3

Значок в JButton написан пользовательским интерфейсом. И класс UI определяется Look and Feel. Это реализация javax.swing.plaf.ButtonUI.

JComponent.paint метод получения щ свойство из экземпляра и вызовите его обновления метод (и где значок окрашен). Пользовательский интерфейс экземпляра приобретается UIManager

.

Вы можете зе метод рисования на Open JDK BasicButonUI

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