2014-10-26 1 views
1

Я очень рад этому парню. Я пытаюсь создать пользовательский светодиодный дисплей, чтобы показать 7 баров, расположенных как 8. Я получил единый пользовательский JComponent (bar), чтобы показать его внутри JFrame, но я не могу заставить бары отображать внутри настраиваемой панели, что я Создание. Вот код для методов конструктора и методов рисования в моих классах, а также основной метод, который я использую для тестирования этих классов.Получение пользовательского JPanel для показа пользовательских JComponents (Java Swing)

Обычай JComponent:

public class Bar extends JComponent 
{ 
    // instance variables - replace the example below with your own 
    private static boolean litUp = false; 
    private static boolean vertical = false; 
    private static boolean rotated = false; 
    private static boolean rotClockwise = false; 
    private static int positionX; 
    private static int positionY; 



    public Bar(boolean lit, boolean vert, int posX, int posY) 
    { 
     litUp = lit; 
     vertical = vert; 
     positionX = posX; 
     positionY = posY; 
     repaint(); 
     System.out.println("The bar is being initialized"); 
    } 
    public void paintComponent(Graphics g) 
    { 
     System.out.println("BAR: Paint Component being called"); 

     super.paintComponent(g); 
     Graphics2D g2D = (Graphics2D)g; 

     if(vertical == true) 
     { 
      if(litUp == true) 
      { 
       g2D.setColor(Color.red); 
      } 
      else 
      { 
       g2D.setColor(Color.black); 
      } 

      g2D.drawRect(positionX , positionY, 10, 30); 
      g2D.fillRect(positionX , positionY, 10, 30); 
      System.out.println("BAR: fillRect is being called for a vertical bar"); 
      if(rotated == true) 
      { 
       if(rotClockwise == true) 
       { 
        g2D.rotate(0.3398); 
       } 
       else 
       { 
        g2D.rotate(-0.3398); 
       } 
      } 

     } 

     else{ 

      System.out.println("BAR: fillRect is being called for a horizontal bar"); 
      if(litUp == true) 
      { 
       g2D.setColor(Color.red); 
      } 
      else 
      { 
       g2D.setColor(Color.black); 
      } 
      g2D.drawRect(positionX,positionY, 30, 10); 
      g2D.fillRect(positionX,positionY, 30, 10); 
     } 


    } 
} 

Обычай JPanel:

public class LED extends JPanel 
{ 
    // instance variables - replace the example below with your own 
    //private static Bar[] bars = new Bar[7]; 
    //private static int xPos; 
    //private static int yPos; 

    private Bar barZero; 
    private Bar barOne; 
    private Bar barTwo; 
    private Bar barThree; 
    private Bar barFour; 
    private Bar barFive; 
    private Bar barSix; 




    /** 
    * Constructor for objects of class LED 
    */ 
    public LED() 
    { 
     barZero = new Bar(false, false, 0, 0); 
     this.add(barZero); 
     // barZero.setDirection(false); 
     barOne = new Bar(false, true, 0, 11); 
     this.add(barOne); 
     //barOne.setDirection(true); 
     barTwo = new Bar(false, true, 20, 11); 
     this.add(barTwo); 
     //barTwo.setDirection(true); 
     barThree = new Bar(false, false, 0, 42); 
     this.add(barThree); 
     //barThree.setDirection(false); 
     barFour = new Bar(false, true, 0, 53); 
     this.add(barFour); 
     //barFour.setDirection(true); 
     barFive = new Bar(false, true, 20, 53); 
     this.add(barFive); 
     //barFive.setDirection(true); 
     barSix = new Bar(false, false, 0, 64); 
     this.add(barSix); 
     //barSix.setDirection(false); 



     System.out.println("The LED class is being accessed"); 

     repaint(); 
    } 

@ Override public void paintComponent(Graphics g) 
    { 
     System.out.println("LED: PaintComponent being called"); 
     //barOne.paintComponent(g); 
     System.out.println("LED: barZero being painted| " + barZero.orientation() + "| " + barZero.coordX()); 

     System.out.println("LED: barOne being painted| " + barOne.orientation() + "| " + barOne.coordX()); 
     //barTwo.paintComponent(g); 
     System.out.println("LED: barTwo being painted| " + barTwo.orientation() + "| " + barTwo.coordX()); 

     //barThree.paintComponent(g); 
     System.out.println("LED: barThree being painted| " + barThree.orientation() + "| " + barThree.coordX()); 
     //barFour.paintComponent(g); 
     System.out.println("LED: barFour being painted| " + barFour.orientation() + "| " + barFour.coordX()); 
     //barFive.paintComponent(g); 
     System.out.println("LED: barFive being painted| " + barFive.orientation() + "| " + barFive.coordX()); 
     //barSix.paintComponent(g); 
     System.out.println("LED: barSix being painted| " + barSix.orientation() + "| " + barSix.coordX()); 


     super.paintComponent(g); 
    } 
} 

и метод Tester:

public class DrawRect { 
    public static void main(String[] a) { 
    JFrame window = new JFrame(); 
    LED led = new LED() 
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    window.setBounds(30, 30, 300, 300); 
    window.getContentPane().add(led); 
    window.setVisible(true); 
    } 
} 

я могу инициализировать панель и отобразить его в Рамка, но я не могу заставить светодиод (панель) показывать в нем полосы. Кроме того, вот строки, которые распечатываются после тестирования компонента. Ни один из баров, которые я добавляю, имеет свои значения: они все горизонтальны, и все они имеют свои позиции x, равные 0. Я не из тех, кто сдался, но эта программа заставляет меня хотеть изменить мой майор.

+0

Для получения более подробной помощи отправьте сообщение [MCVE] (http://stackoverflow.com/help/mcve) (минимальный полный проверяемый пример). Это означает, что один исходный файл (возможно, с несколькими файлами класса внутри) с импортом, в отличие от трех. –

+2

Пользовательский компонент должен переопределять 'getPreferredSize()', чтобы предоставить менеджеру макета подсказки относительно размера. –

+1

Несвязанная проблема, но ваш класс Bar имеет несколько неуместных применений статического модификатора. Большинство этих полей должны быть полями экземпляра, а не статическими полями. –

ответ

3

Есть несколько вопросов, которые вы должны рассмотреть здесь:

  1. Каждый Bar объект нуждается в своих собственных переменных, чтобы следить за его состоянием. Это означает, что переменные-члены в Bar должны быть не статическими.

  2. Пользовательский компонент должен переопределить getPreferredSize(), чтобы указать его родительскому контейнеру, сколько места занимает пользовательский компонент.

  3. Материнская тара отвечает за определение положения компонентов, которые она содержит. (Более того, это ответственность LayoutManager.) Это означает, что неуместно иметь позиции x и y в пользовательском компоненте.

  4. В paintComponent(Graphics g) вам разрешено рисовать только в пределах области, принадлежащей компоненту. Координаты относительно верхнего левого угла компонента, не относительно левого верхнего угла контейнера, который его удерживает. Это означает, что вам нужно, чтобы нарисовать прямоугольник, покрывающий весь компонент:

    g.drawRectangle(0, 0, getWidth(), getHeight()); 
    
  5. Вы можете уменьшить некоторые сложности кода с помощью массива или List для хранения Bar объектов внутри пользовательской панели. Например, вы сможете рисовать каждый Bar в простой петле.

3

Итак, вы довольно близко. Я думаю, что самое лучшее, что вы можете сделать, это уменьшить сложность даже больше, чем использовать ArrayList, и просто использовать компонент, который уже существует. Вот более простой пример использования HorizontalBox.

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

Также не забывайте о целом многопоточном веществе. В разделе «Диспетчер событий», пожалуйста. У меня есть пара макросов в моей среде IDE, которая в основном создает код для EDT примерно через две секунды. Никаких оправданий.

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import javax.swing.Box; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 

public class LedBar extends JComponent 
{ 
    private final Dimension SIZE = new Dimension(20, 50); 
    private float value = 50f; // range 0-100 

    public void setValue(float value) 
    { 
     this.value = value; 
    } 

    public float getValue() 
    { 
     return value; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.setColor(Color.RED); 
     g.drawRect(0, 0, SIZE.width, SIZE.height); 
     g.setColor(Color.RED.darker()); 
     final int top = (int)(SIZE.height*(100f-value)/100f+1); 
     final int bottom = (int)(SIZE.height*(value)/100f-1); 
     g.fillRect(1, top, SIZE.width-1, bottom); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return SIZE; 
    } 
} 

class Test 
{ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      JFrame frame = new JFrame(); 

      Box hbox = Box.createHorizontalBox(); 
      for (int i = 0; i < 5; i++) { 
       LedBar led = new LedBar(); 
       led.setValue(i * 20f); 
       hbox.add(led); 
      } 
      frame.add(hbox); 

      frame.pack(); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setLocationRelativeTo(null); 
      frame.setVisible(true); 
     } 
     }); 
    } 
} 
+0

'class Test {public static void main (String [] args) {..' Huh. Это первый раз, когда я вспоминаю, что я видел неклассический класс с 'main (String [])', вставленным в конец источника другого класса 'public'. Почему бы не скопировать/вставить основной в открытый класс и вообще отказаться от класса 'test'? –

+0

Хорошо, потому что тогда основной метод будет частью класса LedBar. Как и в случае, класс Test является отдельным и никогда не добавляет байты в файл класса LedBar. (Моя IDE найдет любой класс с основным методом в исходном файле и запустит его, поэтому это всего лишь удобный способ сделать два класса - один класс и один тестовый класс - в одном исходном файле.) – markspace

+0

@markspace Я определенно все еще сталкиваюсь с некоторыми проблемами многопоточности. У меня есть заявление печати в методе paintComponent класса Bar. Класс тестера написан позже, и я делаю один бар и добавляю его к фрейму, но я все еще получаю несколько операторов печати для одного бара. Что я делаю не так? – llamaCaraDara