有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么JFrame是透明的?

我的JFrame坏了。如果我只是将JFrame设置为visible,那么整个JFrame就会出现,但如果我在将JFrame设置为visible之后尝试执行任何操作,那么JFrame就会出现,但它是透明的,只有标题和关闭选项可见。这只是最近才发生的事,我不知道发生了什么

可见JFrame

GUI frame = new GUI(); //GUI is a class that extends JFrame
frame.setVisible(true);

透明JFrame

GUI frame = new GUI(); //GUI is a class that extends JFrame
frame.setVisible(true);
frame.setVisible(false); //If I throw a breakpoint here, as soon as it goes from .setVisible(true) to this line, the GUI appears, but is transparent

代码

public class GUI extends JFrame {
private JPanel contentPane;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                GUI frame = new GUI();
                frame.setVisible(true);
                frame.setVisible(false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public GUI() {
    setTitle("Title");
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 330, 250);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);
}

}

图像 enter image description here


共 (1) 个答案

  1. # 1 楼答案

    问题可能在于:

    frame.setVisible(false); // If I throw a breakpoint here, as soon as it goes from 
                             // .setVisible(true) to this line, the GUI appears, 
                             // but is transparent
    

    通过在运行Swing代码时设置断点,可以阻止Swing事件线程,从而阻止GUI绘制或与用户交互。解决方法是,如果需要在GUI运行时对其进行调试,可以尝试不同的方法,包括使用记录器记录程序运行时的状态


    编辑
    你在评论中说:

    I want the user to finish selecting their settings before the applications proceeds forward. So I am not actually using a while(true), but a while(visible). visible is a boolean that is set to false when the user clicks on a button on the gui, which will break out of the loop.

    然后,解决方案就完全不同了,而且非常简单:不要使用第二个JFrame来显示这个设置显示窗口,而是希望使用模式JDialog或JOptionPane(实际上只不过是一个专门的模式JDialog)

    这之所以有帮助,是因为Swing为模式对话框提供了一种特殊机制,在设置对话框可见后,它会立即冻结调用窗口中的代码流。因此,调用代码将始终知道对话框何时不再可见,因为只有当对话框不可见时,其代码的程序流才会恢复。因此,您可能希望在设置对话框或JOptionPane可见的行后面的行中提取对话框窗口的数据。在你认为JOptionPanes过于简单之前,请理解它们的第二个参数,即Object类型的参数可以将任何Swing GUI组件作为参数,包括一个包含非常大和复杂GUI的JPanel,这使得这些工具非常有用


    编辑2
    你在评论中说:

    I am using WindowsBuilder for my GUI related things to make things easier for me. Unfortunately, it doesn't offer the option to use JOptionPane. There are no JDialogue, too. I want to stay on the route that WindowsBuilder will be able to modify.

    在理解底层库之前,我不会讨论为什么避免使用代码生成工具很重要,。。。但我建议您检查WindowBuilder工具是否提供了创建扩展JPanel的类的选项。如果是这样,那么就这样做,创建您的JPanel,然后在调用代码中,只需将您的JPanel填充到JOptionPane或modal JDialog中


    编辑3

    例如,假设您有一个名为GetInfoPanel的JPanel,它允许用户输入一些文本并选择一个JRadioButton:

    class GetInfoPanel extends JPanel {
       public static final String[] COLOR_STRINGS = {"Red", "Green", "Blue", "Orange"};
       private JTextField infoField = new JTextField(10);
       private ButtonGroup buttonGroup = new ButtonGroup();
    
       public GetInfoPanel() {
          JPanel topPanel = new JPanel();
          topPanel.add(new JLabel("Information that you want to submit:"));
          topPanel.add(infoField);
    
          JPanel colorPanel = new JPanel(new GridLayout(1, 0, 5, 0));
          for (String colorString : COLOR_STRINGS) {
             JRadioButton radioButton = new JRadioButton(colorString);
             radioButton.setActionCommand(colorString);
             buttonGroup.add(radioButton);
             colorPanel.add(radioButton);
          }
    
    
          setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
          add(topPanel);
          add(colorPanel);
       }
    
       public String getInfo() {
          return infoField.getText();
       }
    
       public String getColorString() {
          String selection = "";
          ButtonModel model = buttonGroup.getSelection();
          if (model != null) {
             selection = model.getActionCommand();
          }
    
          return selection;
       }
    }
    

    然后,调用类可以创建上面的实例,并将其打包并显示在JOptionPane中,然后提取其中包含的信息:

      public void actionPerformed(ActionEvent e) {
         // create our GetInfoPanel
         GetInfoPanel getInfoPanel = new GetInfoPanel();
    
         // display it in a JOptionPane which is a modal JDialog
         JOptionPane.showMessageDialog(TestGetInfo.this, getInfoPanel,
               "Enter Information Please", JOptionPane.PLAIN_MESSAGE);
    
         // this code will not be called until the dialog above is no longer visible
         // extract the text from the getInfoPanel's text field 
         String info = getInfoPanel.getInfo();
         infoDisplayField.setText(info);
    
         // extract the the radiobutton selection from the getInfoPanel
         String colorString = getInfoPanel.getColorString();
         colorStringField.setText(colorString);
      }
    

    你可以在这个程序中自己测试:

    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class TestGetInfo extends JPanel {
       private JTextField infoDisplayField = new JTextField(10);
       private JTextField colorStringField = new JTextField(10);
       private JButton displayGetInfoBtn = new JButton(new DisplayGetInfoAction(
             "Get Info"));
    
       public TestGetInfo() {
          infoDisplayField.setFocusable(false);
          colorStringField.setFocusable(false);
    
          add(new JLabel("Info:"));
          add(infoDisplayField);
          add(Box.createHorizontalStrut(10));
          add(new JLabel("Color:"));
          add(colorStringField);
          add(Box.createHorizontalStrut(10));
          add(displayGetInfoBtn);
       }
    
       private class DisplayGetInfoAction extends AbstractAction {
          public DisplayGetInfoAction(String name) {
             // this will be the button's text:
             super(name);
          }
    
          @Override
          public void actionPerformed(ActionEvent e) {
             // create our GetInfoPanel
             GetInfoPanel getInfoPanel = new GetInfoPanel();
    
             // display it in a JOptionPane which is a modal JDialog
             JOptionPane.showMessageDialog(TestGetInfo.this, getInfoPanel,
                   "Enter Information Please", JOptionPane.PLAIN_MESSAGE);
    
             // this code will not be called until the dialog above is no longer visible
             // extract the text from the getInfoPanel's text field 
             String info = getInfoPanel.getInfo();
             infoDisplayField.setText(info);
    
             // extract the the radiobutton selection from the getInfoPanel
             String colorString = getInfoPanel.getColorString();
             colorStringField.setText(colorString);
          }
       }
    
       private static void createAndShowGui() {
          TestGetInfo mainPanel = new TestGetInfo();
    
          JFrame frame = new JFrame("TestGetInfo");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    @SuppressWarnings("serial")
    class GetInfoPanel extends JPanel {
       public static final String[] COLOR_STRINGS = {"Red", "Green", "Blue", "Orange"};
       private JTextField infoField = new JTextField(10);
       private ButtonGroup buttonGroup = new ButtonGroup();
    
       public GetInfoPanel() {
          JPanel topPanel = new JPanel();
          topPanel.add(new JLabel("Information that you want to submit:"));
          topPanel.add(infoField);
    
          JPanel colorPanel = new JPanel(new GridLayout(1, 0, 5, 0));
          for (String colorString : COLOR_STRINGS) {
             JRadioButton radioButton = new JRadioButton(colorString);
             radioButton.setActionCommand(colorString);
             buttonGroup.add(radioButton);
             colorPanel.add(radioButton);
          }
    
    
          setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
          add(topPanel);
          add(colorPanel);
       }
    
       public String getInfo() {
          return infoField.getText();
       }
    
       public String getColorString() {
          String selection = "";
          ButtonModel model = buttonGroup.getSelection();
          if (model != null) {
             selection = model.getActionCommand();
          }
    
          return selection;
       }
    }