Missing JPanel in JLayeredPane - java

I was working on an overlay for a JPanel but I have a slight problem, the transparency of the overlay sees straight through to the JFrame.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class GUI extends JFrame {
private GUI() {
super("Recorder Part");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JLayeredPane layers = new Overlay();
add(layers);
pack();
getContentPane().setBackground(Color.GREEN);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new GUI());
}
private class Overlay extends JLayeredPane {
JPanel base;
JPanel overlay;
private Overlay() {
setPreferredSize(new Dimension(800, 100));
createBase();
createOverlay();
add(base, new Integer(0));
add(overlay, new Integer(1));
}
private void createBase() {
base = new JPanel();
base.setPreferredSize(new Dimension(800, 100));
base.setBounds(0, 0, 800, 100);
base.setBackground(Color.BLUE);
base.setOpaque(true);
base.add(new JLabel("Hello"));
}
private void createOverlay() {
overlay = new JPanel();
overlay.setPreferredSize(new Dimension(800, 100));
overlay.setBounds(0, 0, 800, 100);
overlay.setBackground(new Color(255, 0, 0, 0));
}
}
}
How can I fix this so that when the JPanel called overlay is transparent, the Jpanel called base can be seen and not the JFrame?
Edit
I found that this problem only occurs when the overlay panel has one dimension that is greater than or equal to the dimensions of the base panel. This can be seen by adjusting the size of the frame in this example.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class GUI extends JFrame {
private GUI() {
super("Recorder Part");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JLayeredPane layers = new Overlay();
add(layers);
pack();
getContentPane().setBackground(Color.GREEN);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new GUI());
}
private class Overlay extends JLayeredPane {
JPanel base;
JPanel overlay;
private Overlay() {
addComponentListener(new Resize());
setPreferredSize(new Dimension(800, 100));
createBase();
createOverlay();
add(base, new Integer(0));
add(overlay, new Integer(1));
}
private void createBase() {
base = new JPanel();
base.setLocation(0, 0);
base.setBackground(Color.BLUE);
base.setOpaque(true);
base.add(new JLabel("Hello"));
}
private void createOverlay() {
overlay = new JPanel();
overlay.setLocation(0, 0);
overlay.setSize(new Dimension(800, 100));
overlay.setBackground(new Color(255, 0, 0, 128));
}
private class Resize extends ComponentAdapter {
#Override
public void componentResized(ComponentEvent e) {
System.out.println("Resized");
base.setSize(new Dimension(getParent().getWidth(), getParent().getHeight()));
}
}
}
}
This is undesirable as the overlay panel needs to be the exact same size of the base panel. I would appreciate any help.

I have the felling that this is a bug. Change the bounds so it doesn't fully overlap the base to o see what happens:
overlay.setBounds(0, 0, 799, 100); // or (1, 0, 800, 100)
probably some kind of optimization, like ignoring a component if it is being completely obscured by another component, but without considering transparency in that optimization [:-|
EDIT:
that is definitively the problem - paintChildren of JComponent does some kind of optimization based on children being totally obscured by other children.
I found two solutions, the first one is probably the correct one- set the overlay to non-opaque:
overlay.setOpaque(false);
this has the drawback that the background color is not being used at all.
Second is more a workarround - make the JLayeredPane return true for optimizedDrawingEnabled, this will stop the JComponent from doing it:
private class Overlay extends JLayeredPane {
/// ...
#Override
public boolean isOptimizedDrawingEnabled() {
return true;
}
}
but not sure what may stop working by doing that, so I would prefer the first solution!

Related

How to wait until JDialog is fully created

I need to calculate window decorations somehow. So I override JDialog's constructor. But when I call get_decoration_size() it sometimes returns wrong values. And my thought was: window creates later than get_decoration_size() executes(strange, because both in same thread and in same constructor). So I decided to sleep for a second, and it worked, and now decorations always valid.
My question is: is there a way to "join" to the creating process(wait until window is shown by setVisible(true))? If so, it must be something to replace unsafe_sleep(1000).
package swing.window;
import db.db;
import javax.swing.*;
import java.awt.*;
import static swing.util.*;
import static util.util.unsafe_sleep;
public class calc_decor extends JDialog {
{
//some initializations
setLayout(null);
setResizable(false);
JLabel label = new JLabel("Loading...");
add(label);
setxy(label, 3, 3);
fit(label);
setsize(this, label.getWidth() + 100, label.getHeight() + 100);
window_to_center(this);
setVisible(true);//trying to draw
unsafe_sleep(1000);//without that it looks like get_decoratoin_size()
//is called before setVisible(true)
db.sysdecor = get_decoration_size();//trying to get decorations
dispose();
}
private Dimension get_decoration_size() {
Rectangle window = getBounds();
Rectangle content = getContentPane().getBounds();
int width = window.width - content.width;
int height = window.height - content.height;
return new Dimension(width, height);
}
}
I had to assume a lot to create a runnable example.
Here's the result of your getDecorationSize method. The line didn't print until I closed the JDialog.
java.awt.Dimension[width=16,height=39]
And here's the code I used.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JDialogTest implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JDialogTest());
}
private JFrame frame;
#Override
public void run() {
frame = new JFrame("JDialog Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(
150, 100, 150, 100));
panel.setPreferredSize(new Dimension(400, 400));
JButton button = new JButton("Open JDialog");
button.addActionListener(new ButtonListener());
panel.add(button);
return panel;
}
public class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
new CalculateDecor(frame, "Spash Screen");
}
}
public class CalculateDecor extends JDialog {
private static final long serialVersionUID = 1L;
public CalculateDecor(JFrame frame, String title) {
super(frame, true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle(title);
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(200, 200));
JLabel label = new JLabel("Loading...");
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label);
add(panel);
pack();
setLocationRelativeTo(frame);
setVisible(true);
System.out.println(getDecorationSize());
}
private Dimension getDecorationSize() {
Rectangle window = getBounds();
Rectangle content = getContentPane().getBounds();
int width = window.width - content.width;
int height = window.height - content.height;
return new Dimension(width, height);
}
}
}

Cant paint on JFrame

I am having a problem drawing a JLabel on my JFrame. I already did that in another project and it was working properly, but i messed up somewhere this time and cant draw anymore. Here is my Code:
Board:
import javax.swing.*;
import java.awt.*;
public class Board extends JPanel {
public Board() {
initBoard();
}
private void initBoard() {
setPreferredSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
setMinimumSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
setMaximumSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
setBackground(Color.GRAY);
setDoubleBuffered(true);
}
}
Frame:
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.io.File;
import java.io.IOException;
public class Frame extends JFrame {
public static final int GAME_WIDTH = 800;
public static final int GAME_HEIGHT = 600;
private final String title = "title here";
private Image backgroundIMG;
public Frame() {
initUI();
}
private void initUI() {
add(new Board());
pack();
setTitle(title);
setSize(GAME_WIDTH, GAME_HEIGHT);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setLayout(null);
/*
* set background image
*/
/*try {
this.backgroundIMG = ImageIO.read(new File("src/to/image"));
} catch (IOException e) {
e.printStackTrace();
}*/
Border emptyBorder = BorderFactory.createEmptyBorder();
int titleWidth = 270;
int titleHeight = 55;
int titleX = 24;
int titleY = 30;
int titleSize = 47;
String titleFont = "Ravie";
/*
* Customize the startscreen
*/
JLabel title = new JLabel("text");
title.setBounds(0, 0, titleWidth, titleHeight);
title.setFont(new Font(titleFont, Font.BOLD, titleSize));
title.setForeground(new Color(251,102,8));
title.setLocation(titleX, titleY);
add(title);
System.out.println("title should be printed");
}
}
Launcher:
import java.awt.*;
public class Launcher {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
Frame main = new Frame();
main.setVisible(true);
});
}
}
When i start the program, the Frame is loading up but does not display the JLabel. Its also printing "title should be printed" on the console. I did some research already but wasnt able to find anything that helped me. Maybe its just a trivial error and someone can help me out real quick.
Thanks in advance
Getting past all the, "interesting" stuff for moment, you're basic problem comes down to this...
add(new Board());
//...
add(title);
Java/Swing paint's it's component in LIFO order, so the last component added, is the first component painted.
Probably the most logical fix is to add title to the Board, but you might want to fix a couple of other issues first...
Avoid extending from top level containers like JFrame. Lots of reasons, but mostly, you're not adding new functionality to the class and it's locking you into a single use case which can be better managed through other means/components
Avoid setPreferred/Minimum/MaximumSize. These are more trouble then they are worth. Instead, as required, override getPreferredSize
setDoubleBuffered(true); is pointless, as Swing components are double buffered by default
Avoid null layouts, seriously, this is the number one cause of most of the issues people post about on SO. The layout management API is there for a reason, learn to make use of it.
If we take all that into account, you might end up within something more like...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Image;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
private final String title = "title here";
public Test() {
EventQueue.invokeLater(() -> {
JFrame main = new JFrame(title);
main.add(new MainPane());
main.pack();
main.setLocationRelativeTo(null);
main.setVisible(true);
});
}
public static final int GAME_WIDTH = 800;
public static final int GAME_HEIGHT = 600;
public static class MainPane extends JPanel {
private Image backgroundIMG;
public MainPane() {
setLayout(new BorderLayout());
setBackground(Color.GRAY);
add(new Board());
String titleFont = "Ravie";
int titleSize = 47;
JLabel title = new JLabel("text");
title.setHorizontalAlignment(JLabel.CENTER);
title.setFont(new Font(titleFont, Font.BOLD, titleSize));
title.setForeground(new Color(251, 102, 8));
add(title, BorderLayout.NORTH);
}
}
public static class Board extends JPanel {
public Board() {
initBoard();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(GAME_WIDTH, GAME_HEIGHT);
}
private void initBoard() {
setBackground(Color.GRAY);
}
}
}

Java Swing CardLayout multiple files

I am trying to get this code to work, such that I have a cardlayout container and each panel be defined in its own class and actual file. This code is not 100% my own and is a modified version of my previous stuff by another Stack overflow user. It is more or less what I need, but I need it such that it isn't automated and I can write 15 different panels with decisions made inside each one. The Main and Arrow class was modified by said user, and Imagepanel is my attempt to write a class that will be accepted by the working part of the code. The issue is the Imagepanel I insert into the container will register as existing, but nothing shows up on the panel, it's blank. The commented out portion in ImagePanel is my code that I set on the back burner in favor of the established stuff previously used in the Arrow class.
Here is the Main class
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.*;
import javax.swing.*;
public class Main extends JPanel {
private Arrow arrow = new Arrow(); //creates a new Arrow object
public Main() {
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(new NextAction("Next")));
setLayout(new BorderLayout());
add(arrow, BorderLayout.NORTH);
add(btnPanel, BorderLayout.PAGE_END);
}
private class NextAction extends AbstractAction {
public NextAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
arrow.next(); // *** call arrow's public next method that you created
// no need to make a new CardLayout instance
}
}
private static void createAndShowGui() {
Main mainPanel = new Main();
JFrame frame = new JFrame("Iowa Budget Simulation");
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(() -> createAndShowGui());
}
}
Here is the Arrow class where the container is created
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.*;
class Arrow extends JPanel {
private static final long serialVersionUID = 1L;
private CardLayout cardLayout = new CardLayout(); // make me a field
private JPanel cardHolder = new JPanel(cardLayout); //creates a master JPanel
public Arrow() {
for (int i = 0; i < 5; i++) {
cardHolder.add(createCard(i), "card " + i);
}
ImagePanel pear = new ImagePanel();
cardHolder.add(pear, "Pear");
setLayout(new BorderLayout());
add(cardHolder, BorderLayout.NORTH);
}
// public method that other objects can call
public void next() {
cardLayout.next(cardHolder); // call next on the correct object
}
// simply creates a "pretty" new JPanel
private JComponent createCard(int i) {
JLabel label = new JLabel("Card " + i);
label.setFont(label.getFont().deriveFont(Font.BOLD, 50f));
float h = (float)Math.random();
Color c = Color.getHSBColor(h, 1f, 1f);
label.setForeground(c.darker());
JPanel panel = new JPanel(new GridBagLayout());
panel.add(label);
panel.setBorder(BorderFactory.createLineBorder(c.darker(), 20));
panel.setBackground(c.brighter().brighter());
panel.setPreferredSize(new Dimension(400, 300));
return panel;
}
Here is ImagePanel, my attempt at a 3rd, individual panel/class
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.*;
class ImagePanel extends JPanel {
private static final long serialVersionUID = 1L;
private String imgString;
private JLabel imgLabel;
public JComponent ImagePanel() {
/*
setName("Pear");
JLabel john = new JLabel("Pear");
float h = (float)Math.random();
Color c = Color.getHSBColor(h, 1f, 1f);
john.setForeground(c.darker());
JPanel panel = new JPanel(new GridBagLayout());
panel.add(john);
panel.setBorder(BorderFactory.createLineBorder(c.darker(), 20));
panel.setBackground(c.brighter().brighter());
// Ensure size is correct even before any image is loaded.
setPreferredSize(new Dimension(400, 300));
return panel;
*/
JLabel label = new JLabel("Pear");
label.setFont(label.getFont().deriveFont(Font.BOLD, 50f));
float h = (float)Math.random();
Color c = Color.getHSBColor(h, 1f, 1f);
label.setForeground(c.darker());
JPanel panel = new JPanel(new GridBagLayout());
panel.add(label);
panel.setBorder(BorderFactory.createLineBorder(c.darker(), 20));
panel.setBackground(c.brighter().brighter());
panel.setPreferredSize(new Dimension(400, 300));
return panel;
}
There is no error to post, it simply displays a blank panel. Thank you for any assistance I might receive, and I apologize in advance as I am learning Java Swing GUI through YouTube and stack overflow.
public JComponent ImagePanel() { isn't a constructor, it's a method, to make it work in your code you would have to change ImagePanel pear = new ImagePanel(); to JComponent pear = new ImagePanel().ImagePanel();, but frankly that just doesn't make much sense.
Instead, change public JComponent ImagePanel() { to public ImagePanel() {, now it's the class's constructor
Next, change...
JPanel panel = new JPanel(new GridBagLayout());
panel.add(label);
panel.setBorder(BorderFactory.createLineBorder(c.darker(), 20));
panel.setBackground(c.brighter().brighter());
panel.setPreferredSize(new Dimension(400, 300));
return panel;
to
setLayout(new GridBagLayout());
add(label);
setBorder(BorderFactory.createLineBorder(c.darker(), 20));
setBackground(c.brighter().brighter());
//panel.setPreferredSize(new Dimension(400, 300));
//return panel;
Don't get me started on why setPreferredSize is a bad idea
Now you can simply use
ImagePanel pear = new ImagePanel();
cardHolder.add(pear, "Pear");

JPanel transition, what is wrong with my code?

I am new to java, and learning new things everyday.
Today i stumbled upon an error i just can not get fixed.
So i've got a JFrame with a JPanel inside, now I want to remove the Jpanel when i click on my Start game JLabel, and make it transition into my game JPanel ( for now i use a test JPanel)
JFrame class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MainMenu extends JFrame {
JPanel panel;
JFrame frame;
JButton playlabel;
public void mainmenu() {
frame = new JFrame();
panel = new JPanel();
playlabel = new JButton ("Nieuw Spel");
//frame
frame.setSize(new Dimension(800, 600));
frame.getContentPane().setBackground(new Color(14,36,69));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(frame.getMinimumSize());
frame.setVisible(true);
//panel
Dimension expectedDimension = new Dimension(690, 540);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setPreferredSize(expectedDimension);
panel.setMaximumSize(expectedDimension);
panel.setMinimumSize(expectedDimension);
panel.setBackground(new Color(14, 36, 69));
panel.add(playlabel);
playlabel.setAlignmentX(JComponent.CENTER_ALIGNMENT);
//playlabel
playlabel.setFont(new Font("Old English Text MT", Font.BOLD, 40));
playlabel.setBounds(250, 350, 50, 20);
playlabel.setForeground(new Color(217,144,39));
playlabel.setBackground(new Color(14,36,69));
playlabel.setBorderPainted(false);
playlabel.setFocusPainted(false);
playlabel.addActionListener(new PlayListener());
}
private class PlayListener extends JFrame implements ActionListener {
public void actionPerformed(ActionEvent e) {
JPanel panelgame = Game.Game();
this.remove(panel);
this.add(panelgame);
this.revalidate();
}
}
}
Game class:
package labyrinthproject.View;
import java.awt.Color;
import javax.swing.JPanel;
public class Game {
public static JPanel Game(){
JPanel panel = new JPanel();
panel.setSize(690, 540);
panel.setBackground(new Color(255,36,69));
return panel;
}
}
if anyone could explain this to me why this doesn't work, it would be greatly appreciated!
Thank you very much!
Sincerely,
A beginner java student.
There are quite some issues in your code
Create the GUI on the event dispatch thread
Don't extend JFrame (you have three (three!) JFrames floating around there!)
Follow the naming conventions
Don't overuse static methods
Only store the instance variables that you really need to represent your class state
Don't use manual setSize or setBounds calls. Use a LayoutManager instead
The call to frame.setVisible(true) should be the last call, after the frame has been completely assembled
Consider a CardLayout for switching between panels ( http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html )
Slightly cleaned up, but the exact structure depends on what you actually want to achieve at the end:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MainMenu extends JPanel
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame mainFrame = new JFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainMenu = new MainMenu();
mainFrame.getContentPane().add(mainMenu);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
MainMenu()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
Dimension expectedDimension = new Dimension(690, 540);
setPreferredSize(expectedDimension);
setBackground(new Color(14, 36, 69));
JButton newGameButton = new JButton ("Nieuw Spel");
newGameButton.setAlignmentX(JComponent.CENTER_ALIGNMENT);
newGameButton.setFont(new Font("Old English Text MT", Font.BOLD, 40));
newGameButton.setForeground(new Color(217,144,39));
newGameButton.setBackground(new Color(14,36,69));
newGameButton.setBorderPainted(false);
newGameButton.setFocusPainted(false);
newGameButton.addActionListener(new PlayListener());
add(newGameButton);
}
private class PlayListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
removeAll();
GamePanel gamePanel = new GamePanel();
add(gamePanel);
revalidate();
}
}
}
class GamePanel extends JPanel
{
GamePanel()
{
setBackground(new Color(255,36,69));
}
}
You should use a JButton and not a JLabel. Then:
you add to your JButton : Your_JB.addActionListener(this); (don't forget to implement ActionListener to your class).
Now, we are gonna add the detector:
#Override
public void actionPerformed(ActionEvent e){
Object src = e.getSource();
if(src == Your_JB){
panel.setVisible(false);
}
}
When you click the button, it will make your panel disapear.
Try this:
this.remove(panel);
this.validate();
this.repaint(); //if you use paintComponent
this.add(panelgame);
this.revalidate();
Swing is hard to making nice UI. You just need to use validate() after remove().
I hope it's helpfull.

JPanel Possibly Overlapping?

So I have this problem with my code. Whenever I load up the game there is a red square in the center of the screen, and I have not programmed it to do so. I have tried to find the error for hours but I just can't see it. I think it has to do with the panels or something. The second thing is that when I press the button to draw the grid, only a small line appears. It is programmed to be much bigger than what it is, and it is not in the right location either. Below is all my code, and any help is greatly appreciated!!
package com.theDevCorner;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class Game extends JPanel implements ActionListener {
public static JButton grid = new JButton("Show Grid");
public static JPanel drawArea = new JPanel();
public static JMenuBar menu = new JMenuBar();
public static JPanel notDrawn = new JPanel();
public static boolean gridPressed = false;
public Game() {
grid.addActionListener(this);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(new Dimension(
Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit
.getDefaultToolkit().getScreenSize().height));
frame.setTitle("Game");
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
menu.setSize(new Dimension(1600, 20));
menu.setLocation(0, 0);
notDrawn.setBackground(new Color(255, 0, 50));
notDrawn.setSize(100, 900);
notDrawn.add(grid);
notDrawn.setLayout(null);
grid.setSize(new Dimension(100, 25));
grid.setLocation(0, 25);
drawArea.setSize(new Dimension((Toolkit.getDefaultToolkit()
.getScreenSize().width), Toolkit.getDefaultToolkit()
.getScreenSize().height));
drawArea.setLocation(100, 0);
drawArea.setBackground(Color.black);
drawArea.add(menu);
drawArea.add(game);
frame.add(drawArea);
frame.add(notDrawn);
}
public void paint(Graphics g) {
Game game = new Game();
if (gridPressed) {
Game.drawGrid(0, 0, g);
}
g.dispose();
repaint();
}
public static void drawGrid(int x, int y, Graphics g) {
g.setColor(Color.white);
g.drawLine(x, y, 50, 300);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == grid && gridPressed == true) {
gridPressed = false;
System.out.println("Unpressed");
}
if (e.getSource() == grid) {
gridPressed = true;
System.out.println("Pressed");
}
}
}
There are a number of problems...
The red "square" you are seeing is actually your grid button. The reason it's red is because of your paint method.
Graphics is a shared resource, that is, each component that is painted on the screen shares the same Graphics context. Because you chose to dispose of the context and because you've failed to honor the paint chain, you've basically screwed it up.
Don't EVER dispose of a Graphics context you didn't create. It will prevent anything from being painted to it again. Always call super.paintXxx. The paint chain is complex and does a lot of very important work. If you're going to ignore it, be ready to have to re-implement it.
null layouts are vary rarely the right choice, especially when you're laying out components. You need to separate your components from your custom painting, otherwise the components will appear above the custom painting.
This frame.setSize(new Dimension(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height)) is not the way to maximize a window. This does not take into consideration the possibility of things like tasks bars. Instead use Frame#setExtendedState
As Andreas has already commented, you actionPerformed logic is wrong. You should be using an if-statement or simply flipping the boolean logic...
Updated with simple example
ps- static is not your friend here...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JPanel implements ActionListener {
private GridPane gridPane;
public Game() {
setLayout(new BorderLayout());
SideBarPane sideBar = new SideBarPane();
sideBar.addActionListener(this);
add(sideBar, BorderLayout.WEST);
gridPane = new GridPane();
add(gridPane);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setTitle("Game");
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("grid")) {
gridPane.setGridOn(!gridPane.isGridOn());
}
}
public class GridPane extends JPanel {
private boolean gridOn = false;
public GridPane() {
setBackground(Color.BLACK);
}
public boolean isGridOn() {
return gridOn;
}
public void setGridOn(boolean value) {
if (value != gridOn) {
this.gridOn = value;
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (gridOn) {
g.setColor(Color.white);
g.drawLine(0, 0, 50, 300);
}
}
}
public class SideBarPane extends JPanel {
public JButton grid;
public SideBarPane() {
setBackground(new Color(255, 0, 50));
setLayout(new GridBagLayout());
grid = new JButton("Show Grid");
grid.setActionCommand("grid");
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
gbc.weighty = 1;
add(grid, gbc);
}
public void addActionListener(ActionListener listener) {
grid.addActionListener(listener);
}
}
}

Categories