关于flowlayout工作的困惑

时间:2012-10-25 13:50:43

标签: java swing user-interface layout-manager graphics2d

我开发了一种小型摆动应用,其中上半部分有一个方形旋转,下半部分有一个按钮,可以停止/运行方形旋转。 我使用GridLayout放置旋转方块和按钮。 (另一种方法是使用2 JPanel s,一个使用旋转方形,第二个包含按钮。使用此按钮会显示正确的大小。)

以下是代码: -

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;


public class Rotation {
JButton jbtn=new JButton("Stop");
component jpn2=new component();    //created a JPanel named jpn2 and got a reference to its timer object.
Timer timer=jpn2.timer;
Rotation()
{


    JFrame jfrm=new JFrame("Rotating a square about a center");
    jfrm.setSize(400,400);
    jfrm.setLayout(new GridLayout(2,1));
    jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //JPanel jpnl=new JPanel();

    //jpnl.add(jbtn);

    jbtn.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){
        if(e.getActionCommand().equals("Stop"))
        {
            timer.stop();
            jbtn.setText("Spin");
        }
        if(e.getActionCommand().equals("Spin"))
        {
            timer.start();
            jbtn.setText("Stop");
        }

    }});

    jfrm.add(jpn2);
    jfrm.add(jbtn);

    //jfrm.add(new JButton("Click"));
    jfrm.setVisible(true);
    //jfrm.setOpacity(0.8f);
}
public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException
{
    //JFrame.setDefaultLookAndFeelDecorated(true);
    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    SwingUtilities.invokeLater(new Runnable(){public void run(){new Rotation();}});
}

}

class component extends JPanel implements ActionListener
{
Timer timer;
int theta=0;
component()
{
    timer=new Timer(10,this);
    timer.start();
}
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    Graphics2D g2=(Graphics2D)g;
    g2.rotate(theta,100,100);
    g2.fillRect(50, 50, 100,100);
}
public void actionPerformed(ActionEvent e)
{
    //Changing a global variable and then drawing the rectangle again and hence indirectly the square rotates.
    theta=theta+10;
    if(theta==360)
        theta=0;
    repaint();
}
}

这是输出: -

output

但我的困惑是当我决定使用FlowLayout代替GridLayout时,我只获得了按钮而没有旋转方块。 据我所知,FlowLayout将组件放在一行中,如果空间小于它则使用多行。 任何人都可以解决我目前无法解决的这个小愚蠢的问题。

3 个答案:

答案 0 :(得分:3)

您的问题是您使用setSize(...)这些布局将完全按照您的要求进行操作 - 将GUI的大小设置为该大小,无论一切都没有显示。一般情况下,您希望避免调用setSize(...),而是在必要时让组件覆盖getPreferredSize()并在显示它之前打包GUI,让组件自行调整大小。请注意,FlowLayout有其用途,但与其他布局相比,它不是一堆中最“最聪明”的布局(在我看来)。

答案 1 :(得分:3)

FlowLayout仅接受来自其中PreferredSize的孩子,JComponents无法继续使用其父级

GridLayout(您的问题)从最大和更宽的PreferredSize获取JComponents,并为容器中的其余Dimmension设置相同的JComponentsJComponents可以调整大小,并且可以与父级

连续使用

必须对LayoutManager使用pre_implemented JFrame,使用BorderlayoutJComponents可以调整大小并连续使用它(仅限CENTER区域,仅使用其中一个坐标)

除去

jfrm.setLayout(new GridLayout(2,1));

并改变

jfrm.add(jpn2); 
jfrm.add(jbtn, BorderLayout.SOUTH);

JFrame

的通知
frm.add(jpn2); equals frm.add(jpn2, BorderLayout.CENTER);

答案 2 :(得分:2)

正如其他人所说(+1到mKorbel和HFOE)

  • 问题是您使用setSize(..)而是在将pack()设置为可见之前调用JFrame

  • 您还必须覆盖getPrefferedSize(..)类中的JPanel,它将返回您的方块的大小乘以2(否则当它旋转时它不适合)。

  • 在旁注中不要在main(..)中抛出任何重要的事情。

请参阅下面的代码(使用FlowLayout,但也适用于GridLayout):

使用new FlowLayout()

enter image description here

使用new GridLayout(2,1)

enter image description here

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Rotation {

    JButton jbtn = new JButton("Stop");
    component jpn2 = new component();    //created a JPanel named jpn2 and got a reference to its timer object.
    Timer timer = jpn2.timer;

    Rotation() {


        JFrame jfrm = new JFrame("Rotating a square about a center");

        // jfrm.setLayout(new FlowLayout());
        jfrm.setLayout(new GridLayout(2, 1));

        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jbtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getActionCommand().equals("Stop")) {
                    timer.stop();
                    jbtn.setText("Spin");
                }
                if (e.getActionCommand().equals("Spin")) {
                    timer.start();
                    jbtn.setText("Stop");
                }

            }
        });

        jfrm.add(jpn2);
        jfrm.add(jbtn);

        jfrm.pack();
        jfrm.setVisible(true);
    }

    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {

            ex.printStackTrace();
        }

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Rotation();
            }
        });
    }
}

class component extends JPanel implements ActionListener {

    Timer timer;
    int theta = 0;
    int width = 100, height = 100;

    component() {
        timer = new Timer(10, this);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.rotate(theta, 100, 100);
        g2.fillRect(50, 50, width, height);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(width * 2, height * 2);//multiply by 2 to fit while rotating
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //Changing a global variable and then drawing the rectangle again and hence indirectly the square rotates.
        theta = theta + 10;
        if (theta == 360) {
            theta = 0;
        }
        repaint();
    }
}