简体   繁体   English

Java Swing按钮消失

[英]Java Swing button disappear

I am trying to make an invisible button where the painted button is, but when I try to add the button, it disappear almost every time I run the program and when its visible it goes invisible on resize. 我试图在绘制的按钮所在的位置创建一个不可见的按钮,但是当我尝试添加该按钮时,几乎在每次运行该程序时,该按钮都会消失,并且当它可见时,它在调整大小时不可见。 Please help me, whats wrong? 请帮我,怎么了?

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;

public class Main extends JFrame
{
    public static final int VERSION = 1;
    private static final long serialVersionUID = 1L;
    private Image img;
    private boolean hasMouseListener = false;
    private Image bgImage;

    public static int ii;
    public static int jj;


    public Main() throws IOException
    {
        super("Unigin Alpha 1.0.0"); //Set title


        ii = this.getWidth();
        jj = this.getHeight();

        setBackground(Color.WHITE);
        //loginForm1 = new LoginForm(this);
        JPanel localJPanel = new JPanel();
        //localJPanel.setLayout(null);
        setVisible(true); 
        setTitle("Unigin");

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        localJPanel.setPreferredSize(new Dimension(854, 480));

        setLayout(new FlowLayout());
        add(localJPanel, "Center");

        //-------------------------------------------------------------------------
        JButton bb = new JButton("HEEL");
        localJPanel.add(bb, "CENTER");
        //bb.setLocation(getWidth()/2-76-8, getHeight()/2); Doesn't work!
        //i / 2 - 76 - 8, j / 2, 76, 20

        pack();
        setLocationRelativeTo(null);
        try
        {
          setIconImage(ImageIO.read(Main.class.getResource("favicon.png")));
        } catch (IOException localIOException) {
          localIOException.printStackTrace();
        }

        super.paint(getGraphics());
    }





    public void paint(Graphics paramGraphics)
      {
        try {
            bgImage = ImageIO.read(Main.class.getResource("wool_red.png")).getScaledInstance(32, 32, 16);
          } catch (IOException localIOException) {
            localIOException.printStackTrace();
          }

        int i = getWidth() / 2;
        int j = getHeight() / 2;
        if ((img == null) || (img.getWidth(null) != i) || (img.getHeight(null) != j)) {
          img = createVolatileImage(i, j);
        }

        Graphics localGraphics = img.getGraphics();
        for (int k = 0; k <= i / 32; k++)
          for (int m = 0; m <= j / 32; m++)
            localGraphics.drawImage(bgImage, k * 32, m * 32, null);
        String str;
        FontMetrics localFontMetrics;

        if (true) {
          if (!hasMouseListener) {
            hasMouseListener = true;
            //addMouseListener(this);
          }
          localGraphics.setColor(Color.WHITE);
          str = "Bukkit Unigin";
          localGraphics.setFont(new Font(null, 1, 20));
          localFontMetrics = localGraphics.getFontMetrics();
          localGraphics.drawString(str, i / 2 - localFontMetrics.stringWidth(str) / 2, j / 2 - localFontMetrics.getHeight() * 2);

          localGraphics.setColor(Color.LIGHT_GRAY);
          localGraphics.setFont(new Font(null, 0, 12));
          localFontMetrics = localGraphics.getFontMetrics();

          localGraphics.setColor(Color.LIGHT_GRAY);


          localGraphics.fill3DRect(i / 2 - 76 - 8, j / 2, 76, 20, true);
          localGraphics.fill3DRect(i / 2 + 8, j / 2, 76, 20, true);
          //localGraphics.fill3DRect(x,y,width,height,true);

          localGraphics.setColor(Color.WHITE);
          str = "What do you want to do?";
          localGraphics.drawString(str, i / 2 - localFontMetrics.stringWidth(str) / 2, j / 2 - 8);

          localGraphics.setColor(Color.BLACK);
          str = "New plugin";
          localGraphics.drawString(str, i / 2 - 56 - 18 - localFontMetrics.stringWidth(str) / 2 + 28, j / 2 + 14);
          str = "Load plugin";
          localGraphics.drawString(str, i / 2 + 18 - localFontMetrics.stringWidth(str) / 2 + 28, j / 2 + 14);
        }

        localGraphics.dispose();
        paramGraphics.drawImage(img, 0, 0, i * 2, j * 2, null);


      }

    public static void main(String[] args) throws IOException {

        new Main();



    }
}

The painting will disappear when you resize the frame because you aren't overriding the paintComponent of a JComponent you have a method named paint that runs once when called by the constructor. 当您调整框架的大小时,绘画将消失,因为您没有覆盖JComponentpaintComponent ,而是拥有一个名为paint的方法,该方法在构造函数调用时运行一次。

Instead break out your application into separate classes that each handle less responsibility. 而是将您的应用程序分为几个单独的类,每个类的责任较少。 One of which needs to override paintComponent() to actually draw the button. 其中之一需要重写paintComponent()才能真正绘制按钮。

Follow the Swing Tutorial for custom painting: http://docs.oracle.com/javase/tutorial/uiswing/painting/ 遵循Swing教程进行自定义绘画: http : //docs.oracle.com/javase/tutorial/uiswing/painting/

If you want to make an invisible JButton. 如果要制作一个不可见的JButton。

JButton invisibleButton = new JButton(){
     @Override
     protected void paintComponent(Graphics g){}; 
};

Fix 1: 修复1:

Remove super.paint(getGraphics()); 删除super.paint(getGraphics()); from constructor. 来自构造函数。

Reason: You should never do it. 原因:绝对不要这样做。 Use of repaint() is recommended although none is needed in this case. 建议使用repaint(),尽管在这种情况下不需要。


Fix 2: 修复2:

Call super.paint(g) at the end of overridden paint method. 在覆盖的paint方法的末尾调用super.paint(g)

Reason: This method is responsible for drawing children (Your button in this case). 原因:此方法负责绘制子项(在这种情况下为“按钮”)。 Button won't appear if you don't call it every time the frame is painted. 如果您在每次绘制框架时都不调用按钮,则按钮不会出现。


Fix3: 修复3:

Call setBackGround(new java.awt.Color(0, 0, 0, 0)); 调用setBackGround(new java.awt.Color(0, 0, 0, 0)); in the constructor. 在构造函数中。

Reason: If you don't do this, the super.paint(g); 原因:如果不这样做,则super.paint(g); would erase everything you painted manually. 将删除您手动绘制的所有内容。


Personally I'd suggest using a JPanel for custom painting. 我个人建议使用JPanel进行自定义绘画。 It's painting mechanism is much cleaner (Separate paintComponent, paintBorder, paintChildren methods). 它的绘制机制更加简洁(单独的paintComponent,paintBorder,paintChildren方法)。

Good luck. 祝好运。

  • Don't use getGraphics , it unreliable and this is not how custom painting is done 不要使用getGraphics ,它不可靠,这不是完成自定义绘制的方式
  • Don't call paint yourself, ever. 永远不要称自己为paint You are not responsible for performing painting operations, that's the responsibility of the RepaintManager 您不负责执行绘画操作,这是RepaintManager的责任
  • Don't break the paint chain, always call super.paintXxx when overriding paint methods. 不要破坏绘制链,在覆盖绘制方法时始终调用super.paintXxx The painting process is a complex series of chained method calls which work together to generate the output. 绘制过程是一系列复杂的链式方法调用,它们一起工作以生成输出。 You should avoid overriding paint of top level containers, top level containers are a complex series of components, overriding paint can easily break this design as you have done here. 您应该避免覆盖顶层容器的paint ,顶层容器是一系列复杂的组件,覆盖paint很容易破坏此设计,就像您在此处所做的那样。 They are also not double buffered 它们也不是双缓冲的
  • Avoid loading resources within any paintXxx method or performing any time consuming operations. 避免在任何paintXxx方法中加载资源或执行任何耗时的操作。 Paint operations are intended to return quickly. 绘画操作旨在迅速返回。 Failing to do so will slow the repaint process noticeably. 否则,将明显减慢重涂过程。

Basically, by breaking the paint chain, you've prevented the paint process from being able to render the child components of the frame. 基本上,通过断开绘制链,可以防止绘制过程能够渲染框架的子组件。 You would run into issues even if you did call super.paint , as you would either paint over the top of what was previously painted or the paint process would clear what you painted before it...(not to mention that JFrame has at least three layers of other containers sitting on top of it before you even add anything to it) 即使您确实调用了super.paint ,您也会遇到问题,因为您将在先前绘制的内容之上绘制,或者绘制过程将清除您之前绘制的内容...(更不用说JFrame至少具有三层其他容器位于其上,甚至没有添加任何东西)

Start by separating your program logic. 首先分离您的程序逻辑。 Focus on the needs of you "image", rendering to a custom component, extending from something like JPanel , but overriding it's paintComponent method. 专注于您的“图像”需求,将其呈现给自定义组件,从诸如JPanel东西扩展而来,但是覆盖它的paintComponent方法。

Add this to your frame (may as the content pane). 将此添加到您的框架(可能作为内容窗格)。 Add your other controls to it. 向其添加其他控件。

Take a look at Performing Custom Painting and Painting in AWT and Swing for more details about how painting works and How to use root panes to understand the complex nature of top level containers in Swing 查看有关在AWT和Swing执行自定义绘画绘画的内容,以了解有关绘画工作原理以及如何使用根窗格来了解Swing中顶级容器的复杂性的更多详细信息。

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

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