java.awt.Container.checkNotAWindow error in simple gui - java

I am trying to draw a simple GUI (created with windowbuilder in eclipse), I want to have 2 buttons and a scrollable text area between them. I have created the following code to achieve the above:
public class Main extends JFrame implements ActionListener{
public Font font; //used for the font file
public JTextArea txtDataWillBe;
public Main() throws FontFormatException, IOException{
setTitle("Main title ");
setBounds(100, 100, 1200, 600);
getContentPane().setLayout(null);
txtDataWillBe = new JTextArea();
txtDataWillBe.setText("Your data will display here");
txtDataWillBe.setFont(new Font("Droid Sans", Font.BOLD, 18));
txtDataWillBe.setEditable(false);
txtDataWillBe.setColumns(1);
txtDataWillBe.setBounds(0, 40, 919, 484);
getContentPane().add(txtDataWillBe);
JButton button = new JButton("CLICK TO OPEN");
button.setBounds(0, 0, 940, 40);
button.setFont(new Font("Coalition", Font.PLAIN, 18));
getContentPane().add(button);
JButton btnPrint = new JButton("PRINT");
btnPrint.setBounds(0, 531, 940, 40);
btnPrint.setFont(new Font("Coalition", Font.PLAIN, 18));
getContentPane().add(btnPrint);
}
private final String JTextFile = null;
JFileChooser chooser;
String choosertitle;
public static File deletefile;
EDIT:
public static void main(String s[]) {
JFrame frame = new JFrame("Reader");
Main panel = null;
try {
panel = new Main();
} catch (FontFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
File deleteme = new File (deletefile + "mx.txt");
deleteme.delete();
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
I originally had the JTextarea inside of a JScrollPane (thinking that was the best way to get the scrolling I want working). I removed the JScrollPane thinking that was causing the console error, but I am still getting the error.
Console output is:
Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
at java.awt.Container.checkNotAWindow(Container.java:439)
at java.awt.Container.addImpl(Container.java:1035)
at java.awt.Container.add(Container.java:923)
EDIT: Main added above.
What I am doing wrong with my GUI?
Do I need a JScrollPane and JTextArea to enable vertical scrolling of the loaded text?
Thanks for your help;
Andy
EDIT:
I have edited as per the suggestions below so my code now reads:
public Main() throws FontFormatException, IOException{
JFrame frame = new JFrame("Reader ");
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
File deleteme = new File (deletefile + "mx.txt");
deleteme.delete();
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(getPreferredSize());
frame.setVisible(true);
The rest of the code is as before but all I am getting displayed is a blank grey frame without any of my components (although they are all showing in windowbuilder).
Thanks for the continued help.

The console output is describing exactly what is wrong here.
IllegalArgumentException: adding a window to a container
In the line frame.getContentPane().add(panel,"Center"); you add panel into your content pane, but panel itself is an instance of Main extends JFrame.
You should remove any reference to the outer frame at all and just add the window listener to the Main frame, i.e. the main code reduces to something like
JFrame frame = new Main();
frame.addWindowListener( ... );
frame.setVisible(true);
You may also want to move the addWindowListener part inside class Main.

Related

How to overlap a JPanel(background) and a JTextField

I am creating a log in application for someones graduation, I need several text fields and a background, I have added the background and now need to add the text fields, the problem is that they won't seem to go on top of each other.
I have tried them each separately and without one another they both work perfectly but i can't get them to stack, I have seen several answers on this site to deal with a similar problem but for this application I need to put several text fields on the background as apposed to just one, here is what I have thus far...
//creates the frame with a title as a parameter
JFrame frame = new JFrame("Sign In Sheet");
//sets the size
frame.setSize(1000, 556);
//makes it so the application stops running when you close it
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//puts it in the center of the screen
frame.setLocationRelativeTo(null);
//makes it so you can't resize it
frame.setResizable(false);
//setting the background by looking for the image
try{
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:/Users/Gabriel R. Warner/Desktop/clouds.png")))));
}catch(IOException e){
//and prints an error message if it's not found
System.out.println("well it didn't work");
}
//adding text fields with names apropriate to function
JTextField name1 = new JTextField();
name1.setPreferredSize(new Dimension(200, 15));
name1.setBackground(Color.WHITE);
frame.add(name1);
//makes frame visible
frame.setVisible(true);
Simply stated the text field won't show up with the background and all the results only offer answers for a single text field
The problem is in this line: frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:/Users/Gabriel R. Warner/Desktop/clouds.png")))));
In this line you set a JLabel as the content pane of your JFrame. Then, you frame.add(name1); So you are adding a JTextField to a JLabel...Well this does not seem right, right?
The answer would be to create a new JPanel, add the background image to this panel, set the panel as the content pane of the frame and finally add the textfield to the panel/contentpane.
An example:
#SuppressWarnings("serial")
public class FrameWithBackgroundImage extends JFrame {
public FrameWithBackgroundImage() {
super("Sign In Sheet");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
try {
Image bgImage = loadBackgroundImage();
JPanel backgroundImagePanel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bgImage, 0, 0, null);
}
};
setContentPane(backgroundImagePanel);
} catch (IOException e) {
e.printStackTrace();
}
JTextField textField = new JTextField(10);
add(textField);
}
private Image loadBackgroundImage() throws IOException {
File desktop = new File(System.getProperty("user.home"), "Desktop");
File image = new File(desktop, "img.jpg");
return ImageIO.read(image);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new FrameWithBackgroundImage().setVisible(true);
});
}
}
Preview:
Worth to read question: Simplest way to set image as JPanel background

Moving a JLabel for a game

I am coding a Backgammon game that plays by itself. While the backend code is mostly done, me and my colleague have pretty much no experience in GUI coding. We used the Designer given by a plugin for Eclipse and most of the code was generated.
So here's the thing. Right now there is a JFrame which has a JPanel in which are 2 JLabels, one for the background and one for 1 playing piece (when I figure this out, the rest of them will be added). These are all in an initialize() method which is run through EventQueue.invokeLater(new Runnable()). After the board and the piece are drawn, the startGame() method is called, which finally comes to a method called movePiece(), with the sole purpose of moving that JLabel piece I talked about before.
I have tried mostly everything I can think of, I have scoured the forums and only found people talking about layouts (which I may or may not be using, as I said, generated code) and the darn JLabel won't move when I call setLocation() inside the movePiece() method. It always throws a NullPointerException at that line which is bizarre because the image is already drawn. I will include part of the code below.
I know this will probably look like some of the worse codes ever, but please bear with my lack of skill and help me make this better. Any insights?
public class Main{
public JLabel image1;
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main window = new Main();
window.frame.setVisible(true);
new Main(1);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Main() {
initialize();
}
public Main(int i){
startGame();
}
public void startGame() {
//game code
movePiece(Move.getPos(), Move.getDest());
//rest of code
}
public void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 1023, 617);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setPreferredSize(new Dimension(800, 700));
JPanel panel_1 = new JPanel();
panel_1.setPreferredSize(new Dimension(200, 700));
frame.getContentPane().add(panel_1, BorderLayout.EAST);
JButton btnNewButton = new JButton("Start Game");
/* ACTION LISTENER FOR THE BUTTON */
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
btnNewButton.setFocusable(false);
btnNewButton.setForeground(SystemColor.windowBorder);
btnNewButton.setBackground(SystemColor.menu);
btnNewButton.setVerifyInputWhenFocusTarget(false);
btnNewButton.setRequestFocusEnabled(false);
btnNewButton.setRolloverEnabled(false);
btnNewButton.setFont(new Font("Verdana", Font.PLAIN, 11));
btnNewButton.setDebugGraphicsOptions(DebugGraphics.NONE_OPTION);
/* ADDING THE BTN TO PANEL 1 TO THE RIGHT */
panel_1.add(btnNewButton);
JPanel parentPanel = new JPanel();
parentPanel.setFocusable(false);
parentPanel.setEnabled(false);
parentPanel.setDoubleBuffered(false);
parentPanel.setDebugGraphicsOptions(DebugGraphics.NONE_OPTION);
parentPanel.setIgnoreRepaint(true);
parentPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
parentPanel.setBorder(null);
parentPanel.setPreferredSize(new Dimension(800, 700));
parentPanel.setBackground(SystemColor.menu);
frame.getContentPane().add(parentPanel, BorderLayout.WEST);
/* BACKGAMMON BOARD LABEL-->PANEL */
ImageIcon imageIcon = new ImageIcon(
new ImageIcon("images/bg.png").getImage()
.getScaledInstance(800, 551, Image.SCALE_SMOOTH));
parentPanel.setLayout(null);
ImageIcon imageIcon1 = new ImageIcon(
new ImageIcon("images/pl.png").getImage()
.getScaledInstance(50, 50, Image.SCALE_SMOOTH));
image1 = new JLabel("");
image1.setBounds(37, 36, 50, 50);
parentPanel.add(image1);
image1.setIcon(imageIcon1);
JLabel bg = new JLabel("");
bg.setBounds(10, 11, 800, 551);
bg.setIcon(imageIcon);
parentPanel.add(bg);
}
void movePiece(int pos, int dest) {
//null exception happens here, ignore the arguments
image1.setLocation(37 + 50,36);
}
You create an instance of Main and make it visible...
Main window = new Main();
window.frame.setVisible(true);
You then create a new instance of Main, which, through it's constructor, calls your moviePiece method...
new Main(1);
But the new instance of Main has nothing to do with the previous instance or any of the components which they created.
Instead, trying doing...
window.movePiece(Move.getPos(), Move.getDest());
instead of new Main(1);

JFrame setContentPane hides other components

So I'm going into GUI's in Java, and am trying to create a simple main menu for a timer. All is well until I've attempted to add a background for the GUI. Adding the background works, however all other components are now gone, (the button). How could I fix this?
EDIT: Here is my new code.
public class MainMenu {
// JFrame = the actual menu / frame.
private JFrame frame;
// JLabel = provides text instructions or information on a GUI —
// display a single line of read-only text, an image or both text and an image.
private JLabel background;
// JButton = button.
private JButton alarmClockButton;
// Constructor to create menu
public MainMenu() {
frame = new JFrame("Alarm Clock");
alarmClockButton = new JButton("Timer");
// Add an event to clicking the button.
alarmClockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO: CHANGE TO SOMETHING NICER
JOptionPane.showMessageDialog(null, "This feature hasn't been implemented yet.", "We're sorry!",
JOptionPane.ERROR_MESSAGE);
}
});
// Creating the background
try {
background = new JLabel(new ImageIcon(ImageIO.read(getClass()
.getResourceAsStream("/me/devy/alarm/clock/resources/Background.jpg"))));
} catch (IOException e) {
e.printStackTrace();
}
frame.setLayout(new FlowLayout());
frame.setContentPane(background);
frame.add(alarmClockButton);
frame.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
frame.setVisible(true);
frame.setSize(450, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
alarmClockButton.setForeground(Color.RED);
}
}
Thank you!
frame.setContentPane(background);
You use the label as the content pane. The problem is that the label doesn't use a layout manager by default.
You need to add:
background.setLayout( new BorderLayout() ); // or whatever layout you want
frame.setContentPane(background);
Now you can add the button directly to the frame. You don't need the panel.
Or if you want to get fancy you can use the Background Panel which gives you the option to scale or tile the background image.
Instead of making the ContentPane as JLabel, you can wrap the JLabel in a JPanel, then add this JPanel as the ContentPane :
public class MainMenu {
public static void main(String[] args) {
new MainMenu();
}
// JFrame = the actual menu / frame.
private JFrame frame;
private JPanel panel;
private JPanel bkgPanel;
// JLabel = provides text instructions or information on a GUI —
// display a single line of read-only text, an image or both text and an
// image.
private JLabel background;
// JButton = button.
private JButton alarmClockButton;
// Constructor to create menu
public MainMenu() {
frame = new JFrame("Alarm Clock");
panel = new JPanel();
bkgPanel = new JPanel();
alarmClockButton = new JButton("Timer");
// Add an event to clicking the button.
alarmClockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO: CHANGE TO SOMETHING NICER
JOptionPane.showMessageDialog(null, "This feature hasn't been implemented yet.", "We're sorry!",
JOptionPane.ERROR_MESSAGE);
}
});
// Creating the background
try {
background = new JLabel(new ImageIcon(
ImageIO.read(getClass().getResourceAsStream("/me/devy/alarm/clock/resources/Background.jpg"))));
bkgPanel.add(background);
} catch (IOException e) {
e.printStackTrace();
}
frame.setContentPane(bkgPanel);
frame.add(panel);
panel.add(alarmClockButton);
frame.setVisible(true);
frame.setSize(450, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
alarmClockButton.setForeground(Color.RED);
}
}

Displaying an image, Java

I'm new to Java GUI, and am having issues displaying an image. My intention is to display a large image and allow the user to click on regions of the image to indicate where certain features are located. Anyway, I'm getting a rough start because I can't even get the image to appear, despite reading Oracle's explanation and other solutions.
I've created a JFrame and used its setContentPane() method to add a JPanel and JLabel. I use the setIcon() method of the JLabel to add an image to it, or at least that's my intention...
Any advice is appreciated, especially if there's a better way of doing this. I'll be using OpenCV to process images, and plan to convert them to Java image (or BufferedImage) before displaying them.
Here is the code. I left out the libraries to save space.
public class Pathology {
public static void main(String[] args) {
PrimaryFrame primaryFrame = new PrimaryFrame();
primaryFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
primaryFrame.setSize(1500, 900);
primaryFrame.setVisible( true );
primaryFrame.setContentPane(primaryFrame.getGui());
try {
primaryFrame.setImage(ImageIO.read(new File("C:\\Users\\Benjamin\\Pictures\\Pathology\\C\\001.png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
GUI Class:
public class PrimaryFrame extends JFrame{
//private JTextField textField1;
JPanel gui;
JLabel imageCanvas;
public PrimaryFrame() {
super( "Pathology-1" );
//setLayout(new FlowLayout());
//textField1 = new JTextField("Chup!", 50);
//add(textField1);
}
public void setImage(Image image) {
imageCanvas.setIcon(new ImageIcon(image));
}
public void initComponents() {
if (gui==null) {
gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(5,5,5,5));
imageCanvas = new JLabel();
JPanel imageCenter = new JPanel(new GridBagLayout());
imageCenter.add(imageCanvas);
JScrollPane imageScroll = new JScrollPane(imageCenter);
imageScroll.setPreferredSize(new Dimension(300,100));
gui.add(imageScroll, BorderLayout.CENTER);
}
}
public Container getGui() {
initComponents();
return gui;
}
}
Would you laugh at me if I'd tell you that you just have to put the primaryFrame.setVisible( true ); to the end of the main method? :)
For furture understanding, you don't have to call frame.setVisible(true) every time you want to add/update something in the frame (in an ActionListener, for example). Instead you can call frame.revalidate() and frame.repaint(). (Where frame can be replaced with the particular panel)
You need to setVisible(true) after the call to setImage():
primaryFrame.setImage(ImageIO.read(new
File("C:\\Users\\Benjamin\\Pictures\\Pathology\\C\\001.png")));
because any update to the GUI after setVisible() will not be shown.
That's it and the code should be like this:
public class Pathology {
public static void main(String[] args) {
PrimaryFrame primaryFrame = new PrimaryFrame();
primaryFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
primaryFrame.setSize(1500, 900);
primaryFrame.setContentPane(primaryFrame.getGui());
try {
primaryFrame.setImage(ImageIO.read(new File(
"C:\\Users\\Benjamin\\Pictures\\Pathology\\C\\001.png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
primaryFrame.setVisible( true );
}
}

Block a JDialog when I open another one

I've got a JDialog with a button that opens a new window. What I want to do is to block this JDialog whenever the other window opens. When I say block I mean that the user cannot manipulate it, not move it or maximisize or anything.
By the way, is it recommended to use JDialog for a window with buttons and a table? I stil don't get it when I have to use which frame!
This is what I've got:
public class Platos extends JDialog {
private final JPanel contentPanel = new JPanel();
public static void main(String[] args) {
try {
Platos dialog = new Platos();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public Platos() {
setBounds(100, 100, 450, 300);
getContentPane().setLayout(new BorderLayout());
contentPanel.setLayout(new FlowLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
{
JButton btnAgregarPlato = new JButton("Agregar Plato");
btnAgregarPlato.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
AgregarPlato ap = new AgregarPlato();
ap.setVisible(true);
}
});
btnAgregarPlato.setFont(new Font("Tahoma", Font.PLAIN, 11));
contentPanel.add(btnAgregarPlato);
}
}
}
JDialog is the right choice indeed.
To make it block the parent window, you would have to add a constructor to Platos, which will utilise the JDialog constructor with parent frame:
JDialog dlg = new JDialog(parentWindow, modality);
Where parentWindow is typically a JFrame.
You do it like this:
public Platos(JFrame parent) {
super(parent, ModalityType.APPLICATION_MODAL);
....
The trick is the ModalityType.APPLICATION_MODAL argument, which makes your dialog block all other dialogs and the main frame.
You can pass as parent the main window, it will work just fine even if you are opening the dialog from another one - the last one blocks all the previous ones.
For more reference, see the docs.

Categories