I need to pass a JPanel extending class to the main class.
Here is what I have so far:
Main class
import java.awt.Color;
import javax.swing.*;
public class main {
private gamePanel gamepanel = new gamePanel();
public JPanel createContentPane(){
// We create a bottom JPanel to place everything on.
JPanel totalGUI = new JPanel();
//We set the Layout Manager to null so we can manually place
// the Panels.
totalGUI.setLayout(null);
//Now we create a new panel and add it to the bottom JPanel.
totalGUI.add(gamepanel);
totalGUI.setOpaque(true);
return totalGUI;
}
private static void createAndShowGUI(){
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("[=] There's a JPanel in here! [=]");
//Create and set up the content pane.
main demo = new main();
frame.setContentPane(demo.createContentPane());
//The other bits and pieces that make your program a bit more stable.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700,500);
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a jog for the event-dispatching thread:
//creating and showing this application's GUI.
System.out.println(gamepanel);
SwingUtilities.invokeLater(new Runnable() {
public void run(){
createAndShowGUI();
}
});
}
}
The gamePanel class
public class gamePanel extends JPanel implements Commons {
private Dimension d;
private ArrayList snowmens;
private coreFunctions functions = new coreFunctions();
private int snowmenX = 150;
private int snowmenY = 5;
private final String snowmenpix = "snowman.png";
private JPanel background;
public gamePanel() {
add(new JLabel("TEST"));
setFocusable(true);
setDoubleBuffered(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 700, 700);
}
}
I can't figure out why the blue background and the label is not being shown...
EDIT:
Here are more details:
Ok so I am trying to make a little 2D game. For that I need to create some snowmen on the gamePanel class and display it via the main class. To start it off, the createContentPane creates a background panel, the root panel if you want. The createandshowgui creates a JFrame.
The gamepanel class is in fact a JPanel which has 1 panel as of now, which is the background panel. For now, I only want it to have a blue background.
I tried putting it like this because I saw some examples and they were pretty similar to what I have, but for some reason, I can't get it to work....
Thank you,
Ara
You should use LayoutManager instead of setLayout(null); and if only one component is being added no need for it either (that component will stretch to fill unless others are added)
see here for tutorial on LayoutManagers:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html
If all you are trying to do is have a blue background (on which you can add components) then simply override paintComponent() of your gamePanel and paint the background blue:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
then you can add your JLabel as if it was a normal Panel as the background is now being painted blue and not set by/as a component.
If you have an image look into g.drawImage(Image image,int x,int y,ImageObserver iO)
EDIT
DROP THE CALL TO:
setLayout(null);
and it will work
Related
I have been struggling with this for some time. At first, I only used ActionListener, then I added the paintComponent, but I have no idea what to put there. I read some tutorials and used their code as an example, but it still doesn't work. Right now, the end result is the same as it was without PaintComponent.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Scream extends JPanel {
private JButton button = new JButton("OK");
private Color screenColor;
private JPanel panel = new JPanel();
private JFrame frame;
private Dimension screenSize;
private ImageIcon image;
private JLabel label = new JLabel(image);
private int x;
private int y;
private boolean mouseClicked;
public Scream() {
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e ) {
if (e.getSource() == button) {
mouseClicked = true;
frame.getContentPane().add(label);
frame.setSize(image.getIconWidth(), image.getIconHeight());
panel.repaint();
}
}
});
frame = new JFrame ("Existential angst");
screenColor = new Color(150, 100, 0);
panel.setBackground( screenColor );
frame.add(button, BorderLayout.PAGE_END);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1300, 700);
frame.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
image.paintComponent(this, g, 1300, 700);
}
public static void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Scream scream = new Scream();
}
});
}
}
If you are trying to dynamically add an image to a panel then you need to add the label to the panel. There is no need for any custom painting.
The basic code for adding components to a visible GUI is:
panel.add(...);
panel.revalidate();
panel.repaint();
Also, don't attempt to set the size of the frame to the size of the image. A frame contains a titlebar and borders. Instead you can use frame.pack();
I noticed a couple of issues:
image is never initialized to anything so it is null, effectively making the label empty. I assume maybe your example was just incomplete?
Once I initialized the image to something, your example still did not work. Turns out adding label without specifying any constraint basically does nothing (I assume since adding a component to a border layout without a constraint puts it in the center where panel already is). When I added the label to BorderLayout.NORTH, everything worked (though resizing the frame to the size of the image makes it only partially visible since the frame includes the OK button)
I have a very simple java swing application, I have a canvas class extended from JPanel
public class Canvas extends JPanel
{
private void doDrawing(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.drawString("Java 2D", 50, 50);
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
doDrawing(g);
}
}
And then I have my main class
public class SwingCounter extends JFrame {
private JTextField tfCount; // Use Swing's JTextField instead of AWT's TextField
private int count = 0;
public SwingCounter () {
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
cp.add(new JLabel("Counter"));
tfCount = new JTextField("0", 10);
tfCount.setEditable(false);
cp.add(tfCount);
JButton btnCount = new JButton("Count");
cp.add(btnCount);
Canvas canvas = new Canvas();
canvas.setSize(150, 150);
cp.add(canvas);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Exit program if close-window button clicked
setTitle("Swing Counter"); // "this" JFrame sets title
setSize(300, 100); // "this" JFrame sets initial size
setVisible(true); // "this" JFrame shows
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SwingCounter(); // Let the constructor do the job
}
});
}
}
It is basically code from a tutorial, apart from the JPanel. Everything shows fine, the JPanel/Canvas doesn't. What is missing?
You are adding your Canvas class to a panel which uses a FlowLayout. The FlowLayout respects the preferred size of all components. Your component has a preferred size of (0, 0) so there is nothing to paint.
You need to override the getPreferredSize() method of your Canvas class to return an appropriate Dimension for your panel.
Read the section from the Swing tutorial on Custom Painting for more information and a working example that does implement the getPreferredSize() method.
Also, don't call your class Canvas, since that is already an AWT component and is confusing. Use a more descriptive name.
I am new to Java....I studied that we can add two things on frame... I added button and in response by clicking on button I want rectangle as output....but i don't understand that..Why i am not getting output.....
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class customizedgui5 implements ActionListener {
JButton button;
JFrame frame;
public static void main(String[] args) {
customizedgui5 hi = new customizedgui5();
hi.go();
}
public void go() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("click me");
button.addActionListener(this);
myclass a = new myclass();
frame.getContentPane().add(button, BorderLayout.CENTER);
frame.getContentPane().add(a, BorderLayout.SOUTH);
frame.setSize(100, 100);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
frame.repaint();
frame.revalidate();
}
}
class myclass extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.orange);
g.fillRect(20, 50, 100, 100);
}
}
I would start by taking a look at Performing Custom Painting.
The main problem in your code is you are getting NullPointerException when you click the button because the reference of frame is null.
It is null because you've shadowed it in the constructor (basically, declared another variable of the same name within the constructor)...
// I'm null..
JFrame frame;
public void go() {
// Not the same as frame above...
JFrame frame = new JFrame();
You are also going to not see any changes because of a number of reasons...
The myclass panel has no size. With BorderLayout, this won't be "too" much of a problem, but...
You've drawing outside of the visible range of the panel. The rectangle you are painting won't appear because it is being painted outside of the width and height of the panel.
The rectangle will appear before you press the button as paintComponent will be called to update the state of the panel once it's made visible on the screen...
The first thing you need to is provide some kind of size hints to the BorderLayout. Try adding...
#Override
public Dimension getPreferredSize() {
return new Dimension(120, 150);
}
To myclass.
You also don't need to repaint the frame, what you really want to repaint is the instance of myclass. Try updating customizedgui5 so that a becomes a instance variable (like frame...
//...
myclass a;
//...
public void go() {
//...
a = new myclass();
//...
}
public void actionPerformed(ActionEvent event) {
a.repaint();
}
Now, the rectangle will still be shown the moment that the panel is made visible on the screen. Sure you could try setting it invisible, but this will affect the layout of the frame, hiding your component to start with, so, instead, we need some kind of flag we can trip so we know when to paint the rectangle. This is easily achieved by using a simple boolean variable, for example...
class myclass extends JPanel {
private boolean paintRect;
public void setPaintRect(boolean paint) {
paintRect = paint;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(120, 150);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (paintRect) {
g.setColor(Color.orange);
g.fillRect(20, 50, 100, 100);
}
}
}
Then in you actionPerformed method, you just need to set the flag...
public void actionPerformed(ActionEvent event) {
a.setPaintRect(true);
}
You may also want to take a read through Code Conventions for the Java Programming Language. It will make it easier for people to read your code...
When you click on your button, you're calling the method actionPerformed(ActionEvent event)
Take a look at what you did there. Currently, you repaint and re-validate the frame. If you want to add a rectangle to your frame, you need to do so by adding a new component to the frame that will draw the rectangle.
You could add another instance of your myclass JPanel which paints a rectangle like so:
public void actionPerformed(ActionEvent event) {
frame.getContentPane().add(new myclass(), BorderLayout.NORTH);
frame.repaint();
}
This would add your custom rectangle-drawing panel to the North section of your BorderLayout. If you want to add the rectangle "on top of" your button, you should embed your button within a JPanel, then add the rectangle-drawing panel to that instead of your main JFrame
I'm currently trying to draw shapes on a JPanel, which is within another JPanel, within a JFrame.
I've searched Google and Youtube and found out how to draw shapes within a JFrame that has one panel, but have found nothing which can help me with what I'm doing. (maybe I'm not seeing something).
Code I've seen so far:
public class GameScreen
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.red);
g.drawRect(100, 10, 30, 40);
}
public static void main(String[] args)
{
GameScreen gs = new GameScreen();
JFrame f = new JFrame();
f.setTitle("");
f.setSize(400,400);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(gs);
}
This is all good for when I'm dealing with just one panel, but I wanna display shapes on a panel which is within the 1'st panel I've created.
Add a JPanel to the JFrame in the same way as you're doing now, but do it with your own subclass of JPanel.
class MyPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.drawRect(100, 10, 30, 40);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400,400); // As suggested by camickr
}
}
You can add this to a JPanel which sits within the JFrame
public static void main(String[] args)
{
MyPanel mp = new MyPanel();
JPanel jp = new JPanel();
jp.add(mp);
JFrame f = new JFrame();
f.setTitle("");
f.setSize(400,400);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(jp);
}
This can work for components within components, if you add them as children components. The key is to extend the component and override the methods you wish to change.
This is all good for when I'm dealing with just one panel,
The code you posted works fine because a frame uses a BorderLayout. So, when you add your panel to the frame is will increase in size and your custom painting will be seen.
I wanna display shapes on a panel which is within the 1'st panel I've created.
When you create a panel it uses a FlowLayout by default. When you add a custom painting panel to that panel it will be displayed at its preferred size, which will be (0, 0) since you didn't specify the preferred size.
On the panels that do custom painting you also need to implement the getPreferredSize() method so the layout manager knows how to arrange the panels. For example:
public Dimension getPreferredSize()
{
return new Dimension(200, 200);
}
I have a poker game where I designed a nice pretty GUI that displays the cards and players. I did it all extending JPanel inside paint() with a lot of g2d.drawImage's and g2d.drawString()'s, with definite x and y locations.
My problem now is that I need to have a couple interactive buttons underneath it.. but whenever I try to add a JButton, it appears top and center. I've used setLocation(x, y) and setLayout(null) and everything I've seen in other replies, but none of them seem to match my need (Or at least I don't have a very well understanding of where to put it)
This is how my code is set up:
pokerserver.java
public class pokerserver extends JFrame {
public pokerserver() {
add(new drawing());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(720, 640);
setLocationRelativeTo(null);
setTitle("Poker HANGOUTS");
setResizable(false);
setVisible(true);
}
public static void main(String args[]) {
new pokerserver();
}
And then in drawing.class
public drawing() {
setFocusable(true);
setBackground(new Color(39,91,46));
setDoubleBuffered(true);
gameCards = new cards();
gameCards.shuffle();
for (int i = 0; i < 10; i++)
seats[i] = -1;
HQ = new HeadQuarters(this);
HQ.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
//All my UI code
}
My last attempt was trying to add
JButton button = new JButton("TEST");
add(button);
button.setLocation(10, 500);
at the end of public drawing(). I Keep seeing things on layout management, but it's not helping me -- mainly because I'm not sure how to implement it
Here's a screenshot to help visualize what I'm talking about->
http://i.imgur.com/ttvif.png
Trying to get the button underneath. Unless there's a way to add an ActionListener to a drawImage()?
For your main panel use a BorderLayout.
Then to the "CENTER" you can add your game panel with all your custom painting.
Then create a panel and add the buttons to it. Now you can add this panel to the NORTH of the main panel.
In other words you are not restricted to using a single panel.
Also, custom painting should be done in the paintComponent() method of your panel, NOT the paint() method.
I'm not really sure what you are after, but here are two interpretations.
I suspect you want the 1st one 'Buttons over custom painting', but as a user I'd prefer the 2nd, with 'Buttons below custom painting'.
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
class PaintPanel extends JPanel {
BufferedImage bg;
PaintPanel(LayoutManager2 layout) {
super(layout);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (bg==null) {
bg = new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bg.createGraphics();
GradientPaint gp = new GradientPaint(
0,0,Color.RED,500,500,Color.BLUE);
g2.setPaint(gp);
g2.fillRect(0,0,500,500);
g2.dispose();
}
g.drawImage(bg,0,0,getWidth(),getHeight(),this);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel buttons = new JPanel(
new FlowLayout(FlowLayout.CENTER));
buttons.setOpaque(false);
buttons.add(new JButton("Start"));
buttons.add(new JButton("Stop"));
PaintPanel pp = new PaintPanel(new BorderLayout());
pp.setPreferredSize(new Dimension(200,100));
pp.add(buttons, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null,pp);
JPanel gui = new JPanel(new BorderLayout());
gui.setBackground(Color.ORANGE);
gui.add(pp, BorderLayout.CENTER);
gui.add(buttons, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null,gui);
}
});
}
}