import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyDrawPanel extends JPanel{
public void paintComponents(Graphics g){
g.setColor(Color.orange);
g.fillRect(20,50,100,100);
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.getContentPane().add(paintComponents(g));
frame.setVisible(true);
}
}
I think I should add something arguments in frame.getContentPane().add(paintComponents(g));.
I looked up Graphics class but I'm still struggling with it. What should be the parameter of it?
try this
public class MyDrawPanel extends JPanel{
MyDrawPanel()
{
setOpaque(true);
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.orange);
g.fillRect(20,50,100,100);
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyDrawPanel());
frame.setBounds(10,10,500, 500);
frame.setVisible(true);
}
}
I'm no awt expert, but what I think you want to do is add a Canvas object to your content pane from the JFrame, then paint a Graphics object on it.
Okay, this is what I came up with:
public class MyDrawPanel extends JPanel
{
private static void createAndShowGUI()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
MyDrawPanel panel = new MyDrawPanel();
panel.setOpaque(true);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.orange);
g.fillRect(20,50,100,100);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run()
{
createAndShowGUI();
}
});
}
}
Notes:
There are several problems with your line frame.getContentPane().add(paintComponents(g));. What you said is "add to the content pane the result of calling paintComponents on g. Where did g come from? You can not used a variable until declared. The result of calling paintComponents is void which means the result cannot be used as an argument to a method. Presumably you had compiler errors.
I changed paintComponents to paintComponent. The former is used to control painting of subcomponents and in general should not be overridden.
Swing objects should not be created on the main thread. The details are complicated for a beginner (and described here in detail). Mostly you can just memorize the SwingUtilities.invokeLater pattern used above.
Related
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);
}
}
}
I wrote a paint class, and added the jpanel to the frame, but it's getting called twice for some reason, as I put a print statement inside the graphics method, and it printed it twice. The codes below are all the codes I have in my package.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Paint extends JPanel {
static Paint paint = new Paint();
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Hello");
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(paint);
frame.pack();
frame.setLocation(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I tried your code and paintComponent it's not called twice every time. I don't think you have the control on when the JFrame is calling pack() when you call setVisible. It may depends on how your OS manage the windows.
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);
}
}
I set a JPanel as a contentPane of my JFrame.
When I use:
jPanel.setBackground(Color.WHITE);
The white color is not applied.
But when I use:
jFrame.setBackground(Color.WHITE);
It works... I am surprised by this behaviour. It should be the opposite, shouldn't it?
SSCCE:
Here is an SSCCE:
Main Class:
public class Main {
public static void main(String[] args) {
Window win = new Window();
}
}
Window Class:
import java.awt.Color;
import javax.swing.JFrame;
public class Window extends JFrame {
private Container mainContainer = new Container();
public Window(){
super();
this.setTitle("My Paint");
this.setSize(720, 576);
this.setLocationRelativeTo(null);
this.setResizable(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainContainer.setBackground(Color.WHITE); //Doesn't work whereas this.setBackground(Color.WHITE) works
this.setContentPane(mainContainer);
this.setVisible(true);
}
}
Container Class:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Container extends JPanel {
public Container() {
super();
}
public void paintComponent(Graphics g) {
}
}
The reason is very simple include the following line
super.paintComponent(g);
when you override paintComponent.
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
Now it works perfectly.
You should always do this unless you have a very specific reason to do so .
[PS:Change the colour to red or something darker to notice the difference as sometimes it becomes difficult to differentiate between JFrame's default grey colour and White colour]
With my testcode it works the way you expected it to work:
public class Main {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(new Dimension(400,400));
f.setLocationRelativeTo(null);
JPanel p = new JPanel();
p.setSize(new Dimension(20,20));
p.setLocation(20, 20);
//comment these lines out as you wish. none, both, one or the other
p.setBackground(Color.WHITE);
f.setBackground(Color.BLUE);
f.setContentPane(p);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
I have a JFrame created with GUI builder of Netbeans, which contains a JPanel only. I have created a method getPanel for getting a reference to this JPanel:
public class ShowDrawings extends JFrame {
public ShowDrawings() {
initComponents();
}
public JPanel getPanel(){
return panel;
}
private JPanel panel;
}
In my main function I am doing:
public class Main {
public static void main(String[] args){
ShowDrawings sd = new ShowDrawings();
sd.setSize(800, 600);
Graphics g = sd.getPanel().getGraphics();
g.setColor(Color.BLACK);
g.drawOval(400, 300, 50, 50);
sd.getPanel().paint(g);
sd.repaint();
sd.setVisible(true);
}
}
But it does not draw anything. Please help me.
I have looked some related questions but they are all suggesting extending JPanel and overriding its paint method. But I did not want to do that way.
Thanks.
I have looked some related questions but they are all suggesting
extending JPanel and overriding its paint method. But I did not want
to do that way
You should not override JPanel paint() method, rather paintComponent(..). This is best practice and should be done if you want code that will not produce anomalies. Also doing it in your current approach (as you have seen) makes creating persistent drawings a lot harder as they are wiped away on repaint()
Rather extend JPanel and override paintComponent(Graphics g) not forgetting to call super.paintComponent(g) as first call in overridden paintComponent(..) method. Also dont forget to override getPreferredSize() of JPanel so that we can return correct dimensions and pack() may be called on JFrame (+1 to #mKorbels comment):
Here is some example code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void initComponents() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel testPanel = new JPanel() {
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GREEN);
//g2d.drawOval(10,10,100,100);//I like fill :P
g2d.fillOval(10,10,100,100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
};
frame.add(testPanel);
frame.pack();
frame.setVisible(true);
}
}
The first time you repaint() your ShowDrawings sd frame anything you've painted like this (sd.getPanel().getGraphics().drawOval(...)) would be erased by the original JPanel#paintComponent() method.
As Andrew Thompson has written:
Do not use Component.getGraphics(). Instead, subclass and override the paint() (AWT), or paintComponent() (Swing) method.
Component.getGraphics() simply can't work. Java uses a callback mechanism for drawing graphics. You are not supposed to "push" graphics information into a component using getGraphics(). Instead you are supposed to wait until Java calls your paint()/paintComponent() method. At that moment you are supposed to provide the Component with the drawings you would like to do.
If you're just checking/debugging something you could even do something like this:
class Test {
private JPanel panel = new JPanel() {
public void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.drawOval(400, 300, 50, 50);
}
};
}