Looking for an explanation (documentation?) for "add(new Surface());" - java

I found this code online and it works for my application. I'm trying to trace through and understand it more thoroughly. I don't find any documentation that explains the use of the "add(new Surface());" statement. I understand what it does, but here is what I don't understand:
How does the add() method work without a "SomeObject." in front of it. It seems to assume the add() method is for the object (SampleAddMethod) which contains it. I can't find any documentation on how or when this is valid.
Why does "super.add(new Surface()); work, but ""SampleAddMethod.add(new Surface());" fail? It seems the add() method is inherited from Component and SampleAddMethod is a JFrame which is a Component.
Am I correct that (new Surface()) creates an "anonymous class"?
(Sample code below)
package testMainMethod;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
class Surface extends JPanel {
private void doDrawing(Graphics g, int x) {
double xd = (double) x;
Graphics2D g2d = (Graphics2D) g;
// Code to draw line image goes here
}
#Override
public void paintComponent(Graphics g) {
for (int i = 0; i < 512; i++) {
// super.paintComponent(g); // this erases each line
doDrawing(g, i);
}
}
}
public class SampleAddMethod extends JFrame {
public SampleAddMethod() {
initUI();
}
private void initUI() {
setTitle("Lines");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new Surface());
setSize(650, 350);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SampleAddMethod lines = new SampleAddMethod();
lines.setVisible(true);
}
});
}
}

Why does "super.add(new Surface()); work, but ""SampleAddMethod.add(new Surface());" fail?
Because add(Component) is an instance method on Container, basically - and SampleAddMethod is a subclass of Container, indirectly. So the add call in initUI is implicitly this.add(new Surface()). You can't call it as SampleAddMethod.add because that would only work if it were a static method.
Am I correct that (new Surface()) creates an "anonymous class"?
No. It's just calling a constructor. The code is equivalent to:
Surface surface = new Surface();
add(surface);
The only anonymous type in the code you've shown us is in main, where it creates a new anonymous class implementing Runnable.

Related

Calling #Override on paintComponent() when state changes

How do I override a paintComponent method with response to a state change?
Error message: void is an invalid type for the variable paintComponent
public class MyContainer extends Container {
public void paintComponent(Graphics m){
m.drawArc(100,100,100,100,100,100);
m.setColor(Color.green);
m.fillArc(100,100,100,100,100,100);
}
public static void main(String[] args){
Container y = new Container();
JFrame x = new JFrame();
JPanel gg = new JPanel();
x.add(y);
x.setTitle(" Shape Changer");
x.setBounds(100,50,500,300);
x.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x.getContentPane().add(new ContentPanel());
x.getContentPane().add(new ContnetPanel());
x.setContentPane(new ContnetPanel());
x.setVisible(true);
}
static class ContentPanel extends JPanel{
private Graphics g;
private JPanel ss;
public void paint(Graphics g){
g.drawArc(100,100,100,100,100,100);
g.fillRect(100, 100,100,100);
}
public ContentPanel(){
}
}
static class ContnetPanel extends JPanel implements ActionListener, ChangeListener{
JComboBox comboerbox;
class appres {
public void paint(Graphics h){
h.drawRect(100,100,100,100);
h.setColor(Color.red);
h.fillRect(100,100,100,100);
}
}
public ContnetPanel(){
comboerbox = new JComboBox();
comboerbox.addItem("Red Square");
comboerbox.addItem("Blue Square");
comboerbox.addItem("Green Square");
comboerbox.setSelectedIndex(1);
add(comboerbox);
setLayout(new GridLayout(2,1));
}
#Override
protected void paintComponent(Graphics h){
super.paintComponent(h);
h.drawArc(100,100,100,100,100,100);
h.setColor(Color.blue);
h.fillArc(100,100,100,100,100,100);
repaint();
}
int yy = 0;
public void actionPerformed(ActionEvent evt){
switch(comboerbox.getSelectedIndex()){
case 0:yy=0;
case 1: yy=1;
case 2: yy=2;
}
}
//evt.getSource()==comboerbox
public void stateChanged(ChangeEvent evt){
if(evt.getSource()==comboerbox){
#Override
protected void paintComponent(Graphics h){
super.paintComponent(h);
h.drawArc(100,100,100,100,100,100);
h.setColor(Color.blue);
h.fillArc(100,100,100,100,100,100);
repaint();
}
}
else
{
System.out.println("DONE");
}
}
}
}
Of course, the paintComponent method isn't a variable. How would I override paintComponent here? Or is a better way to change the shape with response to state change? That would be great too!
Thanks in advance, love you guys!
In your last question: How do I make the superclass go beyond just the content pane? you were given a link to the Swing tutorial for some Swing basics.
Well there is also a section on Custom Painting for you to read. You can then download the example and play with it to understand how painting works.
Basically the Container class doesn't have a paintComponent() method so you should not be trying to do custom painting in that class.
If you want to change a painting property, then you need to add a method to your class to change the state of the property and then invoke repaint() on itself.
So from the tutorial example in Step 3 you can see how the moveSquare(...) method changes the state of the class and then invokes repaint().
Note you should never invoke repaint() in the paintComponent() method since this will cause the painting to be continually rescheduled.

Java Graphics Update/Repaint Graphic

I'm trying to work with the Java paint
utility and it's been a bit of a hassle.
I'm trying to do something which I assume is quite basic.
I'm drawing a square Graphic to a JPanel and then trying
to move it using repaint
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
public class testGui {
static gui gc_gui;
static int gv_x;
static int gv_y;
public static void main(String[] args) {
gc_gui = new gui();
gv_x = 50;
gv_y = 50;
gc_gui.cv_frame.setVisible(true);
}
public static class gui {
JFrame cv_frame;
content cv_content;
public gui() {
cv_frame = new JFrame();
cv_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cv_frame.setTitle("Test GUI");
cv_frame.setSize(600, 400);
cv_frame.setLayout(new FlowLayout());
cv_content = new content();
cv_content.setBackground(Color.Black);
cv_content.setPreferredSize(new Dimension(500, 300));
cv_frame.add(cv_content);
gv_x = 0;
gv_y = 0;
cv_content.update();
}
}
public static class content extends JPanel {
public void paint(Graphics graphic) {
super.paint(graphic);
draw(graphic);
}
public void update() {
super.repaint();
}
public void draw(Graphics graphic) {
Graphics2D graphic2D = (Graphics2D) graphic;
graphic2D.setPaint(Color.Red);
graphic2D.fillRect(gv_x, gv_y, 100, 100);
}
}
}
I don't know why the call to the update function isn't doing
anything though.
It draws the square at 50x and 50y, the sets it to 0x and 0y
immediately and then when I call repaint I expected it to
be moved to it's new coordinates although it's still at
50x and 50y.
Why is this?
Your solution is to use KeyBindings.
https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
and also.
You need to create a Swing Timer, Thread, or Loop , that manages the frames to be painted. and such
Here is a link for Swing Timers as they are pretty easy to implement:
https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
A lot of programs I see also have this ( AKA. working with threads.):
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});

Java painting program giving many errors

I want to make a simple painting program. So,when you drag your mouse a line will draw in a GUI. The problem is when the user drags the mouse, it will paint automatically, but my code doesn't work. Can someone please tell me how do this? Sorry for my English and if you don't understand my question, look at my code maybe you will than.
My main class:
import javax.swing.JFrame;
public class MainClass {
public static void main(String args[]){
tuna kip = new tuna();
kip.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
kip.setSize(800,600);
kip.setVisible(true);
}
}
This is my other class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class tuna extends JFrame {
JPanel jpanel = new JPanel();
public tuna(){
super("Painting Program");
jpanel.setBackground(Color.WHITE);
add(jpanel);
hand handler = new hand();
jpanel.addMouseListener(handler);
jpanel.addMouseMotionListener(handler);
}
private class hand implements MouseListener ,MouseMotionListener { //THE ERRORS START TO APPEAR HERE
public void mouseDragged(MouseEvent event){
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(event.getX(), event.getY(), 5, 5);
}
}
}
}
When I try to run the code I get too much error messages:
You mean when you try to compile the code you get compile errors.
class hand implements MouseListener ,MouseMotionListener
Your class does not implement all the methods in those listeners. You only implement one method.
Read the section from the Swing tutorial on How to Write a MouseMotionListener for a working example.
If you only care about the mouseDragged() method then you only need to implement the MouseMotionListener.
Or as a simpler solution you can extend MouseMotionAdapter. This class implements all the methods of the MouseMotionListener so you only need to override the methods you want to change. The tutorial also discusses adapters.
Finally class names SHOULD start with an upper case character. Look at the Java API and you will notice this. Follow the Java conventions and don't make up your own.
Yes, there are so many issues in your codes. I just edited it and make it runnable at least. Just study and experiment on it. I hope you will learn something out of this even if I don't explain all of the changes.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class tuna extends JFrame {
int x, y, w, h;
MyPanel jpanel = new MyPanel();
public tuna(){
super("Painting Program");
setLayout(new BorderLayout());
jpanel.setBackground(Color.WHITE);
add(jpanel);
hand handler = new hand();
jpanel.addMouseListener(handler);
jpanel.addMouseMotionListener(handler);
}
private class hand implements MouseListener , MouseMotionListener { //THE ERRORS START TO APPEAR HERE
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
x=e.getX();
y=e.getY();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
w = e.getX() - x;
h = e.getY() - y;
jpanel.repaint();
}
public void mouseMoved(MouseEvent e) {
}
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(x, y, w, h);
}
}
}

Java getGraphics() returning null

I'm starting to learn to create Games in Java, and one of the methods I'm using includes BufferedImage. This is the error I get:
"Exception in thread "main" java.lang.NullPointerException
at tm.Game.init(Game.java:48)
at tm.Game.<init>(Game.java:54)"
From this code:
package tm;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel implements Runnable {
private Settings Settings;
private Thread t;
private BufferedImage offscreenImage;
private Graphics offscr;
public void run() {
while(true) {
repaint();
try {
Thread.sleep(1000/30);
} catch (InterruptedException e) { }
}
}
public void paint(Graphics g) {
offscr.setColor(Color.blue);
offscr.fillRect(0, 0, Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
offscr.setColor(Color.white);
offscr.drawString("Lolz", 10, 10);
g.drawImage(offscreenImage, 0, 0, this);
}
public void update(Graphics g) {
paint(g);
}
public void init() {
t = new Thread(this);
t.start();
offscreenImage = (BufferedImage) createImage(Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
offscr = offscreenImage.getGraphics();
}
public Game() {
Settings = new Settings();
init();
}
}
Settings Class:
package tm;
public class Settings {
public final int GAME_WIDTH = 500;
public final int GAME_HEIGHT = 500;
}
Screen Class:
package tm;
import javax.swing.JFrame;
public class Screen extends JFrame {
private static final long serialVersionUID = 1L;
private JFrame mainScreen;
private Game mainGame;
private Settings Settings;
public Screen() {
mainGame = new Game();
Settings = new Settings();
mainScreen = new JFrame();
mainScreen.add(mainGame);
mainScreen.setSize(Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
mainScreen.setTitle("Lolz");
mainScreen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainScreen.setResizable(false);
mainScreen.setVisible(true);
}
public static void main(String[] args) {
new Screen();
}
}
It is not getGraphics() that returns null but rather the previous function createImage(). From the Component documentation for createImage():
returns an off-screen drawable image, which can be used for double
buffering. The return value may be null if the component is not
displayable. This will always happen if
GraphicsEnvironment.isHeadless() returns true.
You then get a NullPointerException when calling getGraphics() on offscreenImage which is null.
The reason that throw NullPointer exception is that you initialized the offScreenImage and offScr in wrong place.
offscreenImage = (BufferedImage) createImage(Settings.GAME`WIDTH, Settings.GAME_HEIGHT);
offscr = offscreenImage.getGraphics();
This code should be in the function paint. To get the results the Game class should be defined like this. And another tip it is better to declare variables inn Settings class to public static final so that they can be accessed in static way. Make little change to your Game class as defined below. I think this should help you.
package tm;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import tm.Screen.Settings;
public class Game extends JPanel implements Runnable {
// private Setting Settings;
private Thread t;
private BufferedImage offscreenImage;
private Graphics offscr;
public void run() {
while (true) {
repaint();
try {
Thread.sleep(1000 / 30);
} catch (InterruptedException e) {
}
}
}
public void paint(Graphics g) {
if (offscreenImage == null) {
offscreenImage = (BufferedImage) createImage(Settings.GAME_WIDTH,
Settings.GAME_HEIGHT);
}
offscr = offscreenImage.getGraphics();
offscr.setColor(Color.black);
offscr.fillRect(0, 0, Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
offscr.setColor(Color.white);
offscr.drawString("Lolz", 10, 10);
g.drawImage(offscreenImage, 0, 0, this);
}
public void update(Graphics g) {
paint(g);
}
public void init() {
t = new Thread(this);
t.start();
}
public Game() {
init();
}
}
Since createImage only works after the Component is "displayable" e.g. it is attached to a visible JFrame your current code wont work.
There are several ways you can deal with it.
Add JFrame as a parameter to the ctor and add the Game to the JFrame before calling create component - this should work as long as JFrame.add does not call any methods overridden by the partially initialized Game instance.
Game(JFrame jf){
jf.add(this);
...
}
JFrame mainFrame = new JFrame();
mainFrame.setVisible(true);
Game game = new Game(mainFrame);
Make an additional init method which is called after adding Game to the JFrame. This is ugly since the Game object is not really fully initialized until this method is called.
Game game = new Game();
JFrame mainFrame = new JFrame();
mainFrame.add(game);
mainFrame.setVisible(true);
game.init();
One way to find out when the component is displayable is to listen for a HierarchyEvent. You could modify the Listener shown in the answer to call createImage instead of printing "showing". (The class provided by that answer also needs a extends HierarchyListener to work)

Java function that gets called every frame

I was wondering if there was a function like void draw() which Processing programming language uses that gets called every frame. Or even just a function that loops infinitely when it gets called but only runs through it every time there is a new frame. I heard of something called a runnable in java how do i go about using this? also is there a better way then having a runnable with a delay like a function that is hardcoded to run every frame. Oh and also what is the function call that will allow me to see how much time (in milliseconds preferably) since the application has started running that way i can make my runnables / frame calls much more precise so that the game runs about the same speed on every computer regardless of the frame rate.
Perhaps you need something like this
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Repainter extends JPanel {
private Point topLeft;
private int increamentX = 5;
public Repainter() {
topLeft = new Point(100, 100);
}
public void move() {
topLeft.x += increamentX;
if (topLeft.x >= 200 || topLeft.x <= 100) {
increamentX = -increamentX;
}
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(topLeft.x, topLeft.y, 100, 100);
}
public void startAnimation() {
SwingWorker<Object, Object> sw = new SwingWorker<Object, Object>() {
#Override
protected Object doInBackground() throws Exception {
while (true) {
move();
Thread.sleep(100);
}
}
};
sw.execute();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Repaint Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
Repainter repainter = new Repainter();
frame.add(repainter);
repainter.startAnimation();
frame.setVisible(true);
}
});
}
}

Categories

Resources