Je travaille sur un simple petit composant d'oscillation, et je m'arrache les cheveux en essayant de comprendre pourquoi ma méthode de peinture ne fonctionne pas.La méthode de peinture Java ne peint pas?
L'idée derrière ce composant est que c'est un petit JPanel avec un label. L'arrière-plan (derrière l'étiquette) est censé être blanc, avec un rectangle de couleur sur le côté gauche indiquant le rapport de deux mesures: "réel" et "attendu".
Si vous aviez un groupe de ces composants alignés verticalement, ils formeraient un graphique à barres, composé de barres horizontales.
Ce genre de chose devrait être super simple.
Quoi qu'il en soit, voici le code:
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();
}
}
Et voici le faisceau de test simple:
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);
}
}
Le harnais de test crée un cadre simple et ajoute trois de ces contrôles.
Les étiquettes sont toutes affichées correctement, ce qui m'indique que la méthode paint() est en cours d'appel, mais que les rectangles ne sont pas dessinés dans l'objet Graphics.
Qu'est-ce que je fais mal?
Et pourquoi la programmation Swing est-elle si chiante?
Voici mon code final. Merci à tous pour votre aide!
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));
}
Essayez de supprimer "super.paint (g)" et "g.dispose()" et voyez ce qui se passe. –
Intéressant. Si je supprime "super.paint (g)" et "g.dispose()", alors j'obtiens les rectangles d'arrière-plan corrects, mais je perds le rendu de l'étiquette au premier plan. – benjismith
Hmm ... que diriez-vous de mettre un "super.paint (g)" avant de peindre les barres? Vous pouvez également utiliser "g.drawString()" pour afficher du texte. –