【问题标题】:JLabel's background color changes when updated setText()更新 setText() 时 JLabel 的背景颜色发生变化
【发布时间】:2012-06-08 19:29:29
【问题描述】:

编辑(不是不透明属性导致问题,它正在更新 JLabel 的背景属性): 我正在使用 MouseMotionListener 将 JLabel 的 setText() 设置为鼠标的当前位置。 JLabel 在程序第一次运行时以正确的背景颜色/透明度开始。每当更新 text/mouseMotion 时,JLabel 就不再透明。

更新的可运行代码:

例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.TextArea;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class MouseTester extends JFrame {
public static void main(String[] args) {
try {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            MouseTester.createMouseTester();
        }
    });
} catch (Throwable t) {
    System.exit(1);
}
}
private static MouseTester mt = null;
private JLabel mouseLocation = null;
private static Color labelBackgroundColor = new Color(0, 0, 0, 127);
private static Color labelForegroundColor = Color.WHITE;

public static void createMouseTester() {
      if (mt != null)
          return;
      mt = new MouseTester();
      mt.setVisible(true);
}

private MouseTester() {
      super();
      mt = this;
      setResizable(true);
      Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize();
      setMinimumSize(new Dimension(Math.min(800, dScreen.width), Math.min(590,
      dScreen.height)));
      setSize(getMinimumSize());
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      mouseLocation = new JLabel(" Lat/Long ");
      mouseLocation.setOpaque(true);
      mouseLocation.setBackground(labelBackgroundColor);
      mouseLocation.setForeground(labelForegroundColor);
      mouseLocation.setToolTipText("The MGRS coordinates.");

      Component textArea = new TextArea("Move mouse here to see mouse motion info...");

      // Add a mouse motion listener to capture mouse motion events
      textArea.addMouseMotionListener(new MouseMotionAdapter() {

public void mouseMoved(MouseEvent evt) {
      TextArea source = (TextArea) evt.getSource();
          // Process current position of cursor while all mouse buttons are up.
            mouseLocation.setText(source.getText() + "\nMouse moved [" + 
          evt.getPoint().x + "," + evt.getPoint().y + "]");
            mouseLocation.setBackground(labelBackgroundColor);
            mouseLocation.setForeground(labelForegroundColor);
            mouseLocation.setOpaque(true);
            mouseLocation.repaint();

      }
      public void mouseDragged(MouseEvent evt) {

      }
  });

  // Add the components to the frame; by default, the frame has a border layout
        mt.add(textArea, BorderLayout.NORTH);
        mouseLocation.setOpaque(true);
        mouseLocation.setBackground(labelBackgroundColor);
        mouseLocation.setForeground(labelForegroundColor);
        mt.add(mouseLocation, BorderLayout.SOUTH);

        int width = 300;
        int height = 300;
        mt.setSize(width, height);
  }
}

JLabel 开始时透明/略带灰色,然后随着鼠标移动变为不透明且完全黑色。透明度由背景颜色决定。

我几乎尝试过在所有我能想到的地方更改背景颜色,但它不起作用..

我希望它始终保持颜色(启动时的颜色)。

【问题讨论】:

  • 你能发一个SSCCE吗?从您的代码 sn-p 中我们看不到太多。
  • 顺便说一句 - JLabel 默认情况下不透明(== 不透明 == 透明)。如果你想要底部图像 - 你不需要调用setOpaque(false)。我看到您将 opaque 设置为 true(== 有背景 == 不透明),所以最好保留不透明的默认值。
  • sscce+1。

标签: java swing jlabel


【解决方案1】:

您已声明您的 JLabel 是不透明的,这意味着它完全负责绘制自己的背景。然而,您已将其背景颜色设置为半透明颜色。这是一个矛盾,是你的问题的原因。

您可以通过使用 mt.repaint(); 而不是 mouseLocation.repaint(); 来修复 JLabel 的外观,从而强制重新绘制 JLabel 后面的整个面板区域(灰色),然后重新绘制 JLabel用你的半透明颜色。

如果您想避免重新绘制整个mt 对象的成本,那么您需要将您的 JLabel 嵌套在一些可以快速重新绘制的较小组件中。

【讨论】:

  • 对不起,我不得不反对:opacity 与透明度正交。另请参阅此answer 和此answer
  • JComponent 的不透明度和透明度在 Java 中是不同的东西。但是在示例中使用它们的方式非常值得怀疑。除非你能保证包含“不透明但透明”的 JLabel 的组件总是会在 JLabel 本身被重新绘制之前被重新绘制,否则结果将是不可预测的。当我运行示例代码时,大多数重新绘制涉及首先绘制纯黑色背景,但每隔一段时间,一些缓冲图像中的一些随机内容会显示在 JLabel 后面。
  • +1 同意;这个example 解决了一个关于类似artifacts 的问题。
  • 谢谢。我没有意识到这一点,你已经消除了我的困惑。
【解决方案2】:

您必须调用JLabel#repaint() 来从Opaque(true) 切换到Opaque(false),反之亦然,对于从(Xxx)MouseListeners 触发的每个MouseEvents,因为API 中缺少此方法,其余为here with description by @kleapatra

【讨论】:

  • 有趣,文本和颜色是绑定属性,但opacity 不是。
【解决方案3】:

我不确定您为什么要更改标签的 transparency。制作标签opaque并调整其背景saturation可能就足够了,如下所示。

关于您的实施的几点说明:

  • 感谢使用event dispatch thread
  • 让布局完成工作;使用setSize()sparingly
  • 不要不必要地混合 AWT 和 Swing 组件。
  • 不要吞下异常。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class MouseTester extends JFrame {
    private static MouseTester mt;
    private static Color labelBackgroundColor = Color.gray;
    private static Color labelForegroundColor = Color.white;
    private JLabel mouseLocation;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MouseTester.createMouseTester();
            }
        });
    }

    public static void createMouseTester() {
        mt = new MouseTester();
        mt.setVisible(true);
    }

    private MouseTester() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mouseLocation = new JLabel("Lat/Long", JLabel.CENTER);
        mouseLocation.setOpaque(true);
        mouseLocation.setBackground(labelBackgroundColor);
        mouseLocation.setForeground(labelForegroundColor);
        mouseLocation.setToolTipText("The MGRS coordinates.");
        JTextArea textArea = new JTextArea(
            "Move mouse here to see mouse motion info...");
        textArea.addMouseMotionListener(new MouseMotionAdapter() {

            @Override
            public void mouseMoved(MouseEvent me) {
                mouseLocation.setText("Mouse moved ["
                    + me.getX() + ", " + me.getY() + "]");
            }
        });
        this.add(textArea, BorderLayout.CENTER);
        this.add(mouseLocation, BorderLayout.SOUTH);
        this.pack();
        this.setSize(320, 240); // content placeholder
        this.setLocationRelativeTo(null);
    }
}

【讨论】:

  • 这绝对是一种更简单的方法。用户可能想要 JLabel 的半透明背景的一个原因是他是否希望它在每种外观和感觉中看起来都不同。
  • user1442870 的评论是正确的,我使用的示例只是我拼凑起来的一个示例,以解决我遇到的特定问题,因为我正在处理的程序太大发布整个源代码。非常感谢您的注释,我对用户界面编程比较陌生,并且不知道 AWT/Swing 混合方面(我在我正在处理的程序上犯了这个错误)。
猜你喜欢
  • 1970-01-01
  • 2012-08-08
  • 2021-05-15
  • 2011-06-15
  • 1970-01-01
  • 2018-04-04
  • 2011-09-19
  • 2017-06-10
  • 1970-01-01
相关资源
最近更新 更多