dalawh
dalawh

Reputation: 924

Why is the JFrame transparent?

I have a JFrame that is acting up. If I just set the JFrame to visible, then the entire JFrame appears, but if I attempt to do anything after setting the JFrame to visible, then the JFrame will appear, but is transparent with only the title and the close options visible. This is only happening recently and I have no idea what is going on...

Visible JFrame

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

Transparent 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

Code

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);
}

}

Image enter image description here

Upvotes: 1

Views: 493

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

The problem is likely here:

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

By setting a breakpoint in running Swing code, you block the Swing event thread which prevents the GUI from painting or interacting with the user. The work around is to possibly try a different way if you need to debug a GUI as it is running, including using a logger to log the state of the program as it runs.


Edit
You state in comment:

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.

Then the solution is completely different and very simple: Don't use a second JFrame to display this settings display window, but rather you will want to use a modal JDialog or JOptionPane (which really is little more than a specialized modal JDialog).

Why this helps is that Swing has a special mechanism for modal dialogs where it freezes code flow in the calling window starting immediately after setting the dialog visible. And so the calling code will always know when the dialog is no longer visible since its code's program flow will resume only when the dialog isn't visible. So you would want to extract the dialog window's data in the lines immediately following the one that sets the dialog or JOptionPane visible. And before you discard JOptionPanes as being too simplistic, understand that their second parameter, the one of type Object can take any Swing GUI component as a parameter, including a JPanel that holds a very large and complex GUI, making these tools extremely useful.


Edit 2
You state in comment:

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.

I won't get on my soap box about why it's important to avoid using code generation tools until after you understand the underlying library,... but I do recommend that you check to see if the WindowBuilder tool gives you the option of creating a class that extends JPanel. If so, then do that, create your JPanel, and then in the calling code, simply stuff your JPanel into a JOptionPane or modal JDialog.


Edit 3

For instance, say you had a JPanel called GetInfoPanel that allowed the user to enter some text and select a 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;
   }
}

Then a calling class could create an instance of the above and package and display it in a JOptionPane, and then extract the information it contains:

  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);
  }

And you can test this yourself in this program:

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;
   }
}

Upvotes: 5

Related Questions