JFrame graphics ignores the first few renders - java

Here is a minimal code to see the bug:
import javax.swing.*;
import java.awt.*;
public class Main1 extends JFrame {
static Main1 main;
public Main1() {
super("app");
}
public static void main(String[] args) {
main = new Main1();
main.setBounds(300, 300, 800, 500);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Graphics g = main.getGraphics();
for(int i = 0; i < 100; i++){
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, 800, 500);
}
}
}
If i use 100 in the "for" cycle, the frame appears not to be colored, but 200 loops is enough to color it.
I want to make an application where frames change rarely, but this feature ruins the quality of code because I have to make a number of dummy frames.

public static void main(String[] args) {
main = new Main1();
main.setBounds(300, 300, 800, 500);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Graphics g = main.getGraphics();
for(int i = 0; i < 100; i++){
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, 800, 500);
}
}
This is not how you do Swing graphics. Getting a Graphics object by calling .getGraphics() on a component gives you a short-lived unstable and sometimes null object. For instance, it takes some time for the created JFrame to render, and if you call getGraphics() and try to use it prior to rendering, the object may be null, and certainly won't wokr.
Instead paint within a JPanel's paintComponent method using the Graphics object given by the JVM as per the tutorials:
public class MainPanel extends JPanel {
public MainPanel {
setPreferredSize(new Dimension(800, 500)));
setBackground(new Color(255, 0, 0)); // if you just want to set background
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// use g here do do your drawing
}
}
and then use it like so:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
Tutorial: Lesson: Performing Custom Painting
And yes, if you want to drive a simple animation, use a Swing Timer to help drive it like so:
public class MainPanel extends JPanel {
private int x = 0;
private int y = 0;
public MainPanel {
setPreferredSize(new Dimension(800, 500)));
setBackground(new Color(255, 0, 0)); // if you just want to set background
// timer code:
int timerDelay = 15;
new Timer(timerDelay, ()-> {
x += 4;
y += 4;
repaint();
}).start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// use g here do do your drawing
g.setColor(Color.BLUE);
g.drawRect(x, y, 20, 20);
}
}

Related

JPanel and JFrame size not changing [duplicate]

This question already has answers here:
paintComponent not painting onto JPanel
(2 answers)
Closed 5 years ago.
I'm making a game in Java and first I didn't use a JPanel which caused flickering on repaint() and so I decided to use it. I'm not sure how to implement it in my current code. When I tried to do so all I got was a window that was as small as it gets. My original Window class code:
public class Window extends JFrame {
private double stepLen;
public Window(double stepLen) {
this.stepLen = stepLen;
this.setSize(800, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setTitle("Frogger");
this.setLayout(null);
getContentPane().setBackground(Color.black);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int x = (dim.width - this.getSize().width)/2;
int y = (dim.height - this.getSize().height)/2;
this.setLocation(x, y);
JLabel goal = new JLabel();
goal.setText("|=========|");
goal.setForeground(Color.WHITE);
goal.setFont(new Font("Seif", Font.PLAIN, 20));
add(goal);
goal.setBounds(325, -10, 600, 50);
setFocusable(true);
requestFocusInWindow();
this.setVisible(true);
}
This code works and it creates a window.
Main class:
Window window = new Window(50);
And then I tried to do it this way:
I have separate GameFrame (JFrame) and GameCanvas (JPanel) classes.
The Frame looks like this:
public class GameFrame extends JFrame{
private double stepLen;
public GameFrame() {
this.stepLen = 50;
this.setSize(800, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setTitle("Frogger");
this.setLayout(null);
this.setVisible(true);
this.getContentPane().setBackground(Color.black);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int x = (dim.width - this.getSize().width)/2;
int y = (dim.height - this.getSize().height)/2;
GameCanvas gcanvas = new GameCanvas();
this.add(gcanvas);
this.pack();
this.setLocation(x, y);
}
}
}
And the GameCanvas class
public class GameCanvas extends JPanel {
public GameCanvas() {
setDoubleBuffered(true);
JLabel goal = new JLabel();
goal.setText("|=========|");
goal.setForeground(Color.WHITE);
goal.setFont(new Font("Seif", Font.PLAIN, 20));
this.add(goal);
goal.setBounds(325, -10, 600, 50);
this.getPreferredSize();
this.setVisible(true);
this.repaint();
}
Camickr is correct - go up vote and mark his answer as correct, this is only here to save him from pulling out what little hair he has remaining
You're using a null layout, without taking over its responsibility
Failed to provide sizing hints to for the component to allow the layout manager (which you're no longer using) to do it's job
This are all common mistakes, to which there are countless answers already provided
GameFrame
public class GameFrame extends JFrame {
private double stepLen;
public GameFrame() {
this.stepLen = 50;
this.setSize(800, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setTitle("Frogger");
// Well, there's your problem...
//this.setLayout(null);
// Don't do this here...
this.setVisible(true);
this.getContentPane().setBackground(Color.black);
// Simpler way to achieve this
//Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
//int x = (dim.width - this.getSize().width) / 2;
//int y = (dim.height - this.getSize().height) / 2;
GameCanvas gcanvas = new GameCanvas();
this.add(gcanvas);
this.pack();
//this.setLocation(x, y);
setLocationRelativeTo(null);
setVisible(true);
}
}
GameCanvas
public class GameCanvas extends JPanel {
public GameCanvas() {
// Pointless
//setDoubleBuffered(true);
JLabel goal = new JLabel();
goal.setText("|=========|");
goal.setForeground(Color.WHITE);
goal.setFont(new Font("Seif", Font.PLAIN, 20));
this.add(goal);
// Pointless
//goal.setBounds(325, -10, 600, 50);
// Pointless
//this.getPreferredSize();
// Pointless
//this.setVisible(true);
// Pointless
//this.repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public void paintComponent(Graphics g) {
int firstRoad = 5;
int i = 0;
int max = 10;
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.setColor(Color.WHITE);
g2.drawRect(5, 30, 75, 40);
while (i < max) {
g2.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(3));
if (i % 2 == 0) {
g.setColor(Color.WHITE);
g.drawRect(3, firstRoad + 50 * i, 793, 50);
//g.fillRect(3, firstRoad + 50 * i, 793, 50);
} else {
g2.setColor(Color.WHITE);
g2.drawRect(3, firstRoad + 50 * i, 793, 50);
}
i++;
}
}
}
So, the way I was taught in my AP Computer Science class is to set your frame size and other frame characteristics in your main. Here is an example:
import javax.swing.JFrame;
public class theSetupClass{
public static void main(String[] args){
JFrame theGUI = new JFrame();
theGUI.setSize(300,400); //Sets the frame size to 300 by 400
theGUI.setTitle("Example");
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theComponentClass component = new theComponentClass(); //Create new theComponentClass
frame.add(component);//Add theComponentClass to theGUI
frame.setVisible(true);
}
}
The code above creates the JFrame and adds the following class to it.
import java.awt.*;
import javax.swing.*;
public class theComponentClass extends JComponent{
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Rectangle r = new Rectangle(10,10,this.getWidth()-10,this.getHeight()-10);
//Creates a rectangle that is 10 pixels away from all sides of the frame
g2.fill(r); //Draws and fills the rectangle
}
}
I hope that you find this helpful!

In Java, how can I combine CardLayout and GridBagLayout and still be able to switch panels?

New to Java and very new to Java's GUI classes. I'm making a GUI to showcase a few games, but am having difficulties switching panels. I read about CardLayout but I'm having an issue implementing it because I can't get the JPanels that hold the different games' GUIs to send their events back to the class that uses the CardLayout. (This is probably where I'm going wrong -- I can't get my head around how to structure this properly.)
This is my main menu (called mainContainer):
This is the overall structure of the GUI driver:
public class CasinoDriverGUI {
//CardLayout is here in the main method Container contentPane.add(cardLayout)
public static void main(String[] args) throws IOException
//MainContainer is MenuScreen: GridBagLayout for nice button placement
static class MainContainer extends JPanel implements ActionListener{...}
static class CrapsContainer extends JPanel implements ActionListener{...}
static class PokerContainer extends JPanel implements ActionListener{...}
//Button with custom look
class CButton extends JButton
}//end CasinoDriverGUI
Here is the main method: It grabs an image from a website and then adds the menu screen (mainContainer) to the contentPane. The menu screen uses GridBagLayout, but it's where the button components are added. Because of this, I can't figure out how to get the CardLayout of the contentPane to listen to the menu screen's buttons. I tried using ContainerListener but that seemed to be a dead end.
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
As I have it so far, I have just tried using the "menu screen" (mainContainer) to instantiate all the games' panels and use an ActionListener on some buttons to simply call thisGame.setVisible(true). but this is forcing the window to be minimized and re-opened for any change to be detectable.Edit: fixed this.
Any advice on how I can restructure this code to be able to switch the panels from the menu screen to the different game's panels? (Code is below, but the craps and poker GUIs are incomplete.. just using the code as placeholders.
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
static class MainContainer extends JPanel implements ActionListener
{
public BufferedImage gradientImage = null;
public static BufferedImage textureImg; // static for ease
public static boolean loadingFinished = false;
protected JButton pokerJBtn;
protected JButton crapsJBtn;
CrapsContainer crapsContainer;
PokerContainer pokerContainer;
public MainContainer() {
setBorder(new EmptyBorder(50, 50, 50, 50)); // setting the insets
setLayout(new GridBagLayout());
// working with GridBagConstraints
GridBagConstraints labCnst = new GridBagConstraints();
GridBagConstraints txtCnst = new GridBagConstraints();
labCnst.ipady = txtCnst.ipady = 10;
labCnst.fill = GridBagConstraints.HORIZONTAL;
labCnst.gridwidth = 1;
labCnst.weightx = 0.3;
labCnst.gridx = 2;
labCnst.gridy = 2;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
pokerJBtn = new CButton("5-Card Poker");
add(pokerJBtn, labCnst);
labCnst.gridx = 2;
labCnst.gridy = 20;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
crapsJBtn = new CButton("Craps");
add(crapsJBtn, labCnst);
crapsContainer = new CrapsContainer();
pokerContainer = new PokerContainer();
add(crapsContainer);
add(pokerContainer);
crapsContainer.setVisible(false);
pokerContainer.setVisible(false);
//Add Action Listeners
crapsJBtn.addActionListener(this);
pokerJBtn.addActionListener(this);
}
public void changeCompFont(JComponent comp)
{
comp.setForeground(Color.WHITE);
comp.setFont(getFont().deriveFont(Font.BOLD, 13));
}
// To PAINT THE TEXTURE ABOVE THE COMPONENTS
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D)g.create(); // cloning
Rectangle2D txRect = new Rectangle2D.Double(0, 0, textureImg.getWidth(), textureImg.getHeight());
TexturePaint txPaint = new TexturePaint(textureImg, txRect);
g2d.setPaint(txPaint);
//make the texture transparent
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.233f));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();// disposing the graphics object
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if(gradientImage==null || gradientImage.getHeight() != getHeight() )
{
gradientImage = createGradientImg();
}
g2d.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
public BufferedImage createGradientImg()
{
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
// background gradient paint, linear gradient paint for the background
// Gradient paint rendering could be made more optimized
LinearGradientPaint lgrPaint = new LinearGradientPaint(0.0f, 0.0f, getWidth(), getHeight(),
new float[] { 0.0f, 0.5f, 0.6f, 1.0f },
new Color[] { new Color(0x0530E),// new Color[] { new Color(0x002AFF),
new Color(0x0A31B),
new Color(0x0A31B),
new Color(0x0530E ) });
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setPaint(lgrPaint);
//g2d.shear(0.2, 0);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
g2d.drawImage(textureImg, 0, 0, getWidth(), getHeight(), null);
return image;
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == pokerJBtn)
{
pokerContainer.setVisible(true);
}
else if (e.getSource() == crapsJBtn){
this.setVisible(false);
invalidate();
crapsContainer.setVisible(true);
revalidate();
repaint();
}
}
}
//Either Flow, Border, or GridBag Layout
static class CrapsContainer extends JPanel implements ActionListener
{...}
//Either Flow, Border, or GridBag Layout
static class PokerContainer extends JPanel implements ActionListener
{...}
//Custom Button to change aesthetic look
class CButton extends JButton
{...}
}

Paint component after creation

To create my first 2D game in Java, I thought of using the JFrame's getContentPane(), updating it with the new view every 50ms.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// ...
frame.setVisible(true);
// ...
Container area = frame.getContentPane();
Graphics pen = area.getGraphics();
pen.clearRect(0, 0, area.getWidth(), area.getHeight()); // Remove previous drawing
pen.drawString("Text", 50, 50);
// ...
area.repaint();
But it doesn't work; the window doesn't change.
As kiheru already said, use paintComponent(Graphics g) for custom painting. Here is an example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class Example {
int i = 0;
public Example() {
JFrame frame = new JFrame();
frame.getContentPane().add(new DrawingPanel());
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.getContentPane().repaint();
}
};
Timer timer = new Timer(500, actionListener); //500 = Every 500 milliseconds
timer.start();
}
class DrawingPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // Removes previous graphics
Random r = new Random(); //Randomizer
//Random x- and y-coordinates
int x = r.nextInt(400);
int y = r.nextInt(400);
//Random rgb-values
int red = r.nextInt(255);
int green = r.nextInt(255);
int blue = r.nextInt(255);
//Random width and height
int width = r.nextInt(100);
int height = r.nextInt(100);
g.setColor(new Color(red, green, blue)); //Setting color of the graphics
g.fillRect(x, y, width, height); //Filling a rectangle
}
}
public static void main(String[] args) {
new Example();
}
}
research for double buffering or for fast image drawing using VolatileImage type for directly rending into graphics card. In your case if you use double buffering the code will be:
private static BufferedImage bufferedImage = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
private static Graphics2D gBuff = bufferedImage.createGraphics();
public static void main(String[] args)
{
JFrame frame = new JFrame()
{
#Override
public void paint(Graphics g)
{
g.drawImage(bufferedImage,0,0,this);
}
};
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
gBuff.setColor(Color.WHITE);
gBuff.fillRect(0, 0, frame.getWidth(), frame.getHeight()); // Remove previous drawing
gBuff.setColor(Color.BLACK);
gBuff.drawString("Text", 50, 50);
// ...
frame.setVisible(true);
// ...
}

Pause before painting the panel in Java

I am trying to slow down the painting by adding a pause between two consecutive paints. Thread.sleep() apparently doesn't work. Here is the code:
import javax.swing.*;
import java.awt.*;
public class Sa {
int x = 70;
int y = 70;
public static void main(String[] args) {
Sa gui = new Sa();
gui.go();
}
public void go() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyDrawPanel drawPanel = new MyDrawPanel();
frame.getContentPane().add(drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
for(int i=0; i<130; i++) {
x++;
y++;
drawPanel.repaint();
try {
Thread.sleep(1500);
} catch(Exception ex) {}
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
Thread.sleep(1500); // will not work!!
g.setColor(Color.green);
g.fillOval(x, y, 80, 40);
}
}
}
Remove Thread.sleep() inside paint() method, not need it, and second, you Thread.sleep() needs to be caught InterruptedException, it may give an error while compiling:
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
//Thread.sleep(1500); // will not work!! (DONT NEED this
g.setColor(Color.green);
g.fillOval(x, y, 80, 40);
Have you looked at Swing Timer ?

paintComponent not changing shape

can someone take a look at my code below and tell me why, when I change the following two statements, I do not see a change on the rectangle that is painted. So if I change:
g.setColor(Color.black);
g.fillRect(l, w, 100, 100);
The program still prints a black rectangle with the same dimensions and in the same position that I first started with even though I change color to yellow or try to change the dimensions or location. I am BlueJ. The following is my full code:
import java.awt.*;
import javax.swing.*;
public class SwingPaintDemo2 extends JComponent {
public static boolean isWall = true;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
//System.out.println("Created GUI on EDT? "+
//SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
JPanel MyPanel = new JPanel();
MyPanel.setBorder(BorderFactory.createEmptyBorder(1000, 1000, 1000, 1000));
MyPanel.setPreferredSize(new Dimension(250, 200));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int l = 10;
int w = 10;
g.setColor(Color.black);
g.fillRect(l, w, 100, 100);
}
}
Any advice would be appreciated.
Your SSCCE doesnt compile where is MyPanel class or did you mean new SwingPaintDemo2()?
On the assumption you meant new SwingPaintDemo2():
The code does work just fine but the JFrame is sized very small:
because you dont give it any size and none of its components have a size as they do not have any components added to them, thus we must make the JComponent return a correct size so when we call pack() our JFrame is sized correctly
Solution
override getPreferredSize() of JComponent to return a width and height which fits all drawings.
Some suggestions though:
Dont extend JComponent rather extend JPanel
Here is an example (your code with above fixes implemented):
import java.awt.*;
import javax.swing.*;
public class SwingPaintDemo2 extends JPanel {
public static boolean isWall = true;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
//System.out.println("Created GUI on EDT? "+
//SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
JPanel MyPanel = new JPanel();
MyPanel.setBorder(BorderFactory.createEmptyBorder(1000, 1000, 1000, 1000));
MyPanel.setPreferredSize(new Dimension(250, 200));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new SwingPaintDemo2());
f.pack();
f.setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int l = 10;
int w = 10;
g.setColor(Color.black);
g.fillRect(l, w, 100, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
}

Categories

Resources