문제

나는 간단한 작은 스윙 구성 요소를 연구하고 있으며 페인트 방법이 왜 작동하지 않는지 알아 내려고 머리를 찢고 있습니다.

이 구성 요소의 아이디어는 레이블이있는 작은 jpanel이라는 것입니다. 배경 (라벨 뒤)은 흰색으로되어 있으며 왼쪽에 컬러 사각형이 두 가지 측정의 비율을 나타내는 "실제"와 "예상"의 비율을 나타냅니다.

이 구성 요소가 수직으로 정렬 된 경우 수평 막대로 구성된 막대 차트를 형성합니다.

이런 종류의 것은 매우 단순해야합니다.

어쨌든 코드는 다음과 같습니다.

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

}

간단한 테스트 하네스는 다음과 같습니다.

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

}

테스트 하네스는 간단한 프레임을 생성 한 다음 세 가지 컨트롤을 추가합니다.

레이블은 모두 올바르게 렌더링되며, 이는 Paint () 메소드가 실제로 호출되고 있음을 나타내지 만 직사각형은 그래픽 객체에 그려지지 않습니다.

내가 뭘 잘못하고 있죠?

그리고 왜 스윙 프로그래밍이 그렇게 많이 빨는가?


여기 내 마지막 코드가 있습니다. 감사합니다, 여러분의 도와 주셔서 감사합니다!

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));
}
도움이 되었습니까?

해결책

나는 당신이 다윗의 대답과 함께 의견에서 자신의 질문에 거의 대답했다고 생각합니다. 변화 paint(Graphics g) 에게 paintComponent(Graphics g) 방법의 마지막 두 줄을 제거하면 괜찮을 것입니다.

편집하다: 이상하게도, 이것은 세 가지의 첫 번째 막대에만 적용됩니다. 더 많은 테스트 진행 중 ...

그건 그렇고, 당신은 테두리 페인팅 코드에 오프별 오류가 있습니다. 그것은해야한다:

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

edit2 : 알았어. 당신의 전체 paintComponent 방법은 다음과 같아야합니다.

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

주어진 좌표에 유의하십시오 g.fillRect() 그리고 g.drawRect() 구성 요소와 관련이 있으므로 (0,0)에서 시작해야합니다.

그리고 아니, 나는 당신의 마지막 질문에 당신을 도울 수 없습니다. 그러나 나는 당신의 고통을 느낍니다. :)

다른 팁

JPANEL에서, 당신은 super.setopaque (true)라고 불렀습니다. JPANEL은 Super.Paint ()를 호출하고 망 갈색을 덮어 쓰면 배경을 완전히 채울 것입니다.

이것이 당신의 문제의 원인인지 확실하지 않지만 스윙에서 당신은 무시해야합니다. paintComponent(Graphics2D) 대신에...

무엇이든, 나는 당신이 super.paint (g)라고 부르야한다고 생각합니다. 당신의 방법의 맨 위에, 맨 아래가 아닌. 슈퍼 클래스가 당신의 물건 위에 그려 질 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top