I am trying to set background color of my screen to green.
My code so far:
package game;
import java.awt.*;
import javax.swing.JFrame;
public class Game extends JFrame {
public static void main(String[] args) {
DisplayMode dm = new DisplayMode(800, 600, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
Game g = new Game();
g.run(dm);
}
public void run(DisplayMode dm) {
setBackground(Color.GREEN);
setForeground(Color.WHITE);
setFont(new Font("arial", Font.PLAIN, 24));
Screen s = new Screen();
try {
s.setFullScreen(dm, this);
try {
Thread.sleep(5000);
} catch (Exception E) {
}
} finally {
s.restoreScreen();
}
}
#Override
public void paint(Graphics g){
g.drawString("Check Screen", 200, 200);
}
}
When I run the program, I get this:
Screen should be green according to line:
setBackground(Color.GREEN);
Why does the background is not being set to green when I run the program?
You need to add a call to super.paint (g); in your paint () method.
#Override
public void paint(Graphics g){
super.paint (g);
g.drawString("Check Screen", 200, 200);
}
This will ensure that the component will draw itself correctly, including the background color, then draw your text.
Generally, whole approach is very bad. Even if it works with getContentPane().setBackground(Color.GREEN) it won't probably work because you are calling a Thread.sleep(5000) on EDT (or you will have issues soon or later). Use proper component for repetitive task's (refreshing of your screen): Swing Timer.
Instead of overriding JFrame's paint method, it's far better to use JPanel and to override it's paintComponent method. So, something like this:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Game extends JFrame {
JFrame frame = new JFrame();
public Game() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Panel());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Game();
}
});
}
class Panel extends JPanel {
Timer timer;
Panel() {
setBackground(Color.BLACK);
setForeground(Color.WHITE);
refreshScreen();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("arial", Font.PLAIN, 24));
g.drawString("Check Screen", 200, 200);
}
public void refreshScreen() {
timer = new Timer(0, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.setRepeats(true);
//Aprox. 60 FPS
timer.setDelay(17);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(650, 480);
}
}
}
Related
public class Rec extends JFrame {
public Rec (){
JFrame jframe = new JFrame();
jframe.setSize(500, 500);
jframe.setVisible(true);
}
public void render (Graphics g){
g.setColor(Color.red);
g.fillRect(0,0,50,50);
}
public static void main(String[] args) {
Rec frame = new Rec();
frame.render(g);
}
}
Why does this not work? I am aware I may need a paintComponent, if so how would I go about doing this? Any help would be great, Thank You!
The thing is that painting in a JFrame is not what you should be doing. It is better (in this instance) to set the contentpane as a JPanel, and paint inside the JPanel.
Take this short snippet as an example:
import java.awt.*;
import javax.swing.*;
public class Rec {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame rec = new JFrame();
rec.setSize(50, 150);
rec.setContentPane(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 50, 50);
}
});
rec.setVisible(true);
}
});
}
}
Result:
//May be this is what you are looking for.
public void paintComponent(Graphics g) {
// Create a copy of the passed in Graphics object
Graphics gCopy = g.create();
// Change the properties of gCopy and use it for drawing here
// Dispose the copy of the Graphics object
gCopy.dispose();
}
//or might be this
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Dimension;
import javax.swing.JFrame;
public class DrawingCanvas extends JPanel {
public DrawingCanvas() {
this.setPreferredSize(new Dimension(600, 75));
}
#Override
public void paintComponent(Graphics g) {
// Draw a rectangle
g.fillRect(100, 100, 100, 100);
}
public static void main(String[] args) {
JFrame frame =new JFrame("Drawing");
frame.getContentPane().add(new DrawingCanvas());
frame.pack();
frame.setVisible(true);
}
}
I have problem with KeyListener, I've been searching solution but it should be working.
Unfortunately, it doesn't and i have no idea why. When i type up arrow, nothing happens.
I was reading about "Focus", but I don't know how this works, maybe you can give me some example, unnecessary to my problem.
public class Trawa extends JPanel implements KeyListener {
int wysokosc = 200;
public Trawa(){
addKeyListener(this);
setSize(200,600);
setBackground(Color.GREEN);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
Color c1 = new Color(36,217,36);
g2d.setColor(c1);
g2d.fillRect(10, wysokosc, 100, 100);
c1 = new Color(0,0,0);
g2d.setColor(c1);
g2d.fillRect(10, wysokosc, 30, 30);
g2d.fillRect(80, wysokosc, 30, 30);
c1 = new Color(252,3,0);
g2d.setColor(c1);
g2d.fillRect(40, wysokosc+60 ,30,30);
}
#Override
public void keyPressed(KeyEvent arg0) {
int key = arg0.getKeyCode();
if(key == KeyEvent.VK_UP)
wysokosc-=100;
repaint();
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
Here is my main class with frame. Maybe the problem is here.
public class GUI extends JFrame{
public GUI(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
add(new Trawa());
setLayout(new GridLayout(1,5));
pack();
setSize(1300, 600);
setLocation(40, 100);
setVisible(true);
}
public static void main(String[] args) {
new GUI();
}
}
You have to understand how focus works before using a KeyListener.
Try calling setFocusable(true) from your JPanel's constructor.
You have done everything correctly, but you forgot to bind the key listener with your frame.
try this version of you GUI class
class GUI extends JFrame {
public GUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
Trawa t = new Trawa();//this is a JPanel as well as a KeyListner
add(t);
this.addKeyListener(t);
setLayout(new GridLayout(1, 5));
pack();
setSize(500, 400);
setLocation(40, 100);
setVisible(true);
}
}
as pointed by Kevin: the minimal change required is to set focus on the panel
public Trawa() {
addKeyListener(this);
setSize(200, 600);
setBackground(Color.GREEN);
setFocusable(true);
}
I am trying to draw a rectangle in the class "Graphics", but for some reason the rectangle does not appear, but the program returns no errors. I have never experience issues such as this before so I am rather confused.
Main()
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main
{
public Main()
{
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(container);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Main();
}
});
}
Graphics()
import java.awt.Color;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(500, 500, 500, 500);
}
}
EDIT FOR HOVERCRAFT
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main
{
public Main()
{
JFrame window = new JFrame();
Sound soundCall = new Sound();
Draw drawCall = new Draw();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawCall);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Main();
}
});
}
}
Through adding this window.getContentPane().add(drawCall); asks me to change drawCall to a Component
EDIT 2:
public class Draw
{
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
}
}
ERROR
The method add(Component) in the type Container is not applicable for the arguments (Draw)
You add your graphicsCall variable to nothing, and so it will not be displayed. Solution: add it to a container such as that JPanel that you just created, or perhaps directly to the JFrame's contentPane.
i.e., change this:
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(container);
to this:
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
// final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(soundCall);
As an aside, you will want to re-name that class from Graphics to something else, or else you risk confusing yourself or your compiler since there already exists a critical Java class with that name.
Also, avoid using setSize(...). Better to have your drawing JPanel override getPreferredSize() and to call pack() on your JFrame.
Edit
As per MadProgrammer's astute observation, you're drawing outside of the bounds of your component.
Edit 2
Regarding your latest code, this:
public class Draw
{
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
}
}
is useless dreck. Why are you needlessly wrapping a class inside of a class? Instead why not simply:
public class Draw extends JPanel {
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
#Override
public Dimension getPreferredSize() {
// return an appropriate Dimension here
}
}
I was drawing my game on Canvas, all was god, but I changed it into a JPanel, but now its not working correctly, here are the codes, you can just copy them and you'll see where is the problem (I have a menu and after clicking on the button it should create new thread and there i want to draw, the problem in JPanel is that the button is able to see, its blinking and i can press it, in canvas it was fine, there wasn't any button). I solved it, that after clicking on the button I setted him unvisible (button.setVisible(false)), but these codes are just examples and in my game I have more buttons, so its not practical because I need them to see after the game ends. I think I just forgot an important method in JPanel, thx for help, codes:
//Main class representing menu
public class Sandbox extends JFrame{
Panel p = new Panel();
public static void main(String[] args) {
new Sandbox();
}
public Sandbox() {
setLayout(null);
setPreferredSize(new Dimension(200, 200));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
final JButton but = new JButton("Button");
but.setBounds(0, 0, 50, 50);
but.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
p.start();
}
});
add(p);
add(but);
pack();
setVisible(true);
}
}
//Drawing on Canvas -> working well
public class Panel extends Canvas implements Runnable {
Thread t;
public Panel() {
setSize(new Dimension(200, 200));
setVisible(false);
}
public void start() {
t = new Thread(this);
t.start();
setVisible(true);
}
public void draw() {
BufferStrategy b = getBufferStrategy();
if(b == null) {
createBufferStrategy(3);
return;
}
Graphics g = b.getDrawGraphics();
g.setColor(Color.red);
g.fillRect(0, 0, 200, 200);
g.dispose();
b.show();
}
#Override
public void run() {
while(!t.isInterrupted()) {
try {
draw();
t.sleep(200);
} catch (InterruptedException ex) {}
}
}
}
//Drawing on JPanel -> here i can press the button after first click on it
public class Panel extends JPanel implements Runnable {
Thread t;
public Panel() {
setSize(new Dimension(200, 200));
setVisible(false);
}
public void start() {
t = new Thread(this);
t.start();
setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 200, 200);
}
#Override
public void run() {
while(!t.isInterrupted()) {
try {
repaint();
t.sleep(200);
} catch (InterruptedException ex) {}
}
}
}
Not sure I understand exactly what you are trying to do but you do have a couple of problems:
the setVisible(true) method should be invoked AFTER you have added all the components to the frame and packed the frame.
by default the content pane of a JFrame uses a BorderLayout. You code is adding two components to the CENTER of the BorderLayout, but a BorderLayout only allows you to add one component to the CENTER, so only the last component added will be displayed.
I'm trying to play around with JFrame/JPanels repaint(); and so forth, but when I start a thread, and call repaint via run while true, it only spits out a line of System.out.println("as"); which I put in place to check if loop was running.
So the question is:
Why is my drawings disappearing when calling repaint in a loop?
(It seems only a JFrame with the canvas_width/height is showing up, no panels etc.)
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(CANVAS_WIDTH, CANVAS_HEIGHT);
frame.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new GridLayout());
frame.getContentPane().add(p);
Something s = new Something();
p.add(s);
p.setBackground(Color.black);
frame.pack();
}
And the something class:
public class Something extends JPanel implements Runnable {
public Something(){
Thread t = new Thread();
t.start();
run();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.cyan);
g.fillRect(0, 0, getWidth()-150, getHeight()-100);
g.setColor(Color.BLACK);
g.fillOval(10, 10, 25, 25);
}
#Override
public void run() {
while(true){
repaint();
System.out.println("as");
try {
Thread.sleep(1);
} catch (InterruptedException e){}
}
}
}
Any help regarding the contentpane is appreciated, since, I'm not sure this is done correctly.
Instead of calling Thread.sleep(n) in your Thread, implement a Swing Timer for repeating tasks. That ensures that repaint() is called on the Event Dispatch Thread.
See Concurrency in Swing for more details.
Also, repainting every 1 millisecond is being very optimistic.
Working SSCCE E.G. (Note this version actually changes the co-ords of the resulting paint operations, just so we know something is happening!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Something extends JPanel {
static final int CANVAS_WIDTH = 400;
static final int CANVAS_HEIGHT = 100;
private int xDelta = 0;
public Something(){
ActionListener animater = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
};
Timer t = new Timer(10,animater);
t.start();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.cyan);
g.fillRect(0, 0, getWidth()-(xDelta--), getHeight()-100);
g.setColor(Color.BLACK);
g.fillOval(xDelta, 10, 25, 25);
if (xDelta<0) {
xDelta = CANVAS_WIDTH;
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new GridLayout());
frame.getContentPane().add(p);
Something s = new Something();
p.add(s);
p.setBackground(Color.black);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
Starting a Runnable in a new Thread is done with java.lang.Thread.Thread( Runnable ) constructor.
Calling a method of a GUI component outside the Swing event loop is not a good practice, use a Swing timer instead.
Your code becomes:
public static void main(String[] args) {
...
new Timer( 40, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
repaint
}
}).start();
...
}