【问题标题】:How to move button to exact location?如何将按钮移动到确切位置?
【发布时间】:2017-07-24 01:16:15
【问题描述】:

我希望按钮和文本框以与它们相同的布局进入标记为红色的空间中。查看图片以了解我的意思。

更新:按钮现在就位,但图像不会出现在第二个面板上

我怎样才能将它们移到那里?到目前为止,这是我的代码

package gasindicator;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;

public class GasIndicator extends JPanel
 {
private Image image;


GasIndicator()
{
    try
    {
        image = ImageIO.read(new URL("http://i68.tinypic.com/2ceja8i.png"));

    }
    catch (IOException ioe)
    {
        System.out.println("Unable to fetch image.");
        ioe.printStackTrace();
    }

    setLayout( new BorderLayout() );

    JLabel background = new JLabel( new ImageIcon(image) );
    background.setLayout( new FlowLayout(FlowLayout.LEFT) );
    add( background );

    JPanel buttonPanel = new JPanel( new GridLayout(0, 3, 6, 5) );
    buttonPanel.setBorder( new EmptyBorder(338, 233, 0, 0) );

    buttonPanel.setOpaque( false );


    //for (int i = 0; i < 7; i++)
    {
        JButton button = new JButton("Button");
        JButton button1 = new JButton("Button");
        JButton button2 = new JButton("Button");
        JButton button3 = new JButton("Button");
        JButton button4 = new JButton("Button");
        JButton button5 = new JButton("Button");

        button.setPreferredSize( new Dimension(160, 45) );
        buttonPanel.add(button);
        buttonPanel.add(button1);
        buttonPanel.add(button2);
        buttonPanel.add(button3);
        buttonPanel.add(button4);
        buttonPanel.add(button5);

         button.addActionListener(new Action());
    }

    background.add( buttonPanel );
}

static class Action implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            JFrame frame2 = new JFrame("Museums in London");
            frame2.setVisible(true);
            frame2.setSize(550, 650);
            JPanel panel = new JPanel();
            frame2.add(panel);
            Custom contentPane;

            // JFrame frame = new JFrame("JTextField");
            contentPane = new Custom();
            frame2.setContentPane(contentPane);

        }
    }

private static void ShowGUI()
{
    JFrame frame = new JFrame("SSCCE");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new GasIndicator());
    frame.pack();
    frame.setLocationByPlatform( true );
    frame.setVisible( true );
}

public static void main(String[] args)
{
    EventQueue.invokeLater( () -> ShowGUI() );
/*
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            createAndShowGUI();
        }
    });
*/
}

class Custom extends JPanel {

public BufferedImage image;

public Custom() {
    try {

        image = ImageIO.read(new URL 
("http://www.destination360.com/europe/uk/images/s/museums.jpg"));
    } catch (IOException ioe) {
        System.out.println("Unable to fetch image.");
        ioe.printStackTrace();
    }
}

public Dimension getPreferredSize() {
    return (new Dimension(image.getWidth(), image.getHeight()));
}

public void paintComponent(Graphics x) {
    super.paintComponent(x);
    x.drawImage(image, 10, 10, this);
}
  }
}

【问题讨论】:

  • panel.setLayout(null);
  • 这里的其他人会告诉你将布局设置为 null 是糟糕的设计,你应该学会使用不同的 LayoutManager 来做到这一点。
  • 我把那个放在哪里?以及如何将所有按钮一起移动到所需位置?
  • 99.9% 的时间,当您认为您需要 null 布局时,您不需要。布局管理器做了很多重要的工作,不仅仅是定位组件,整个 API 是基于当 UI 以某种方式发生变化时布局管理器的交互。当涉及到字体指标和硬件的不同方面时,还需要进行很多繁琐的计算

标签: java swing layout null-layout-manager


【解决方案1】:

这里的问题是您的面板上设置了标准的 Layoutmanager。 尝试禁用它

contentPane.setLayout(null);

然后您可以使用button.setBountds(x,y,w,h); 随意移动按钮

我总是直接在 Frame 上绘制,而不是像您那样使用自定义面板,但我发现在某些用例中这会是更好的方法。

如果你写

new JFrame.getContentPane().setLayout(null);

您的框架获得了默认窗格,并且仍然将其布局设置为 null。

不同之处在于您可以直接添加到框架中,而不是使用放置内容的面板。

frame.add(new Button().setBounds(x,y,w,h));

试试我尝试调试的这个版本的代码:

Custom1 contentPane;


//at first create and set the frame
JFrame frame = new JFrame("Windowname goes here");
frame.setSize(1160, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);

//next add your custom panel
contentPane = new Custom1();
frame.setContentPane(contentPane);

//better add this to the panel instead of the frame
JTextField textfield = new JTextField(20);
frame.add(textfield);

textfield.setBackground(Color.black);
textfield.setForeground(Color.white);

//you are using 2 panels with null layout here
JPanel panel = new JPanel();
panel.setSize(frame.getHeight(),frame.getWidth());      //give the panel some bounds!
panel.setOpaque(false); //unnecesary
panel.setLayout(null);
panel.setBackground(Color.BLACK);
frame.add(panel);

JButton button = new JButton("London");
JButton button1 = new JButton("Oxford");
JButton button2 = new JButton("Cambridge");

//you seemed to not have added these before
JButton button4 = new JButton("Click");
JButton button5 = new JButton("Click");
JButton button6 = new JButton("Click");

button.setBounds(60, 400, 220, 30);
button.setBackground(Color.black);
button.setForeground(Color.WHITE);

button1.setBounds(x,y,w,h);                         // !!!! <------
button1.setBackground(Color.black);
button1.setForeground(Color.WHITE);

button2.setBounds(x,y,w,h);                         // !!!! <------
button2.setBackground(Color.black);
button2.setForeground(Color.WHITE);

button4.setBounds(80, 50, 100, 30);
button5.setBounds(x,y,w,h);                         // !!!! <------
button6.setBounds(x,y,w,h);                         // !!!! <------

panel.add(button);
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
panel.add(button6);

//SETVISIBLE ALWAYS GOES LAST
frame.setVisible(true);

我修补了您的代码并在其中编写了一些 cmets。 我用 !!!!标记了您需要为按钮设置边界的位置,您似乎已经为 button4 设置了此设置,但没有为其他设置设置。此外,您应该在代码中获得更好的结构,我不想侮辱您,但我将其称为“意大利面条代码”。 还有一些问题存在问题,例如您似乎根本没有添加按钮,但它们出现在您的图片中......

在使用边界值并调查代码中的最终错误后,让我知道它是否有效。 另外,如果你把整个项目发给我,我可以看管它,但最好自己尝试一下,如果别人做了你的工作,它不会给你任何东西。

祝你好运,编码愉快 (͡° ͜ʖ ͡°)

【讨论】:

  • 你能把它添加到我的代码中吗?当我添加它时。它会删除所有按钮,就好像它们不存在一样
  • (1-) 不要使用空布局。在包含按钮的面板上使用 GridLayout 或 GridBagLayout。
  • @camickr 我正在使用网格布局,但这不会将所有按钮移到我想要它们所在的位置
  • ....then you won't get far with a fixed layoutmanager - 当然可以。您可以嵌套面板。您可以在面板之间提供水平/垂直间隙。您可以在面板上使用边框。用布局管理器把所有组件放到一个面板上,然后用上面的技巧调整面板的位置,就容易多了,接下来就是调整各个独立按钮的位置了。
  • “也许你能找出究竟是什么让空布局如此糟糕?” 当然! null layout is evil,也是this question 和this example 中的答案。所以,这就是你应该使用@camickr 上面建议的layout managers 的原因(我出于与他相同的原因投了反对票)
【解决方案2】:

演示使用带边框的布局管理器概念的简单示例。按钮的大小也已调整为图像中按钮的大小:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;

public class SSCCE extends JPanel
{
    private Image image;

    SSCCE()
    {
        try
        {
            image = ImageIO.read(new URL("http://i68.tinypic.com/2ceja8i.png"));

        }
        catch (IOException ioe)
        {
            System.out.println("Unable to fetch image.");
            ioe.printStackTrace();
        }

        setLayout( new BorderLayout() );

        JLabel background = new JLabel( new ImageIcon(image) );
        background.setLayout( new FlowLayout(FlowLayout.LEFT) );
        add( background );

        JPanel buttonPanel = new JPanel( new GridLayout(0, 3, 6, 5) );
        buttonPanel.setBorder( new EmptyBorder(338, 233, 0, 0) );

        buttonPanel.setOpaque( false );

        for (int i = 0; i < 6; i++)
        {
            JButton button = new JButton("Button " + i);
            button.setPreferredSize( new Dimension(160, 45) );
            buttonPanel.add(button);
        }

        background.add( buttonPanel );
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

是的,仍然对值进行了一些调整。但是用一个 EmptyBorder 调整整个面板的位置,并且所有按钮同时移动,比单独调整每个按钮的位置更容易。

注意:不要使用 JLabel 来显示图像,因为如果调整框架大小,组件会发生偏移。而是使用您的自定义面板来绘制图像。

【讨论】:

  • 完美谢谢!但是,我对一件事感到困惑。如何命名所有六个按钮不同的名称?每个按钮也使用我的代码上的 actionlistener 打开一个新面板,你能用这个代码为我做 1 个 actionlistener 然后我就能看到你是怎么做到的,剩下的就自己做
  • @NatalieMcKnight,您不需要循环来创建按钮。这只是演示该概念的一个简短示例。在您的代码中,您分别创建按钮并将 ActionListeners 添加到每个按钮。也不要忘记阅读我添加的“注释”。
  • 是的,注意到了。我遇到了另一个小错误,当我单击按钮时,会打开一个新面板,该面板应该包含背景图像,但它不会显示,你能运行我的代码,看看你能不能找出原因?我在上面更新了它
猜你喜欢
  • 1970-01-01
  • 2014-11-22
  • 1970-01-01
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
  • 2011-11-10
  • 1970-01-01
相关资源
最近更新 更多