调整框架大小Java上的组件大小

时间:2012-10-23 23:15:37

标签: java swing user-interface resize gridbaglayout

当我调整GUI大小时,我在尝试调整GUI中的组件时遇到了一些麻烦。现在,当我调整GUI的大小时,组件的大小不会改变,它们会保持我设置的静态大小。当我调整GUI大小时,通过显示它们所需的最小大小,它们将不再显示。我希望它们在调整GUI大小时调整大小并保持宽高比。

以下是我对GUI的代码:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.*;
import java.net.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.text.*;
import javax.swing.text.html.*;

public class DraftGUI implements MouseListener {

private JPanel jpPack;
private JPanel jpCards;
private JPanel jpInfo;
private JPanel jpChat;
private TextField tf;
private StyledDocument doc;
private JTextPane tp;
private JScrollPane sp;

public void mousePressed(MouseEvent e) {
}

public void mouseReleased(MouseEvent e) {
}

public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

public void mouseClicked(MouseEvent e) {
    e.getComponent().setVisible(false);
}

private Client client;


public GUI(Client client) throws IOException {

    JFrame frame = new JFrame("Draft");

    //set the size to fullscreen to start
    frame.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);

    //set the content pane, we'll add everything to it and then add it to the frame
    JPanel contentPane = new JPanel();
    contentPane.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
    contentPane.setLayout(new GridBagLayout());

    //creates some panels with some default values for now
    JPanel jpCards = new JPanel(new BorderLayout());
    jpCards.setOpaque(true); //ensures it paints every pixel
    jpCards.setBackground(Color.BLUE);

    JPanel jpInfo = new JPanel();
    jpInfo.setOpaque(true);
    jpInfo.setBackground(Color.GREEN);

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

    //grab some info to make the JTextPane and make it scroll
    this.client = client;
    tf = new TextField();
    doc = new DefaultStyledDocument();
    tp = new JTextPane(doc);
    tp.setEditable(false);
    tf.addActionListener(this.client);
    sp = new JScrollPane(tp);

    //adding the quantities to the chat panel
    JPanel jpChat = new JPanel();
    jpChat.setLayout(new BorderLayout());
    jpChat.add("North", tf);
    jpChat.add("Center", sp);

    //a new GridBagConstraints used to set the properties/location of the panels
    GridBagConstraints c = new GridBagConstraints(); 

    //adding some panels to the content pane
    //set it to start from the top left of the quadrant if it's too small
    c.anchor = GridBagConstraints.FIRST_LINE_START; 
    c.fill = GridBagConstraints.BOTH; //set it to fill both vertically and horizontally
    c.gridx = 0; //set it to quadrant x=0 and
    c.gridy = 0; //set it to quadrant y=0
    c.weightx = 0.7;
    c.weighty = 0.3;
    contentPane.add(jpCards, c);

    c.gridx = 1;
    c.gridy = 0;
    c.weightx = 0.3;
    c.weighty = 0.3;
    contentPane.add(jpInfo, c);

    c.gridx = 0;
    c.gridy = 1;
    c.weightx = 0.7;
    c.weighty = 0.7;
    contentPane.add(jpPack, c);

    c.gridx = 1;
    c.gridy = 1;
    c.weightx = 0.3;
    c.weighty = 0.7;
    contentPane.add(jpChat, c);

    //set some necessary values 
    frame.setContentPane(contentPane);
    frame.setLocationByPlatform(true);
    frame.setVisible(true);

    //This code works for adding an Image
    //need to learn how to specify a path not dependent on the specific users's machine
    //this is not a high priority for now though
    GridBagConstraints d = new GridBagConstraints();
    d.gridx = 0;
    d.gridy = 0;

    ImageLabel imageLabel1 = new ImageLabel("path-to-file");

    imageLabel1.setPreferredSize(new Dimension(223, 310));
    jpPack.add(imageLabel1, d);

    ImageLabel imageLabel2 = new ImageLabel("path-to-file");
    imageLabel2.setPreferredSize(new Dimension(223, 310));
    ImageLabel imageLabel3 = new ImageLabel("path-to-file");
    imageLabel3.setPreferredSize(new Dimension(223, 310));
    d.gridx = 1;
    jpPack.add(imageLabel2, d);
    d.gridy = 1;
    jpPack.add(imageLabel3, d);

    imageLabel1.addMouseListener(this);
    imageLabel2.addMouseListener(this);
    imageLabel3.addMouseListener(this);

    //223, 310 are the aspect values for a card image, width, height
    //these need to be maintained as the GUI size changes

    }

}


class ImageLabel extends JLabel {
   Image image;
   ImageObserver imageObserver; 

   // constructor with filename     
   ImageLabel(String filename) {
      ImageIcon icon = new ImageIcon(filename);
      image = icon.getImage();
      imageObserver = icon.getImageObserver();
   }

   // constructor with icon
   ImageLabel(ImageIcon icon) {
      image = icon.getImage();
      imageObserver = icon.getImageObserver();
   }

   // overload setIcon method
   void setIcon(ImageIcon icon) {
      image = icon.getImage();
      imageObserver = icon.getImageObserver();
   }

   // overload paint()
   public void paint( Graphics g ) {
       super.paint( g );
       g.drawImage(image,  0 , 0 , getWidth() , getHeight() , imageObserver);

   }

}

由于某些原因,帧的组件没有默认的resizing属性,因此当帧调整大小时,组件不会执行任何操作。我不确定我做错了什么或错过了什么,但显然我遗漏了一些东西。

此外,如果有人知道,ImageLabels会占用额外的空间。填充默认设置为0,所以我不确定它为什么会像它们周围的边框那样创建。

感谢。

Guillaume的编辑:

我知道如果我想将它作为一个独立的程序运行它是必要的,它当前是另一个应用程序的一部分,并在其中单独调用。如果没有主要的完整性,发布它可能不是最好的决定,但无论如何,这不是一个大问题。

您的代码取出了实际显示图片的部分。 “path-to-file”应该被实际的图像文件路径替换,因此您将显示图像。当它只是那里的文本时,很难真正看到手头的问题。

如果图像显示正确,并且您尝试调整整个GUI的大小,您会注意到图像不会缩小。它保持其首选尺寸,并且当它变得小于它时会出现问题。在我的代码中,当它无法显示至少首选大小时,它会完全停止显示图片。在您的代码中,它会在缩小时切断部分图片。

我想要的是它实际调整包含图片的JLabel的大小,以便在GUI调整大小时,图像也会调整大小。对于我的程序,图像必须相应缩小。用户最终将具有基于单击图像的功能,因此仅显示一些图像或部分图像根本不会。

请再次尝试您的代码/我的代码并重现我遇到的问题,测试图片,以便我们找到正确的解决方案。感谢。

1 个答案:

答案 0 :(得分:4)

  1. JFrame.setVisible(true)应该是您拨打的最后一行。
  2. GridBagLayout可以根据框架大小调整组件的大小,只要您使用weightx/weightyfill
  3. 更新:

    1. 忘记设置首选大小,这只是走向GUI问题的路径
    2. 如果您使用LayoutManager(并且这是一个非常好的主意),忘记调用setSize()/ setBounds()/ setLocation(),无论如何,LayoutManager都会覆盖它们
    3. 您需要注意调整图像大小以保持原始图像比例
    4. 如果你使用weightx / weighty,你还应该使用anchor和/或fill
    5. 使用frame.pack()正确调整框架尺寸
    6. 使用setExtendedState()最大化框架
    7. 顺便说一下,SSCCE表示您为其他人制作了一个可运行的示例,这包括将图像的本地路径更改为在线URL(参见下面的示例)。

      使用以下代码段,一切似乎都可以正常运行:

      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.Dimension;
      import java.awt.Graphics;
      import java.awt.GridBagConstraints;
      import java.awt.GridBagLayout;
      import java.awt.TextField;
      import java.awt.event.MouseEvent;
      import java.awt.event.MouseListener;
      import java.net.MalformedURLException;
      import java.net.URL;
      
      import javax.swing.ImageIcon;
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.JScrollPane;
      import javax.swing.JTextPane;
      import javax.swing.SwingUtilities;
      import javax.swing.text.DefaultStyledDocument;
      import javax.swing.text.StyledDocument;
      
      public class DraftGUI implements MouseListener {
      
          private static final String IMAGE_URL = "http://images.paramountbusinessjets.com/space/spaceshuttle.jpg";
          private JPanel jpPack;
          private JPanel jpCards;
          private JPanel jpInfo;
          private JPanel jpChat;
          private TextField tf;
          private StyledDocument doc;
          private JTextPane tp;
          private JScrollPane sp;
      
          @Override
          public void mousePressed(MouseEvent e) {
          }
      
          @Override
          public void mouseReleased(MouseEvent e) {
          }
      
          @Override
          public void mouseEntered(MouseEvent e) {
          }
      
          @Override
          public void mouseExited(MouseEvent e) {
          }
      
          @Override
          public void mouseClicked(MouseEvent e) {
          }
      
          public DraftGUI() throws MalformedURLException {
      
              final JFrame frame = new JFrame("Draft");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              // set the content pane, we'll add everything to it and then add it to the frame
              JPanel contentPane = new JPanel();
              contentPane.setLayout(new GridBagLayout());
      
              // creates some panels with some default values for now
              JPanel jpCards = new JPanel(new BorderLayout());
              jpCards.setBackground(Color.BLUE);
      
              JPanel jpInfo = new JPanel();
              jpInfo.setBackground(Color.GREEN);
      
              JPanel jpPack = new JPanel(new GridBagLayout());
              jpPack.setBackground(Color.RED);
      
              // grab some info to make the JTextPane and make it scroll
              tf = new TextField();
              doc = new DefaultStyledDocument();
              tp = new JTextPane(doc);
              tp.setEditable(false);
              sp = new JScrollPane(tp);
      
              // adding the quantities to the chat panel
              JPanel jpChat = new JPanel();
              jpChat.setLayout(new BorderLayout());
              jpChat.add("North", tf);
              jpChat.add("Center", sp);
      
              // a new GridBagConstraints used to set the properties/location of the panels
              GridBagConstraints c = new GridBagConstraints();
      
              // adding some panels to the content pane
              // set it to start from the top left of the quadrant if it's too small
              c.anchor = GridBagConstraints.FIRST_LINE_START;
              c.fill = GridBagConstraints.BOTH; // set it to fill both vertically and horizontally
              c.gridx = 0; // set it to quadrant x=0 and
              c.gridy = 0; // set it to quadrant y=0
              c.weightx = 0.7;
              c.weighty = 0.3;
              contentPane.add(jpCards, c);
      
              c.gridx = 1;
              c.gridy = 0;
              c.weightx = 0.3;
              c.weighty = 0.3;
              contentPane.add(jpInfo, c);
      
              c.gridx = 0;
              c.gridy = 1;
              c.weightx = 0.7;
              c.weighty = 0.7;
              contentPane.add(jpPack, c);
      
              c.gridx = 1;
              c.gridy = 1;
              c.weightx = 0.3;
              c.weighty = 0.7;
              contentPane.add(jpChat, c);
      
              // set some necessary values
              frame.setContentPane(contentPane);
              frame.setLocationByPlatform(true);
      
              // This code works for adding an Image
              // need to learn how to specify a path not dependent on the specific users's machine
              // this is not a high priority for now though
              GridBagConstraints d = new GridBagConstraints();
              d.weightx = 1.0;
              d.weighty = 1.0;
              d.fill = GridBagConstraints.BOTH;
              d.gridx = 0;
              d.gridy = 0;
              ImageLabel imageLabel1 = new ImageLabel(new ImageIcon(new URL(IMAGE_URL)));
              jpPack.add(imageLabel1, d);
              ImageLabel imageLabel2 = new ImageLabel(new ImageIcon(new URL(IMAGE_URL)));
              d.gridx++;
              jpPack.add(imageLabel2, d);
      
              ImageLabel imageLabel3 = new ImageLabel(new ImageIcon(new URL(IMAGE_URL)));
              d.gridy++;
              jpPack.add(imageLabel3, d);
      
              imageLabel1.addMouseListener(this);
              imageLabel2.addMouseListener(this);
              imageLabel3.addMouseListener(this);
              frame.pack();
              // 223, 310 are the aspect values for a card image, width, height
              // these need to be maintained as the GUI size changes
                  frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
              frame.setVisible(true);
          }
      
          public static void main(String[] args) {
              SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          new DraftGUI();
                      } catch (MalformedURLException e) {
                          e.printStackTrace();
                      }
                  }
              });
          }
      
          public static class ImageLabel extends JPanel {
              private static int counter = 1;
              private ImageIcon icon;
              private int id = counter++;
      
              public ImageLabel(ImageIcon icon) {
                  super();
                  setOpaque(false);
                  this.icon = icon;
              }
      
              @Override
              public Dimension getPreferredSize() {
                  return new Dimension(icon.getIconWidth(), icon.getIconHeight());
              }
      
              @Override
              protected void paintComponent(Graphics g) {
                  super.paintComponent(g);
                  double zoom = Math.min((double) getWidth() / icon.getIconWidth(), (double) getHeight() / icon.getIconHeight());
                  int width = (int) (zoom * icon.getIconWidth());
                  int height = (int) (zoom * icon.getIconHeight());
                  g.drawImage(icon.getImage(), (getWidth() - width) / 2, (getHeight() - height) / 2, width, height, this);
                  g.setFont(g.getFont().deriveFont(36.0f));
                  g.drawString(String.valueOf(id), getWidth() / 2, getHeight() / 2);
              }
          }
      }