简体   繁体   English

Java Paint方法不绘画?

[英]Java Paint Method Doesn't Paint?

I'm working on a simple little swing component, and I'm tearing out my hair trying to figure out why my paint method isn't working. 我正在研究一个简单的小摆动组件,我正在撕扯我的头发试图弄清楚为什么我的油漆方法不起作用。

The idea behind this component is that it's a small JPanel with a label. 这个组件背后的想法是它是一个带标签的小型JPanel。 The background (behind the label) is supposed to be white, with a colored rectangle on the left-hand side indicating the ratio of two measurements: "actual" and "expected". 背景(标签后面)应该是白色的,左侧有一个彩色矩形表示两个测量值的比率:“实际”和“预期”。

If you had a bunch of these components aligned vertically, they'd form a bar chart, composed of horizontal bars. 如果你有一堆这些组件垂直对齐,它们会形成一个由水平条组成的条形图。

This kind of thing should be super-simple. 这种事情应该是超级简单的。

Anyhow, here's the 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();
   }

}

And here's the simple test harness: 这是简单的测试工具:

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

}

The test harness creates a simple frame and then adds three of these controls. 测试工具创建一个简单的框架,然后添加其中三个控件。

The labels are all rendered correctly, which indicates to me that the paint() method is actually being called, but the rectangles aren't being drawn to the Graphics object. 标签全部正确呈现,这向我指示实际调用了paint()方法,但矩形未被绘制到Graphics对象。

What am I doing wrong? 我究竟做错了什么?

And why does Swing programming suck so much? 为什么Swing编程太吸引人了?


Here's my final code. 这是我的最终代码。 Thanks, everyone, for your help! 谢谢,大家,谢谢你的帮助!

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

I think you've almost answered your own question in the comments, along with David's answer. 我想你在评论中几乎已经回答了你自己的问题,以及大卫的回答。 Change paint(Graphics g) to paintComponent(Graphics g) and remove the last two lines of the method, and you should be fine. paint(Graphics g)更改为paintComponent(Graphics g)并删除方法的最后两行,你应该没问题。

EDIT: Oddly, this only works for the first bar of the three. 编辑:奇怪的是,这只适用于三者中的第一个栏。 More testing in progress... 正在进行更多测试......

By the way, you have an off-by-one error in the border-painting code. 顺便说一下,边框绘制代码中有一个一个一个错误。 It should be: 它应该是:

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

EDIT2: OK, got it. EDIT2:好的,明白了。 Your full paintComponent method should be as follows: 您的完整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));
}

Note that the coordinates given to g.fillRect() and g.drawRect() are relative to the component, so they must start at (0,0). 请注意,给予g.fillRect()g.drawRect()的坐标是相对于组件的,因此它们必须从(0,0)开始。

And no, I can't help you with your last question, though I feel your pain. 不,我无法帮助你解决你的最后一个问题,尽管我感到痛苦。 :) :)

In your JPanel, you called super.setOpaque(true). 在你的JPanel中,你调用了super.setOpaque(true)。 The JPanel is going to completely fill in the background when you call super.paint() and overwrite your retangles. 当您调用super.paint()并覆盖您的重新绑定时,JPanel将完全填充后台。

不确定这是否是你的问题的根源,但在Swing你应该覆盖paintComponent(Graphics2D)而不是......

If anything, I think you should be calling super.paint(g); 如果有的话,我想你应该打电话给super.paint(g); at the TOP of your method, not at the very bottom. 在你的方法的顶部,而不是在最底层。 It's possible the superclass is drawing on top of your stuff. 超类可以在你的东西之上绘图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM