I'm a beginner programmer, so I don't know all the vocab, but I understand some of the basics of java.
So I'm trying to Draw in a GUI from the main using another class. I know I'm not being very specific but here's my code, and I'll try to explain what I'm trying to do.
This is my main
import javax.swing.*;
import java.awt.*;
public class ThisMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame theGUI = new JFrame();
theGUI.setTitle("GUI Program");
theGUI.setSize(600, 400);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ColorPanel panel = new ColorPanel(Color.white);
Container pane = theGUI.getContentPane();
pane.add(panel);
theGUI.setVisible(true);
}
}
This is my other class
import javax.swing.*;
import java.awt.*;
public class ColorPanel extends JPanel {
public ColorPanel(Color backColor){
setBackground(backColor);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
}
}
I'm trying to use the line
ColorPanel panel = new ColorPanel(Color.white);
Or something like it to use things like
drawRect();
In the main and have it draw in the GUI.
This is the code I used that i think came closest to working
import javax.swing.*;
import java.awt.*;
public class ThisMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame theGUI = new JFrame();
theGUI.setTitle("GUI Program");
theGUI.setSize(600, 400);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//I'm trying to draw a string in the JFrame using ColorPanel but i'm Trying to do it from the main
ColorPanel panel = new ColorPanel(){
public void paintComponent(Graphics g){
super.paintComponent(g);
//This is the line I need to work using the ColorPanel in anyway
g.drawString("Hello world!", 20, 20);
};
Container pane = theGUI.getContentPane();
//The errors occur here
pane.add(panel);
theGUI.setVisible(true);
//and on these brackets
}
}
I'm not really sure what exactly you're trying to do (you haven't replied to my comment to your question for clarification), but I would:
Give your ColorPanel a List<Shape>
Give it a public void addShape(Shape s) method that allows outside classes to insert shapes into this List, and then calls repaint()
And in the ColorPanel's paintComponent method, iterate through the List, painting each Shape item using your Graphics2D object.
Note that Shape is an interface, and so your List can hold Ellipse2D objects, Rectangle2D objects, Line2D objects, Path2D objects, and a whole host of other objects that implement the interface. Also, if you want to associate each Shape with a Color, you could store the items in a Map<Shape, Color>.
The reason why you are not able to compile is caused by this line:
ColorPanel panel = new ColorPanel(Color.white);
because the class ColorPanel is not included in the swing library so you have to code it. This code extends JPanel and includes a constructor that takes a Color parameter. The constructor runs when the panel is instantiated and sets its background color:
import javax.swing.*;
import java.awt.*;
public class ColorPanel extends JPanel {
public ColorPanel(Color backColor) {
setBackground(backColor);
}
}
Related
I wanted to know if it is possible to use/make a function in another Class to draw an image/oval and then call it in the paint public void in our main Class.
If I have
public class Trydraw{
public void drawrcircle(Graphics g){
g.setColor(Color.RED);
g.drawOval(0, 0, 20,20);
g.fillOval(0,0,20,20);
}
}
And then call it here this way
import java.awt.GridLayout;
import javax.swing.*;
import java.awt.*;
public class Display extends JPanel{
public static void main(String[]haha){
JFrame frame = new JFrame();
frame.setSize(800, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void paint(Graphics g){
super.paint(g);
Trydraw l = new Trydraw();
l.drawrcircle(g);
}
}
Thanks for your future help.
Yes you can, if I get your question correctly.
Your sample code works for me if I add
frame.add(new Display());
to the end of your
public static void main(String[] haha)
method.
With your snippet the paint(g) method will never be called, because it will be executed with the initialization of the JPanel which will be initialized with the initialization the Display class (because of inheritance).
You probably want to create an instance of Display, which automatically initializes the JPanel with the overridden paint(g) method, thus the new Operator.
As the constructor of a JPanel returns a JPanel, the constructor of Display returns a type of JPanel as well, which contains the red circle. This JPanel needs to be added with the add method to your original JFrame.
I'm practising to draw a shape on a JPanel by clicking on a Jbutton, but I cannot. It's been five hours that I'm surfing the web, but I cannot find the way to do it.
This is what I want to do: if I click on "Rectangle" button a rectangle appears under the buttons and if I click on "Circle" button a circle appears.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Shape extends JFrame {
JButton rec, circle;
static String botSelected;
Shape (){
frameSet ();
}
void frameSet(){
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(600,300);
rec = new JButton ("Rectangle");
circle = new JButton("Circle");
JPanel panel = new JPanel();
frame.add(panel);
panel.add(rec);
panel.add(circle);
Click clk = new Click();
rec.addActionListener(clk);
circle.addActionListener(clk);
}
public void paint (Graphics g){
super.paint(g);
if (botSelected.equals("Rectangle"))
g.fillRect(50,50,50,50);
else if (botSelected.equals("Circle"))
g.fillOval(50,50,50,50);
}
public static void main (String [] arg){
Shape s = new Shape();
}
}
class Click implements ActionListener{
public void actionPerformed (ActionEvent e){
Shape.botSelected = e.getActionCommand();
}
}
The first thing I would do is have a read through Painting in Swing and Performing custom painting to better understand how the painting process works.
Next you need to understand that JFrame is a bad choice for painting to. Why? Because it's multilayered.
A JFrame contains a JRootPane, which contains a JLayeredPane the contentPane, glassPane and the JMenuBar and in your example, it also contains a JPanel.
With the (default) exception of the glassPane, all these components are opaque.
While it's possible to have something drawn in the paint method show it, if any of the other components paint themselves, it will be wiped clean - this is because Swing components can actually be painted independently of each other, with having to have the parent paint itself first.
A better solution is to start by extending from JPanel and override its paintComponent method.
For simplicity, I'd also encourage you to implement the ActionListener against this class as well, it will allow the actionPerformed method to access the properties of the component and, in your case, call repaint to trigger a paint cycle when you want to update the UI.
Here is a derived example from your code.
As #MadProgrammer said, don't extend JFrame.
In the following example, here are the major changes :
give a non-null value to botSelected, or the first calls to paintComponent will give you a NullPointerException
the class now extends JPanel, and overrides paintComponent for custom painting
the ActionListener is an anonymous class, because you don't need a separate class, and it has direct access to the fields from Shape
botSelected is no longer static (see above point)
.
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Shape extends JPanel {
JButton rec, circle;
String botSelected = "";// don't let it be null, it would make paintComponent crash on startup
Shape() {
frameSet();
}
void frameSet() {
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(600, 300);
rec = new JButton("Rectangle");
circle = new JButton("Circle");
frame.add(this);
this.add(rec);
this.add(circle);
// anonymous class, has access to fields from the outer class Shape
ActionListener clk = new ActionListener() {
public void actionPerformed(final ActionEvent e) {
botSelected = e.getActionCommand();
repaint();
}
};
rec.addActionListener(clk);
circle.addActionListener(clk);
}
//custom painting of the JPanel
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
if (botSelected.equals("Rectangle")) {
g.fillRect(50, 50, 50, 50);
} else if (botSelected.equals("Circle")) {
g.fillOval(50, 50, 50, 50);
}
}
public static void main(final String[] arg) {
Shape s = new Shape();
}
}
I used a border layout and I put a canvas in the center; where the main game will be, but I can't draw anything to it.
Could anyone point me in the right direction?
import java.awt.*;
import javax.swing.*;
public class TestingGraphics {
public static void main (String[] args) {
GameScene window = new GameScene();
}
}
import java.awt.*;
import javax.swing.*;
public class GameScene extends JFrame {
Canvas gameCanvas;
Graphics Pencil;
JPanel game;
public GameScene() {
game = new JPanel();
add(game);
setTitle("Yet to name this thing.");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameCanvas = new Canvas();
gameCanvas.setPreferredSize(new Dimension(1280, 720));
game.add(gameCanvas);
drawString();
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public void drawString(Graphics Pencil) {
Pencil.drawString("boo", 100, 100);
}
}
Your problem is that you're making wild guesses on how to draw in Swing and that never works, and your errors include trying to draw directly within a JFrame, trying to call a method without passing in necessary parameters, drawing outside of any painting method.... First and foremost, go to the Swing drawing tutorials which you can find here: Swing Drawing Tutorials -- and read them.
Next, do as they tell you:
Create a class that extends JPanel
Draw in the paintComponent method override of that class, not directly in a JFrame
Be sure to call the super's paintComponent method in your overridden method.
Add your JPanel to a top-level window such as a JFrame
Display the GUI
Done.
I am writing this code so that it will add JPanels and will change the background color when clicked. The code in the class that runs the JFrame class is:
import javax.swing.*;
public class project9Driver {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Project9 w=new Project9();
w.setVisible(true);
w.setSize(900, 900);
}
}
The Project9 class is:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class Project9 extends JFrame implements MouseListener{
JPanel panes[]=new JPanel[64];
public void Project9(){
JFrame mainFrame=new JFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container mainBox=mainFrame.getContentPane();
mainBox.setLayout(new GridLayout(8,8));
mainBox.addMouseListener(this);
for(int i=0;i<=63;i++){
panes[i].setBackground(Color.WHITE);
mainBox.add(panes[i]);
}
}
public void paint(Graphics g){
super.paintComponents(g);
}
public void mouseClicked(MouseEvent e) {
for(int i=0;i<=64;i++){
if(e.getSource()==panes[i]){
Random xR=new Random();
Random yR=new Random();
Random zR=new Random();
int x=xR.nextInt(255),y=yR.nextInt(255),z=zR.nextInt(255);
panes[i].setBackground(new Color(x,y,z));
}
}
}
}
Whenever I try to run the program, it comes up with an empty GUI window. What am I missing?
Project9 is a Frame, and you're creating another Frame inside of Project9 and you're not showing it, and becouse of that, just Project9 (w) is draw on screen, but it doesn't have anything.
You have to use "this" instead of another frame.
public class Project9 extends JFrame implements MouseListener{
JPanel panes[]=new JPanel[64];
public void Project9(){
//JFrame mainFrame=new JFrame(); delete this.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container mainBox= this.getContentPane();
Three answer all point out different problems with your code.
You should start with a proper working example. The TopLevelDemo.java code from the Swing tutorial on Using Top Level Containers will show you the basics and the proper way to create GUI components.
You should not even be extending JFrame. It is important that all components are created on the Event Dispatch Thread which is why the invokeLater() code is used in the tutorial.
Use the tutorial for examples of using all Swing components. Other example will show you how to extend JPanel for a more complex GUI. You don't need to extend JFrame.
The original problem I noticed with the code is:
public void paint(Graphics g){
super.paintComponents(g);
}
Don't override the paint() method. There is no reason to do this!
The paint() method is for painting and you are not doing any custom painting.
First problem is this that you are using constructor Project9 w=new Project9();
and in class Project9 you are defining method public void Project9(){ you should remove void keyword.
public Project9(){
//JFrame mainFrame=new JFrame(); delete this.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container mainBox= this.getContentPane();
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);
}
};
}