Pregunta

Estoy trabajando en un pequeño y simple componente swing, y me estoy deshaciendo de mi cabello tratando de averiguar por qué mi método paint no está funcionando.

La idea detrás de este componente es que es un pequeño JPanel con una etiqueta.El fondo (detrás de la etiqueta) se supone que es blanca, con un rectángulo de color en el lado izquierdo, que indica la relación de dos medidas:"real" y "espera".

Si usted tuviera un montón de estos componentes alineados verticalmente, que había forma de un gráfico de barras, compuesto de barras horizontales.

Este tipo de cosas debe ser super-simple.

De todos modos, aquí está el código:

package com.mycompany.view;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

import javax.swing.JLabel;
import javax.swing.JPanel;

public class BarGraphPanel extends JPanel {

   private static final Color BACKGROUND = Color.WHITE;
   private static final Color FOREGROUND = Color.BLACK;

   private static final Color BORDER_COLOR = new Color(229, 172, 0);
   private static final Color BAR_GRAPH_COLOR = new Color(255, 255, 165);

   private int actual = 0;
   private int expected = 1;

   private JLabel label;

   public BarGraphPanel() {
      super();
      label = new JLabel();
      label.setOpaque(false);
      label.setForeground(FOREGROUND);
      super.add(label);
      super.setOpaque(true);
   }

   public void setActualAndExpected(int actual, int expected) {
      this.actual = actual;
      this.expected = expected;
   }

   @Override
   public void paint(Graphics g) {

      double proportion = (expected == 0) ? 0 : ((double) actual) / expected;
      Rectangle bounds = super.getBounds();

      g.setColor(BACKGROUND);
      g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);

      g.setColor(BAR_GRAPH_COLOR);
      g.fillRect(bounds.x, bounds.y, (int) (bounds.width * proportion), bounds.height);

      g.setColor(BORDER_COLOR);
      g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);

      label.setText(String.format("%s of %s (%.1f%%)", actual, expected, proportion * 100));
      super.paint(g);
      g.dispose();
   }

}

Y aquí está la simple instrumento de prueba:

package com.mycompany.view;

import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.UIManager;

public class MyFrame extends JFrame {

   public MyFrame() {
      super();
      super.setLayout(new GridLayout(3, 1));
      super.setPreferredSize(new Dimension(300, 200));

      BarGraphPanel a = new BarGraphPanel();
      BarGraphPanel b = new BarGraphPanel();
      BarGraphPanel c = new BarGraphPanel();

      a.setActualAndExpected(75, 100);
      b.setActualAndExpected(85, 200);
      c.setActualAndExpected(20, 300);

      super.add(a);
      super.add(b);
      super.add(c);
   }

   public static void main(String[] args) {
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGUI();
         }
      });
   }

   public static void createAndShowGUI() {

      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      } catch (Throwable t) { }

      MyFrame frame = new MyFrame();
      frame.pack();
      frame.setVisible(true);
   }

}

El instrumento de prueba, crea un marco sencillo y, a continuación, agrega tres de estos controles.

Las etiquetas se generan correctamente, lo que me indica que el paint() método que realmente se llama, pero los rectángulos no están siendo atraídos a el objeto Graphics.

¿Qué estoy haciendo mal?

¿Y por qué el Swing de programación de chupar tanto?


Aquí está mi código final.Gracias a todos por su ayuda!

public void paintComponent(Graphics g) {

   double proportion = (expected == 0) ? 0 : ((double) actual) / expected;

   Rectangle bounds = super.getBounds();

   g.setColor(BACKGROUND);
   g.fillRect(0, 0, bounds.width, bounds.height);

   g.setColor(BAR_GRAPH_COLOR);
   g.fillRect(0, 0, (int) (bounds.width * proportion), bounds.height);

   g.setColor(BORDER_COLOR);
   g.drawRect(0, 0, bounds.width - 1, bounds.height - 1);

   FontMetrics metrics = g.getFontMetrics();
   String label = String.format("%s of %s (%.1f%%)", actual, expected, proportion * 100);
   Rectangle2D textBounds = metrics.getStringBounds(label, g);

   g.setColor(FOREGROUND);
   g.drawString(label, 5, (int) ((bounds.height + textBounds.getHeight()) / 2));
}
¿Fue útil?

Solución

Creo que casi he respondido a tu propia pregunta en los comentarios, junto con David de la respuesta.Cambio paint(Graphics g) a paintComponent(Graphics g) y quitar las dos últimas líneas del método, y usted debería estar bien.

EDITAR: Curiosamente, esto sólo funciona para el primer bar de las tres.Más pruebas en el progreso...

Por cierto, tienes un off-by-one de error en la frontera-la pintura de código.Debe ser:

g.setColor(BORDER_COLOR);
g.drawRect(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);

EDIT2: OK, lo tengo.Su completo paintComponent el método debe ser como sigue:

@Override
public void paintComponent(Graphics g) {
    double proportion = (expected == 0) ? 0 : ((double) actual) / expected;
    Rectangle bounds = super.getBounds();
    g.setColor(BACKGROUND);
    g.fillRect(0, 0, bounds.width, bounds.height);
    g.setColor(BAR_GRAPH_COLOR);
    g.fillRect(0, 0, (int) (bounds.width * proportion), bounds.height);
    g.setColor(BORDER_COLOR);
    g.drawRect(0, 0, bounds.width-1, bounds.height-1);
    label.setText(String.format("%s of %s (%.1f%%)", actual, expected, proportion * 100));
}

Tenga en cuenta que las coordenadas dadas a g.fillRect() y g.drawRect() son en relación al componente, por lo que deben comenzar en (0,0).

Y no, yo no puedo ayudarte con tu última pregunta, aunque siento su dolor.:)

Otros consejos

En su JPanel, llamó a super.setOpaque (verdadero). El JPanel va a completar completamente el fondo cuando llame a super.paint () y sobrescriba sus rectificaciones.

No estoy seguro si este es el origen de su problema, pero en Swing se supone que debe anular paintComponent(Graphics2D) en su lugar ...

En todo caso, creo que debería llamar a super.paint (g); en la parte superior de su método, no en la parte inferior. Es posible que la superclase esté dibujando sobre tus cosas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top