my Jlabel is not showing up - java

The Jlabel is not showing up when I put it in the paint(Graphics2d g) method and I can't figure out why.
My text class:
import java.awt.Color;
import java.awt.Graphics2D;
import javax.swing.JLabel;
public class Text {
int ballX,ballY,squareX,squareY;
Text text;
private Game game;
private Ball ball;
private Racquet racquet;
public void main(){
ballX = ball.getBallX();
ballY = ball.getBallY();
squareX = racquet.getSquareX();
squareY = racquet.getSquareY();
}
public void paint(Graphics2D g) {
g.setColor(Color.red);
JLabel balltext = new JLabel("the ball is at " + ballX + ballY);
balltext.setVisible(true);
g.setColor(Color.green);
JLabel squaretext = new JLabel("the ball is at " + squareX + squareY);
squaretext.setVisible(true);
}
}

There are a few things not quite right with your code.
Firstly, Text does not extend from anything that is paintable, so paint will never be called. Convention tends to favor overriding paintComponent of Swing components anyway.
Also, you should always call super.paintXxx, this would have highlighted the problem in the first place.
Secondly, components are normally added to some kind container which takes care of painting them for you.
If you want to use Swing components in your program, I'd suggest taking a look at Creating a GUI With JFC/Swing.
If you want to paint text, I'd suggest you take a look at 2D Graphics, in particular Working with Text APIs
An bit more information about what it is you're trying to achieve might also help
Also, I'm not sure if this deliberate or not, but public void main(){ ins't going to act as the main entry point of the program, it should be public static void main(String args[]), but you might just be using main as means to call into the class from else where ;)

From the look of things you are missing quite a few paradigms / idioms for a Java Swing gui.
For example:
Text should extend JComponent if you want to override paint / paintComponent to specify how the component should be drawn.
You should create a separate Main class to serve as an entrypoint to your program (you don't have to, but it helps you keep things logically separated for now, which is easier conceptualize mentally for you)
You need to create a JFrame inside your main method, then create the Text class and add it to JFrame and call pack() and setVisible(True) on the JFrame.
I would recommend looking at some examples first to get oriented:
http://zetcode.com/tutorials/javaswingtutorial/firstprograms/
http://www.javabeginner.com/java-swing/java-swing-tutorial

Related

Cant draw a shape to a specific panel in a NetBeans GUI

I'm trying to make a simple application to draw shapes to a panel in a jFrame. The GUI is a NetBeans generated jFrame. The application has three panels. the first two hold button groups to select the shape and a color. There's a button to draw the shape to the third panel once the selections are made.
What the GUI looks like
Unfortunately I'm having no love and can't make it work. For now I just want to get the button to draw a shape then I'll add the button functionality. Here's the code I have so far.
private void btnDrawShapeActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Draw shape = new Draw();
pnlDrawPad.add(shape); //pnlDrawPad is the name of the jPanel
shape.drawing();
}
import javax.swing.*;
import java.awt.*;
public class Draw extends JPanel{
public Draw(){
super();
}
public void drawing(){
repaint();
}
//#Override <-- gives error "method does not override or implement a method from a supertype"
public void paintCompnent(Graphics g){
super.paintComponent(g);
g.setColor(Color.RED);
g.drawString("Hello World!",40,30);
}
}
When I click the "Draw Shape" button nothing happens. I've been searching for a couple days now and am not finding the answer. Actually, its making me more confused as to what to do.
How to deal with this?
Don't keep creating new panels for each shape.
Instead you need a single panel with an ArrayList of objects you want to paint. Then you customize the paintComponent(...) method of the panel to iterate through all the objects in the panel and paint them.
So you button will just add another object to the ArrayList and then invoke repaint() on the panel.
Check out Custom Painting Approaches. The DrawOnComponent example shows how to paint a Rectangle objects from an ArrayList to get you started.
I found that with NetBeans you don't need to Override the paintComponents() method. Since all the GUI stuff is done when you design it, you merely need to add the drawings to the panel or what ever you need to do. I found you that by declaring and instantiating a 2D graphics object then drawing it to the place you want.
private void btnDrawShapeActionPerformed(java.awt.event.ActionEvent evt) {
int centerX;
int centerY;
Graphics2D drawFx = (Graphics2D)pnlDrawPad.getGraphics();
drawFx.setColor(Color.ORANGE);
centerX = (int)(458*Math.random());
centerY = (int)(440*Math.random());
drawFx.fillOval(centerX-50, centerY-50, 100, 100);
drawFx.dispose();
}
Worked like a charm so now every time I push the draw shape button it draws a shape to the panel in a different location every time. I've since put in the radio button functionality to change shape color and fill and added a button to clear the screen.
Not sure if this is the ideal way to do it but for this stupid simple little program it works well enough and I'm done stressing over it.

Java AWT troubleshooting

So I've been trying to create a simple graphics program to run on Windows 10. From what I can infer, this is how my textbook would like me to create this program:
import java.awt.*;
public class DrawLine1 {
public static void main (String[]args) {
DrawingPanel panel = new DrawingPanel(1281, 721);
Graphics g = panel.getGraphics();
g.drawLine(1, 1, 69, 69);
}
}
However, when I try to compile it, cmd returns the following error:
D
rawLine1.java:4: error: cannot access DrawingPanel
DrawingPanel panel = new DrawingPanel(1281, 721);
^
bad source file: .\DrawingPanel.java
file does not contain class DrawingPanel
Please remove or make sure it appears in the correct subdirectory of the sourcepath.
1 error
Is this an error with the code I wrote or with how I set up Java, and how do I fix it?
Looks like the code you've written is incomplete -- the compiler appears to be complaining that it can't find the DrawingPanel class, and if it doesn't exist, then you also need to create and compile the DrawingPanel code first. But having said that, I wouldn't recommend that you use this code or whatever tutorial suggests it as it's making some key bad recommendations
For one, you need to display any drawing JPanel (assuming DrawingPanel is a JPanel) in a top level window for it to be displayed. For Swing GUI's this would mean you would need to create a JFrame and put the drawing JPanel into it, and then set the JFrame as visible via setVisible(true)
Drawing with a components Graphics object in this way -- by calling getGraphics() is not recommended as the Graphics object obtained in this fashion is not guaranteed to persist. For instance, assuming that you get this code to work, if you minimized and restored your GUI, your line would disappear.
Swing and AWT graphics are passive -- you would override your JPanel's paintComponent method and do your drawing inside of this method.
You should start Swing and AWT GUI's on the Swing event thread. This is usually done by placing this code into a Runnable's run() method and then passing the Runnable into a SwingUtilities.invokeLater(...) method call.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
public class SimpleLine extends JPanel {
private static final int PANEL_WIDTH = 400;
public SimpleLine() {
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_WIDTH));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // so JPanel can do its own housekeeping graphics
int x1 = 1;
int y1 = x1;
int x2 = PANEL_WIDTH - 2;
int y2 = x2;
g.drawLine(x1, y1, x2, y2);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SimpleLine");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleLine());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Looks like you're working with the textbook Building Java Programs. I was able to reproduce your problem, which is not a problem with your code nor with how you have setup Java (assuming you are running Java 8).
Your code is referencing another java class, DrawingPanel, provided by the textbook's author on the author's website.
To continue on your learning path with that textbook, and to get your program to compile, you'll need to download the DrawingPanel class from the textbook website:
http://www.buildingjavaprograms.com/DrawingPanel.java
Then put that java file in the same location as your DrawLine1.java file.
Recompile as you did before, and your code should compile with no errors.

Simple animations in Java

I'm attempting to code a simple animation or physics example in a Java Swing application. I have the actual windows application open and working, but I can't figure out how to actually draw my shapes, and how I'd format the code for calculations between frames, that sort of stuff.
I've read some stuff about over riding a paint method, but I don't know what that means, and I don't believe I'm using it in the code I'm using right now. This is my code:
public class Physics extends JFrame{
public Physics() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
getContentPane().add(panel);
panel.setLayout(null);
final JLabel label = new JLabel("Hi, press the button to do something");
label.setBounds(20, 0, 2000, 60);
final JButton submitButton = new JButton("Start");
submitButton.setBounds(20, 150, 80, 20);
submitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Put button code here later
}
});
panel.add(label);
panel.add(submitButton);
setTitle("Program");
setSize(300, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Physics ex = new Physics();
ex.setVisible(true);
}
});
}
}
So I have some blank space above my button where I'd like to draw maybe a square or circle moving across the screen to start off with, once I get that down I can start getting into the more advanced stuff. Any hints on how to do that would be appriciated :D
Thanks!
"I've read some stuff about over riding a paint method, but I don't know what that means"
So you've overridden actionPerformed, so you know what an #Override is. As you'll notice from the ActionListener, you never actually explicitly call actionPerformed, but whatever you put in the there, still get's used. That's because the ActionListener implicitly call it for you.
The same is true with painting. In the Swing painting process, there is a paint chain that Swing uses to paint components. Along the way paint is called somewhere. So just like actionPerformed, you can override paint and it will get implicitly called for you.
#Override
public void paint(Graphics g) {
super.paint(g);
}
The Graphics object passed to the method is the graphics context that Swing will use for the painting. You can look at the Graphics API to see the methods you can use. You can use drawOval to draw a circle
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawOval(x, y, width, height);
}
Now here's the thing. You don't actually want to override paint. In the tutorials linked above, some of the examples will use applets and override paint, but you shouldn'y paint on top level containers like JFrame or JApplet. Instead paint on a JPanel or JComponent and just add it the JFrame. When you do paint on JPanel or JComponent, you'll instead override paintComponent (which also gets called along the paint chain), instead of paint
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, width, height);
}
You see how I used variables for the drawOval method. The x is the x location from the top-let of the screen, and y and the y point. width and height are width and height of the circle. The great thing about using variables is that their values can be changed at runtime.
That's where the animation comes to play. As pointed out, you an use a javax.swing.Timer
The basic construct is
public Timer(int delay, ActionListener listener) {
}
The delay is the milliseconds to delay each call to the listener. The listener will have your actionPerformed call back that will do what's inside, every delay milliseconds. So what you can do, is just change the x from the drawOval and repaint(), and it will animate. Something like
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
x += 5;
repaint();
}
});
timer.start();
The timer code you can just put in the constructor. That's probably simplest explanation I can give. Hope it helps.
Don't forget the to see Custom Painting and Grapics2D for more advance topics on graphics. Also see some example of timers and animation here and here and here and here and here
Also avoid using null layouts. See Laying out Components Within a Container to learn how to use layout managers, as should be done with Swing apps.
Take a look at the Swing tutorial on Custom Painting.
The example shows you how to do painting. If you want animation, then you would use a Swing Timer to schedule the animation. The tutorial also has a section on How to use a Swing Timer.
Put the two tutorial together and you have a solution.
There are any number of ways to achieve this.
Start by taking a look at:
Performing Custom Painting
2D Graphics
For details about how painting in Swing is done.
Animation is not as simple as just pausing a small period of time and then repainting, theres acceleration and deceleration and other concepts that need to be considered.
While you could write your own, that's not a small task, a better solution might be to use a pre-existing engine, for example...
Then take a look at:
Timing Framework
Trident
java-universal-tween-engine
Which are all examples of animation engines in Swing. While I prefer the Timing Framework as it provides me with a lower level API, this is a personal opinion. Both Trident and the JUWE seem to be geared more towards component/property based animation (which the Timing Framework can do if you want to build some of the feature sets up)
I created a simple animation with two rockets blasting off. The full eclipse project is here: https://github.com/CoachEd/JavaExamples/tree/master/RaceToSpace. Here's a screenshot:

paintComponent method mixes different JPanel components

I'm developing a software which paints 2 different JPanel for my GUI: a score and a mast guitar. The score is a class which extends JPanel and has paintComponent() method like this:
public class PanelPartitura extends JPanel implements MouseListener{
public void paintComponent(Graphics comp){
super.paintComponent(comp);
comp2D = (Graphics2D)comp;
comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground();
paintStave();
paintNotes();
[...]
}
}
The mast guitar is a class as well:
public class PanelGuitarra extends JPanel implements MouseListener
public void paintComponent(Graphics comp){
super.paintComponent(comp);
comp2D = (Graphics2D)comp;
comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//Then I call secondary methods to paint it:
paintBackground();
PaintPoints();
}
[...]
}
It still works fine. I add the class PanelPartitura to a JScrollPane in order to scroll when it's playing:
partitura = new PanelPartitura();
JScrollPartitura = new JScrollPane(partitura, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
Both JPanels mix each others painted components when the software is playing and scrolling. I would like to ask, if somebody has a clue about what on earth is going on? In my opinion:
It could be because I separated the painting methods as we've seen above:
paintBackground();
paintStave();
paintNotes();
then, when the software starts to paint, it paints some parts of the first JPanel (paintBackground() for example) and then some parts of the mast guitar (paintBackground()), then it changes again and the result is a mixture of both.
I think this is because it mixes different parts every time, I mean it doesn't behave in the same way every time it plays.
I really don't want this to be happening, so let me ask you: how can I make atomic methods to be sure this wouldn't be the problem?
I missunderstood the scroll method. I scroll on this way:
//the note playing currently position is saved in positionBar
positionBar = 150 + 50*PGuitarra.composicion.getAcordeSeleccionado().getPosicionXAcorde();
//horizontalScrollBar is moved to this position
PGuitarra.JScrollPartitura.getHorizontalScrollBar().setValue(positionBar);
I see that your paint methods are not using the same Graphics object (at the JPanel scope). Could that be the reason? And if it is, try passing comp (the Graphics object) as a parameter to paintBackground, paintStave and paintNotes.

Saving JPanel Graphics

I'm not quite sure exactly how Graphics work in Java so I having trouble debugging my problem.
I have a Class MyFrame Extends JPanel. Now I do some drawing on MyFrame save and save me properties about that certain frame then add it an ArrayList collection of MyFrames. Later on I want to recall the properties a certain instance of MyFrame and repaint that frame on the screen. Having the the graphic of frame show up again is what I am having trouble with.
Here is a quick bit of code that will demonstrate my problem.
public class MyFrame extends JPanel{
private int property;
private int x;
private int y;
public MyFrame(int xp, int yp){
x = xp;
y = yp;
}
#override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(x,y,5,5);
}
public void setProperty(int p){
property = p;
}
}
public class MainClass() extends JPanel{
private ArrayList<MyFrame> frames = new ArrayList<MyFrame>;
private MyFrame currentFrame = new MyFrame();
public void addFrame(int x, int y){
this.remove(currentFrame);
currentFrame = new MyFrame();
this.add(currentFrame);
frames.add(currentFrame);
}
public void setFrame(int frame){
this.remove(currentFrame);
currentFrame = frames.get(frame);
this.add(currentFrame);
}
}
Summary:
I'd like the panel to display the correct frame when setFrame is called. currently when I do this set frame will be blank.
You seem to be swapping JPanels in and out of another JPanel, and when doing this, you must take into consideration the layout used by the container-JPanel and you would need to call revalidate and repaint on the container-JPanel after the swap.
But rather than mess with all of this, why not go the easy route by just swaping JPanels or perhaps JLabels with ImageIcons holding an image using a CardLayout?
You could also consider adding some states, an enum data member, to a single JPanel and ask it to switch from one state to another, then call its repaint method and, in its paintComponent overriden method, draw some graphics according to its state.
Your architecture (as enhance by #Hovercraft Full of Eels is also good, even better if the draw methods vary quite a lot and have very different purposes. However, my proposal could lay to a faster app, and could allow other fatures such as transition between states, shared double buffer, variable/code reuse in case graphics are close.
What is your app doing ?
Regards,
Stéphane

Categories