How can I make this custom JButton work? - java

I've looked through so many threads- and none have helped me.
Here is my code:
package myProjects;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.*;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class LukeButton extends JButton{
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setTitle("Luke");
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
LukeButton lb = new LukeButton("Text");
lb.addActionListener(e->{
System.out.println("Clicked");
});
frame.setVisible(true);
}
public LukeButton(String text){
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
Shape rec = new Rectangle2D.Float(10, 10, 60, 80);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(2));
g2.draw(rec);
g2.setColor(Color.BLUE);
g2.fill(rec);
}
}
And the rectangle that is supposed to be there, isn't. I don't know if this is not allowed when extending JButton, but if it's not, I don't know how to fix it. Does anyone have a solution?

A main problem: You don't add your LukeButton instance to the GUI. Solution: add it via a container's add(lb) method.
public static void main(String[] args) {
LukeButton lb = new LukeButton("Text");
JPanel panel = new JPanel();
panel.add(lb);
JFrame frame = new JFrame();
frame.add(panel);
Other problems:
You should override the paintComponent method not the paint method
Call the super's paintComponent method in the override
Override the getPreferredSize of your component.
Don't ignore the String being passed into your constructor's parameter. You'll probably want to pass it into the super's constructor.
You're likely far better off not using inheritance to do whatever it is you're trying to do, that is, to not extend JButton. If you can give us more detail of your overall problem, we can help.

Related

paint() in java with no display

import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
class game extends JFrame {
public game(){ //this is constructor
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(500,500);
frame.setTitle("Hello world");
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Double(60,90,150,100);
g2.draw(line);
}
public static void main(String args[]) {
game l = new game();
}
}
The above code is compiling in java but on running the code it only displays the frame and its title, but does not include any of the lines being drawn using the Graphics2D and Line2D, what is the mistake that is being made??? The frame being displayed does not show any content, why is that???
First, you are creating and displaying a JFrame which is not an instance of game, so there is no chance that it paints what you have in the paint method of game .
You usually don't want to create a subclass of JFrame for custom painting anyway, just create a subclass of JPanel, and set it as the content pane of the frame.
Also don't override paint, but paintComponent, which is the method responsible for painting the current component.
You should also call the parent method of paintComponent, to make sure that all the usual cleaning takes place correctly.
Also by convention, class names should start with an upper case letter.
One last thing, make the frame visible only once you have added all your components, or you may encounter visual glitches some day.
Putting it all together :
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Game extends JPanel {
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
Line2D line = new Line2D.Double(60, 90, 150, 100);
g2.draw(line);
}
public static void main(final String args[]) {
Game l = new Game();
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setTitle("Hello world");
frame.setContentPane(l);
frame.setVisible(true);
}
}
In your constructor call method of JFrame class using this keyword because you extends JFrame class in your class.
public game(){ //this is constructor
/*JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(500,500);
frame.setTitle("Hello world");*/
this.setVisible(true);
this.setSize(500,500);
this.setTitle("Hello world");
}
This solve your problem.
you dont need to create instance of JFrame class ,
modified you constructor as shown below
public game(){ //this is constructor
setVisible(true);
setSize(500,500);
setTitle("Hello world");
}

How would I draw on a JPanel to then be shown on a JFrame?

I've tried to research how Java's 2D rendering works, but I could never understand it. Here is the code in my main class:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main{
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setSize(new Dimension(500,500));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("JFrame testing");
frame.setVisible(true);
Frame panel = new Frame();
frame.add(panel);
}
}
And then here is for the JPanel class:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Frame extends JPanel{
private static final long serialVersionUID = 1L;
public Frame() {
Graphics g = this.getGraphics();
g.drawRect(0, 0, 100, 100);
this.paintComponent(g);
}
}
I am also getting this exception, but I'm not sure what it means:
Exception in thread "main" java.lang.NullPointerException
at Frame.<init>(Frame.java:10)
at Main.main(Main.java:18)
I'm basically just trying to draw a rectangle onto a panel to be shown on the frame I've created. I've heard about the paintComponent method, but I also don't fully understand that.
You should Never use getGraphics() of a Component.
Try below code
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0, 0, 100, 100);
//this.paintComponent(g);
}
Edit
"why is super.paintComponent(g); called again inside the method?"
The documentation of paintComponent says it pretty well:
if you do not invoker super's implementation you must honor the opaque
property, that is if this component is opaque, you must completely
fill in the background in a non-opaque color. If you do not honor the
opaque property you will likely see visual artifacts.

Why JFrame fails to display when thread is invoked?

(I've seen the other 2 questions that are similar to mine in title, but they are different and do not provide a solution to my problem.)
Hi,
I have the below code of simple display of lines. I'm declaring a JFrame in the main, then calling on a new instance of the DrawGraph1 class, passing the JFrame as argument.
In the constructor, I'm invoking a thread (EventQueue.invokeLater). The constructor use the JFrame and use it to create some lines and string and whatever)
(Sorry about improper indentation, it has been tweaked a lot)
package test;
import java.awt.*;
import java.awt.geom.*;
import java.text.DateFormatSymbols;
import javax.swing.*;
public class test {
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.setVisible(true);
DrawGraph1 obj = new DrawGraph1(frame);
}
}
class DrawGraph1{
DrawGraph1(final JFrame frame){
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
frame.setTitle("LineDrawing");
frame.add(new JComponent()
{
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Double();
int decrement = 0, label = 0;
g2.setColor(Color.red);
g.drawString("Red Line ->> High temperatures", 330, 110);
g2.setColor(Color.green);
g.drawString("Green Line ->> Low temperatures", 330, 130);
} });}});}}
So According to my testing, the program reaches the constructor, passes the frame, and starts the thread, but apparently it stops at the line
frame.add(new JComponent()
With the NetBeans debugger underlining (or something) the add method. I also tried in which I invoke the thread at the main, pass the JFrame to the constructor, jump to it and it also stops at the same statement.
The display is simply the Frame itself with whatever settings prior to the add statement (i.e. in the main settings such as size).
I'm pretty sure it is very silly problem since it worked yesterday, not sure what I changed, but I just gave up.
I just changed the order of these two lines.
frame.setVisible(true);
DrawGraph1 obj = new DrawGraph1(frame);
to
DrawGraph1 obj = new DrawGraph1(frame);
frame.setVisible(true);
and the output:
Primarily, you passed the JFrame to the JPanel. You should create the JPanel, and pass it to the JFrame.
Here are the major changes I made.
All of the Swing GUI creation has to be on the Event Dispatch Thread. This includes the JFrame and the JPanel. I added a Runnable to the main method, and called the EventQueue invokeLater method to start the Swing GUI on the Event Dispatch Thread.
I moved all the JFrame code in the main method, and all of the JPanel drawing code in the DrawGraph1 class paintComponent method. The paintComponent method is for painting only. Do your other processing in other classes and / or other methods.
The JFrame methods have to be called in a specific order. Call the JFrame methods in the same order that I called them in your code.
I added a call to super.paintComponent to your paintComponent method. This maintains the Swing paint chain and clears the drawing panel.
I moved the sizing of the GUI from the JFrame to the JPanel. You're concerned with the size of the drawing panel, not the entire GUI.
Here's the revised code. I renamed the class so that it wouldn't conflict with other code in my testing package. You should change it back.
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SimpleJPanelTest {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
final JFrame frame = new JFrame("Line Drawing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawGraph1());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
};
EventQueue.invokeLater(runnable);
}
}
class DrawGraph1 extends JPanel {
private static final long serialVersionUID = 6733473371292195071L;
public DrawGraph1() {
setPreferredSize(new Dimension(800, 700));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Double();
int decrement = 0, label = 0;
g2.setColor(Color.red);
g.drawString("Red Line ->> High temperatures", 330, 110);
g2.setColor(Color.green);
g.drawString("Green Line ->> Low temperatures", 330, 130);
}
}

Failing to draw Image to JFrame

first I want to apologize for any mistakes, I'm not speaking english well, I'm new to Java and I'm new to Stackoverflow. Please be kind!
I keep failing to draw a simple image to screen. I tried everything, but I keep failing and I'm getting more and more confused. Here's my Sourcecode:
package com.Animation;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Class1 extends JFrame{
private BufferedImage backgroundImg;
public Class1(){
this.setTitle("Animation");
this.setSize(1080, 720);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
LoadContent();
}
public static void main(String[] args){
new Class1();
}
private void LoadContent()
{
try
{
URL backgroundImgUrl = this.getClass().getResource("Back.jpg");
backgroundImg = ImageIO.read(backgroundImgUrl);
}
catch (IOException ex) {
System.err.println("Fehler!");
}
}
public void Draw(Graphics2D g2d)
{
g2d.drawImage(backgroundImg, 0, 0, null);
}
}
So what happens is, that a JFrame window opens with nothing to see on it. I think that's beacuse the Draw() method doesn't get called. But when I add like "Draw(g2d);" somewhere, I keep getting a NullPointerException. The picture "Back.jpg" is located in the same package as the class. I'm using eClipse and the JRE JavaSE 1.7.
I really hope you can help me, im totally exhausted by all my tries to figure out what's the problem. It would be cool if you could write the correct code into the answers and explain what I've done wrong. Remember, I'm new to all this.
Thanks a lot!
There are a lot of ways to do that. Examples
1) JLabel. //Not recommended
Add the JLabel in your JFrame, then do label.setIcon(backgroundImg);
2) JPanel
Override the paint() method in JPanel(make sure you've added it to your JFrame).
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(backgroundImg, 0, 0, this);
}
Try this. Here I have set the image to a JPanel instead of directly setting it to JFrame.
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
/**
*
* #author Rumesh
*/
public class Test extends JFrame{
public static void main(String[] args) throws IOException {
JFrame frame = buildFrame();
final BufferedImage image = ImageIO.read(new File("1.jpg"));
JPanel pane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
frame.add(pane);
}
private static JFrame buildFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
return frame;
}
}
I don't know if this is what you're searching for:
ImageIcon image = new ImageIcon("src/media/Image.jpg");
JLabel lblImg = new JLabel("", image, JLabel.CENTER);
lblImg.setBounds(..., ..., ..., ...);
add(lblImg);
This way you'll add an image to a JLabel and than place it on the screen. I hope it helps in some way.

How can I resize and paintComponent inside a frame

Write a program that fills the window with a larrge ellipse. The ellipse shoud touch the window boundaries, even if the window is resized.
I have the following code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,150,200);
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
And the main class:
import javax.swing.JFrame;
public class EllipseViewer {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(150, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
EllipseComponent component = new EllipseComponent();
frame.add(component);
frame.setVisible(true);
}
}
in your EllipseComponent you do:
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,getWidth(),getHeight());
I'd also recommend the changes given by Hovercraft Full Of Eels. In this simple case it might not be an issue but as the paintComponent method grows in complexity you realy want as little as possible to be computed in the paintComponent method.
Do not resize components within paintComponent. In fact, do not create objects or do any program logic within this method. The method needs to be lean, fast as possible, do drawing, and that's it. You must understand that you do not have complete control over when or even if this method is called, and you certainly don't want to add code to it unnecessarily that may slow it down.
You should create your ellipse in the class's constructor. To resize it according to the JComponent's size and on change of size, use a ComponentListener.:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
Ellipse2D ellipse = null;
public EllipseComponent {
ellipse = new Ellipse2D.Double(0,0,150,200);
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
// set the size of your ellipse here
// based on the component's width and height
}
});
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
Caveat: code not run nor tested

Categories