Java graphics - failing to paint properly - java

Learning to use graphics in java and currently at the moment i'm trying to add some graphics to the screen but failing. I've tried different approaches in a trial and error fashion yet had no luck. The code shown, the structure cannot change in terms of having paint method in a separate class for example. Its a simplified version on a project I’m working on.
Other questions on stackoverflow have helped to an extend and similar with the oracle website but I'm still facing issues hence why I am asking here.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test
{
public static void main(String Args[])
{
panelme p1 = new panelme();
}
}
class panelme
{
JFrame mainPanel;
panelme ()
{
mainPanel = new JFrame();
mainPanel.setSize(1000,1000);
mainPanel.setDefaultCloseOperation(mainPanel.EXIT_ON_CLOSE);
//paintFrame();
//paintFrame(g);
//paintFrame(null);
mainPanel.setVisible(true);
}
public void paintFrame(Graphics g)
{
g.drawString("This is a string!", 30, 40);
//repaint();
}
}

Start by taking a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing
Next, take a look at 2D Graphics trail
Next, create your self a custom class which extends from JPanel and then override it's paintComponent method and place your custom painting within it...
public class PaintPane extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("This is a string!", 30, 40);
}
}
Next, add your custom panel to a window...
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});

Related

Java: paintComponent() Oval is not appearing in Netbeans

I'm trying to learn how to draw an oval in java but the paintComponent I made is not being called by anything, and attempting to call it only causes more issues.
The program runs successfully but the image I want displayed isn't showing up.
import java.awt.*;
import javax.swing.*;
public class TEST2{
public void paintComponent(Graphics g){
g.drawOval(70, 70, 100, 100);
}
public static void main(String[] args) {
TEST2 gui = new TEST2();
gui.setUpFrame();
}
public void setUpFrame(){
JFrame frame = new JFrame();
frame.setTitle("Images should be in this program");
frame.setSize(600,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Start by taking a look at Painting in AWT and Swing and Performing Custom Painting
In order to be able to perform custom painting in Swing, you must...
Inherit from a swing based component (like JComponent or JPanel)
You must then override it's paintComponent method and perform you custom painting within this method.
Add this component to something that is displayable (like a JFrame)
You should make sure to call super.paintComponent before doing any custom painting
To ensure that you're not making any (common) mistakes, you should use the #Override annotation
As an example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test2 extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(70, 70, 100, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame();
frame.setTitle("Images should be in this program");
frame.add(new Test2());
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
The paintComponent() method is a method that you override and it should be accessed inside a class that extends JPanel. You can create a new class that extends JPanel and override the paintComponent() method to draw your oval. You will also have to add the new JPanel to your JFrame for it to display. I modified your code below it should display the oval now. As Madprogrammer noted you should probably construct your GUI within the context of the edt to avoid concurrency issues but I will omit that for simplicity.
import java.awt.*;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
Test gui = new Test();
gui.setUpFrame();
}
public void setUpFrame() {
JFrame frame = new JFrame();
frame.setTitle("Images should be in this program");
frame.setSize(600, 300);
JPanel oval = new oval();
frame.setContentPane(oval);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class oval extends JPanel{
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(70, 70, 100, 100);
}
}
}

Java Program flow

i have been programming in python for a while and have been interested in learning Java for a while now so i figured i would give it a go so have mercy i know this is a infinite loop at the moment so tread carefully.
import javax.swing.*;
import java.awt.*;
public class snake extends JFrame{
public static void main(String[] args) {
JFrame screen = new JFrame("Snake");
screen.setSize(640, 480);
screen.setResizable(false);
screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = screen.getContentPane();
screen.setVisible(true);
while(true) {
pane.add(new Render());
}
}
}
class Render extends JComponent {
Render(){
}
public void paint(Graphics g) {
g.setColor(Color.white);
g.fillRect(0,0,640,480);
g.setColor(Color.green);
g.fillRect(100,100,25,25);
}
}
my current goal for this small program is to loop my code so that every time my while loop iterates i would like the flow of code to update the screen and redraw anything so in the future the rectangle could move. From my tests i have been running the first iteration of the loop runs through the method inside of my Render class and then after that it stays in the (i believe that is a constructor in java)
Render() {
}
piece of code.where it cycles through every iteration how i would like it for the method. I have tried to call the method from inside the constructor and that did not work. How can i route the flow of the program so every iteration of my loop the program goes through that method? Thanks for your time.
Start by taking a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting in Swing works...
This...
while(true) {
pane.add(new Render());
}
is going to cause issues. If it doesn't block the Event Dispatching Thread, it will run so fast as it cause other threads to stall (or run more slowly) and simply continuously add new instances of Render to pane, which I'm pretty sure you don't want.
It is generally encouraged to override paintComponent instead of paint, as it can cause less issues. You should also, be convention, call super.paintComponent before doing any custom painting.
Instead, simply create an instance of Render and add it to the frame
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Snake {
public static void main(String[] args) {
new Snake();
}
public Snake() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Render());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
class Render extends JComponent {
Render() {
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, 640, 480);
g.setColor(Color.green);
g.fillRect(100, 100, 25, 25);
}
}
}
You are likely going to want to perform some animation, take a look at Concurrency in Swing and How to use Swing Timers for more details
For example

Simple Java Animation using JFrame and JPanel

Ok, so the program's purpose is to just draw and oval and move it across the screen. The code compiles on Eclipse without an error, but when run, no oval is drawn or moved across the screen. I have been researching, and it seems that threads have to do a lot with this, but do I need one for this simple program? I am obviously new to GUI programming with Swing so I would appreciate an explanation or link to one for any additions to the program regarding threads or such related concepts.
public class Game extends JPanel
{
int x =0;
int y =0;
private void moveBall()
{
x+=1;
y+=1;
}
public void paint (Graphics g)
{
super.paint(g);
g.fillOval(x, y, 30, 30);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Animation");
Game game = new Game();
frame.add(game);
frame.setVisible(true);
frame.setSize(300,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
while (true)
{
game.moveBall();
game.repaint();
}
}
}
The likely problem is, that thread is running too fast for the UI, the UI is been shown well after the "ball" has left the visible area.
You need to do a couple of things...
First, you need to make sure that the updates are scheduled properly within the Event Dispatching Thread and secondly, that there is a short delay between updates. For example, 25fps is about a 40 millisecond delay between updates, 60fps is about 16 milliseconds
There are a number of ways to achieve this, depending what it is you hope to achieve, for example, you could simply use Thread.sleep to cause the thread to pause for a small amount of time between updates. The problem with this is Swing is not thread safe and all updates to the UI should be made within the context of the Event Dispatching Thread.
While you program is only simply, it's possible that a paint cycle could run while you updating it's state, resulting in a dirty update.
Another solution might be to use a Swing Timer which will allow you schedule updates at a regular interval which are triggered within the context of the Event Dispatching Thread, making it safer to use.
Have a look at Concurrency in Swing and How to use Swing Timers for more details.
As an example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class BallAnimation {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new BallAnimation();
}
public BallAnimation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int x = 0;
private int y = 0;
public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
moveBall();
repaint();
}
});
timer.start();
}
protected void moveBall() {
x++;
y++;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.fillOval(x, y, 30, 30);
g2d.dispose();
}
}
}
As a side note, unless you really have reason to do so, you should avoid overriding paint and instead use paintComponent
try your loop with sleep as simplest way to fit your code. main is actually a thread. and JFrame creates its own thread.
while (true)
{
game.moveBall();
game.repaint();
try { Thread.sleep(50); } catch (Exception e){}
}
and I just realized, you dont paint your whole screen with a default color.
change your paint method to this
public void paint (Graphics g)
{
super.paint(g);
g.setColor(Color.white); //default color
g.fillRect(0, 0, getWidth(), getHeight()); // fill whole canvas
g.setColor(Color.black); //change color
g.fillOval(x, y, 30, 30); // draw oval
}

Why can I post text with JLabel but not with .drawString

Im not sure what I'm doing wrong as i've seen it done this way countless times before in various open source programs and games. below is my code that is giving me the error that g2 isn't a assigned variable? im confused..
package scratch;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/* FrameDemo.java requires no other files. */
public class okay {
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("helllo", JLabel.CENTER);
emptyLabel.setPreferredSize(new Dimension(250, 100));
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public void paint ( Graphics g ){
Graphics2D g2 = (Graphics2D) g;
g2.drawString("hello",0,0);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
paint(g2);
}
});
}
}
Your class extends no Swing component and so the paint method is not an override and does nothing. Instead you should have your class extend JPanel, put this JPanel into a JFrame, and override paintComponent. Also, 1) always give methods that you think are overriding super methods the #Override annotation. This way the compiler would have told you immediately that what you're doing is wrong. 2) Don't guess when it comes to learning new Java features -- look at and study the appropriate tutorial before trying this stuff. Here the painting in Swing tutorial would have answered these questions for you.
e.g.,
public class Foo extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("hello", 0, 20);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(new Foo());
frame.pack();
frame.setVisible(true);
}
}

JFrame not painting rectangle

Have a very simple issue which I haven't come across before. I used a similar layout before when doing a project.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class q1
{
public static void main (String Args [])
{
q1Window showMe = new q1Window();
}
}
class q1Window
{
q1Window()
{
JFrame window = new JFrame("Tutorial 1");
window.setSize(600,600);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint (Graphics back)
{
back.setColor(Color.black);
back.fillRect(30,30,100,200);
}
}
Now I can't seem to print anything however the JFrame shows.
You can't just add a paint() method to any class. Only Swing components have painting methods.
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
Quick summary is that you need to override the paintComponent() method of a JPanel and then add the panel to the frame.
As camickr pointed out, you need a Swing component to do what you want, which in this case, is to override paint(), although you should be overriding paintComponent() instead.
Try this:
class q1 {
public static void main(String Args[]) {
q1Window showMe = new q1Window();
}
}
class q1Window extends JFrame {
q1Window() {
setTitle("Tutorial 1");
setSize(600, 600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics back) {
back.setColor(Color.black);
back.fillRect(30, 30, 100, 200);
}
}

Categories

Resources