Frage

Ich bin auf einer einfachen kleinen Swing-Komponente zu arbeiten, und ich meine Haare, warum meine paint-Methode funktioniert nicht, um herauszufinden, Ausreißen.

Die Idee hinter dieser Komponente ist, dass es ein kleines JPanel mit einem Etikett ist. Der Hintergrund (hinter dem Etikett) soll mit einem farbigen Rechteck auf der linken Seite sein, weiß, was das Verhältnis von zwei Messungen:. „Ist“ und „erwartet“

Wenn Sie eine Reihe dieser Komponenten hatten vertikal ausgerichtet sind, würden sie ein Balkendiagramm bilden, bestehend aus horizontalen Balken.

Diese Art der Sache sollte super-einfach sein.

Wie auch immer, hier ist der 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();
   }

}

Und hier ist der einfache Test-Harnisch:

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);
   }

}

Die Testumgebung erstellt einen einfachen Rahmen und fügt dann drei diese Kontrollen.

Die Etiketten sind alle korrekt wiedergegeben, die mir zeigt, dass die Farbe () Methode tatsächlich aufgerufen wird, aber die Rechtecke werden nicht gezogen werden, um das Graphics-Objekt.

Was mache ich falsch?

Und warum Swing-Programmierung saugt so viel?


Hier ist mein letzter Code. Danke, alle, für Ihre Hilfe!

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));
}
War es hilfreich?

Lösung

Ich glaube, Sie haben fast Ihre eigene Frage in den Kommentaren beantwortet, zusammen mit David Antwort. Ändern paint(Graphics g) paintComponent(Graphics g) und entfernen Sie die letzten beiden Zeilen des Verfahrens, und Sie sollten in Ordnung sein.

EDIT: Merkwürdig ist, dass dies funktioniert nur für den ersten Takt der drei. Weitere Tests im Gang ...

übrigens, haben Sie einen Off-by-one Fehler in dem Grenz-Malerei-Code. Es sollte sein:

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

EDIT2: OK, es bekommt. Ihre vollständige paintComponent Methode sollte wie folgt aussehen:

@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));
}

Beachten Sie, dass die Koordinaten gegeben g.fillRect() und g.drawRect() auf die Komponente relativ sind, so müssen sie bei (0,0) beginnen.

Und nein, ich kann Ihnen mit Ihrer letzten Frage nicht helfen, obwohl ich fühle deinen Schmerz. :)

Andere Tipps

In Ihrer JPanel, genannt Sie super.setOpaque (true). Die JPanel wird sich vollständig im Hintergrund zu füllen, wenn Sie anrufen super.paint () und Ihre retangles überschrieben.

Nicht sicher, ob dies die Ursache des Problems ist, sondern in Swing bist du stattdessen außer Kraft zu setzen paintComponent(Graphics2D) soll ...

Wenn überhaupt, ich glaube, Sie sollten super.paint (g) anrufen; an der Spitze Ihrer Methode, nicht ganz am Ende. Es ist möglich, die übergeordnete Klasse auf Ihre Sachen zieht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top