【问题标题】:Placing JButton inside JPanel inside JFrame with variable outcomes将 JButton 放在 JFrame 内的 JPanel 内,结果可变
【发布时间】:2020-08-03 03:10:59
【问题描述】:

我在一个简单的(?)概念上遇到了一个非常令人困惑的问题。我正在尝试学习JFrameJPanel 等的基础知识,现在正在尝试实现一个简单的任务。我想有一个大的JFrame,叫做画布,里面有两个JPanel,彼此相邻,没有边距或任何东西。在这两个 JPanel 中,我有一个按钮覆盖了一个彩色矩形。当您单击按钮时,按钮应该消失并显示颜色。我的问题很多。

代码似乎有自己的生命。即使在 print 语句中使用 get 消息也会导致输出发生变化。至于输出本身,乍一看,它看起来不错,两个按钮并排命名正确。

但是,当您单击按钮 1 时,两个按钮都会消失,而第三个按钮(名为按钮 2)会出现在右上角。当您单击新按钮时,它会禁用但不会消失。

有时当你点击按钮 1 时,第三个按钮 2 也会出现,但原来的按钮 2 只禁用不隐藏。此外,整个背景是蓝色的,而不是应有的红色和蓝色。当您单击按钮 2 时会发生一组全新的事件,但希望这可能足以帮助您。

非常感谢!

import java.awt.*;
import javax.swing.*;
public class testbig {
    public static void main(String[] args) {
        JFrame canvas = new JFrame("canvas");
        canvas.setSize(400,400);
        canvas.setVisible(true);
        canvas.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        canvas.setLayout(null);

        testinner temp = new testinner("1",Color.blue);
        temp.setBounds(0,0,200,400);
        canvas.getContentPane().add(temp);

        testinner temp2=new testinner("2",Color.red);
        temp2.setBounds(200,0,200,400);
        canvas.getContentPane().add(temp2);
    }
}
public class testinner extends JPanel implements ActionListener{
    private JButton button;

    private Color color2;
    public testinner(String title,Color color) {
        super();
        color2=color;
        setSize(200,400);
        setBackground(color);
        setLayout(new FlowLayout());
        button=new JButton(title);
        button.setBounds(getX(), getY(), getWidth(), getHeight());
        button.setVisible(true);
        button.addActionListener(this);
        //panel.add(label);
        add(button);
    }
    public void paintComponent(Graphics gr) {
        gr.setColor(color2);
        gr.fillRect(getX(), getY(), getWidth(), getHeight());

    }
    public void actionPerformed( ActionEvent evt){
        button.setEnabled(false);
        button.setVisible(false);
        //System.out.println(this);
        //shown.setVisible(true);
    }
}

【问题讨论】:

  • 您不应该将“getX”添加到您的fillRect 或按钮的setBounds。它们应该是相对于它们所在的容器的值。这也适用于您的 paintComponent

标签: java swing jpanel jbutton actionlistener


【解决方案1】:

让我们看看你做了什么。您已经创建了一个具有空布局的 JFrame。所以这意味着它不管理它的孩子的大小或位置。 (有人可能会说这是一个疏忽的父母。)

这意味着你的两个 JPanel应该记住你给他们打的 setBounds 电话。这both设置了它们的大小和位置。所以你的setSize 电话是多余的。

您已将 JPanel 设置为具有 flowLayout 布局管理器。这意味着他们确实会尝试管理孩子的大小和位置。它并不总是即时的。

您在按钮上调用 setBounds。现在他们真的搞砸了。首先,它们有自己的界限和大小。 不要在非自定义组件上调用 setBound。实际上,最好不要使用它。

第一个面板没问题。您将按钮的边界设置为 (0, 0, 200, 400)。那是在它打算利用的 JPanel 中。

第二个面板不行。您的按钮的边界是 (200, 0, 200, 400) 您的组件是 200 宽,因此您已经为按钮提供了面板外部的空间以供绘制。然后您的绘图组件也将填充一个矩形在您的 jpanel 之外

所以你的按钮有一个大小和位置,一旦你要求你的布局管理器做某事,它就会改变。

以下代码管理我假设您正在尝试做的事情。有两个彩色面板,每个都显示一个 JButton。当您单击它时,它会消失。这主要是您删除了一些冗余位后所拥有的。

import java.awt.*;
import javax.swing.*;
public class TestBig {
    public static void main(String[] args) {
        JFrame canvas = new JFrame("canvas");
        canvas.setSize(400,400);

        canvas.setLayout(null);

        JPanel leftPanel = new JPanel( new FlowLayout(0, 0, 0) );
        leftPanel.setOpaque(true);
        leftPanel.setBackground(Color.BLUE);

        JPanel rightPanel = new JPanel();
        rightPanel.setOpaque(true);
        rightPanel.setBackground(Color.RED);

        BufferedImage img = new BufferedImage(200, 400, BufferedImage.TYPE_INT_ARGB);
        Graphics g = img.getGraphics();
        g.setColor(Color.YELLOW);
        g.fillRect(0, 0, 200, 400);
        g.dispose();

        JButton left = new JButton(new ImageIcon(img));
        left.setBorder(null);
        left.addActionListener( evt->{
            left.setVisible(false);
        });

        JButton right = new JButton("right");
        right.addActionListener( evt -> {
            right.setVisible(false);
        });

        leftPanel.add(left);
        rightPanel.add(right);

        canvas.add(leftPanel);
        canvas.add(rightPanel);

        leftPanel.setBounds( 0, 0, 200, 400);
        rightPanel.setBounds(200, 0, 200, 400);

        canvas.setVisible(true);
        canvas.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    }
}

【讨论】:

  • 谢谢!这很有帮助。您的代码有效,我想让按钮填满整个 JPanel。因此,我在它们的 ActionListener 之后立即添加了这一行:left.setPreferredSize(new Dimension(leftPanel.getBounds().width,leftPanel.getBounds().height)) 用于左右。不幸的是,它们并没有完全占据整个空间。这是因为面板有默认的 FlowLayout 吗?即使您说不,我是否应该将其设为 null 并为按钮设置边界?感谢您的帮助!
  • @Arneya 可能。 setBounds 是你的布局管理器处理的东西。因此,当您在布局中的对象上设置它时,布局管理器可能会更改它。一个答案是您的建议,使用空布局和 setBounds。我认为您可以看到这个问题,它不能很好地适应不同尺寸的显示器或不同的字体。扩展它要困难得多。除此之外,如果它正在做你想做的事,那很好。
  • 是的,FlowLayout 有一个边框,你可以检查它的默认选项,docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/… 但我想你会发现即使 JButton 扩展了面板的全尺寸也会有边框。您可能需要考虑制作图像/图标并在您的面板上使用它。
  • @Arneya 我已经更新了答案,用纯色/图像填充左侧按钮。我还让 FlowLayout 有 0px 填充。我认为左侧面板看起来像您想要的那样。
猜你喜欢
  • 2012-05-09
  • 1970-01-01
  • 2017-08-18
  • 2012-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
相关资源
最近更新 更多