Drawing a line on another JFrame in a class that extends JFrame - java

I have a class with two JFrames and am trying to draw a line on a particular frame .
I tried the code below but it only appears in the first frame which is the success frame.
It also appears above all the other components of the success frame thus making all other
components invisible. It does not appear in the comp Frame.
How do I correct this.
Here is the code I have so far :
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
public class lineGUI{
public static void main(String []args){
Success s=new Success();
s.setVisible(true);
}
}
class Success extends JFrame{
JPanel alas =new JPanel();
JFrame comp =new JFrame();
public Success(){
JPanel panel=new JPanel();
getContentPane().add(panel);
setSize(450,450);
JButton button =new JButton("press");
panel.add(button);
comp.setSize(650,500);
comp.setTitle("View Report");
JRootPane compPane=comp.getRootPane();
Container contePane=compPane.getContentPane();
contePane.add(alas);
ActionListener action =new ActionListener(){
public void actionPerformed(ActionEvent e){
if (e.getSource()==button){
comp.setVisible(true);
}
}
};
button.addActionListener(action);
JButton button2=new JButton("access");
alas.add(button2);
}
public void paint(Graphics g) {
comp.paint(g);
Graphics2D g2 = (Graphics2D) g;
Line2D lin = new Line2D.Float(100, 100, 250, 260);
g2.draw(lin);
}
}

You've got some crazy code up there. Suggestions:
Don't draw directly in a JFrame, but in a the paintComponent method of an object derived from JComponent such as JPanel or JComponent itself.
Your drawing directly in another component's paint(...) method is not kosher at all. Why not simply share the data between classes, and use the data (the ints) to draw where desired.
You would rarely want to have a GUI display more than one JFrame at a time. Usually one window is the main window (the JFrame), and it often owns any other windows which would be dialog windows such as JDialogs.
Read the graphics tutorials to learn the correct way to do Swing Graphics

Two things:
If you want to draw in the "comp" frame, then you should extend that frame explicitly to overload its paint method. Right now you're overloading the paint method of "Success" frame. The line comp.paint(g) is using the paint method of comp (a standard JFrame) to draw on the Graphics object of the "Success" frame. You probably want to make that into super.paint(g) instead, then put this paint function into it's own JFrame and create comp from that.
http://pastebin.com/ZLYBHpmj
(Sorry, first post, couldn't figure out how to get Stackoverflow to quit complaining about format)

Related

JPanel How to create an instance/object

I keep mixing up JFrame and JPanel. I have a code that compiles but nothings happens and the program ends.
This is a homework assignment that requires us to draw a triangle. Then add a button, when button is pressed the triangle will flip upside down. Press again to return to the first location.
Any assistance would be great. This is my countless rough draft and I'm just trying to initiate the object to view.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.awt.Color;
public class Triangle extends JPanel implements ActionListener
{
JButton button = new JButton("Just Flip It");
public Triangle()
{
add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawLine(125,75,100,200);
g.drawLine(125,75,150,200);
g.drawLine(100,200,150,200);
}
public static void main(String[] args)
{
Triangle frame = new Triangle();
frame.setSize(400, 400);
frame.setVisible(true);
}
}
Think of a JPanel as a piece of paper and a JFrame as a book.
If you never add the piece of paper to the book, it will never be shown.
So, here are the steps to get your program running:
Create a JFrame that will hold your JPanel (Triangle) inside it
Add some logic in your ActionListener to have a boolean flag, that will be changed to true or false depending on the current state and based on it repaint the pane
Have some logic inside the paintComponent(...) method that draws the triangle upside down or upside up based on the state of the boolean flag above
So, from the above in your main(...) method you should have
JFrame frame = new JFrame("My frame");
//Initialize your Triangle here
frame.add(triangle);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
Your actionPerformed() method should look like this:
public void actionPerformed(ActionEvent e)
{
clicked = !clicked;
repaint();
}
And your paintComponent():
super.paintComponent();
if (clicked) {
//Draw upside up
} else {
//Draw upside down
}
As we're using pack() instead of setSize(...) method, we should override getPreferredSize() method of our JPanel as well:
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
Otherwise we could get a really small JFrame (and it's a good practice to do it this way)
Also don't forget to place your program on the EDT (as I show in the point #2 of this answer)
As a side note, you might also want to move to use the Shape's API as recommended by #MadProgrammer in this answer
Both links above have cool examples and tips, check them out!
You need to add your JPanel to a JFrame object in your main method in the same way you add a button to your panel. The JFrame is the window that your JPanel exists inside of.
Make sure that you set the JFrame object to visible and set its size.
Not related to your question, but I would suggest at least separating out a private class for you ActionListener rather than having the Triangle class be both. If you're feeling adventurous, you could look into using an anonymous inner class or a lambda expression.

Understanding painting in swing

I'm trying to understand what actually paints components in Swing. I read this article about painting in AWT and Swing and now tried to write the following simple program:
//A simple wrapper to understan how paint() works
public class MyButton extends JButton{
/**
* Default serialVersionUID
*/
private static final long serialVersionUID = 1L;
private final JButton jButton;
public MyButton(JButton jButton) {
this.jButton = jButton;
}
#Override
public void paint(Graphics g){
jButton.paint(g);
}
}
But when I try to add MyButton to frame
JFrame frame = new JFrame("Hello swing");
JPanel panel = new JPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.add(new MyButton(button));
frame.add(panel);
it renders nothing
But after deleting
#Override
public void paint(Graphics g){
jButton.paint(g);
}
it renders the empty button:
QUESTION: Why does it behave that way? Why does the delegating cause rendering to fail?
First of all when you post a question you should post a proper SSCCE that demonstrates the problem. We can't copy/compile random lines of code. Until a problem is solved, you don't know what part of the code is causing the problem.
Why does the delegating cause rendering to fail?
My guess would be that the size of the button is (0, 0) so there is nothing to paint.
When you get rid of the custom paint method, then the real button can be painted because it does have a size because the layout manager has done its job.
public class Demo extends JFrame{
public static void main(String[] args)
{
JPanel panel = new JPanel();
getContentPane().setLayout(new BorderLayout());
panel.add(new JButton("Test"));
this.getContentPane().add(panel, BorderLayout.CENTER);
this.setSize(200,200);
this.setVisible(true);
}
}
If you want to add UI Components do it like that, don't use paint in any way.
If you want to paint for example a rectangle follow this tutorial: https://docs.oracle.com/javase/tutorial/uiswing/painting/
Your paint method does not draw the MyButton object, but instead draws the JButton which is member of your class. The problem now is, that this Button has not been added to the panel and so it's drawn on nothing. By removing your paint method, super.paint(g) is called because your class has no paint method and so your button, but not the member JButton is drawn.
I hope you understand what I am trying to explain to you.

Drawing to a nested panel using BorderLayout

im new to Java so therefore I am trying out some things.
I am playing around with Java layouts, specfically Nested Panels using BorderLayout.
The Problem that I have is that i am unable to draw to the nested panels. I am able to draw to the main panel but not the panels nested within it.
I would be very greatful if you could show me where I am going wrong.
Here is my main code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUI extends JFrame{
public GUI()
{
setSize(600,600);
Here is the main panel.
JPanel pan1 = new JPanel();
pan1.setLayout(new BorderLayout());
pan1.setPreferredSize(new Dimension(200,200));
JLabel label = new JLabel("Panel 1");
pan1.add(label);
Then i create the two nested panels which i add to the main one.
JPanel pan2 = new JPanel();
pan2.setBackground(Color.YELLOW);
pan2.setPreferredSize(new Dimension(200,200));
JPanel pan3 = new JPanel();
pan3.setBackground(Color.YELLOW);
pan3.setPreferredSize(new Dimension(200,200));
Here is where I call the class which draws the shape on the screen.
draw drawingShape = new draw();
Here is the problem as i am unable to draw the shape to the nested panel.
pan2.add(drawingShape);
However i can draw it to this panel which is the main one.
pan1.add(drawingShape);
I am inserted the two panels to the main one.
pan1.add(pan2, BorderLayout.NORTH);
pan1.add(pan3, BorderLayout.SOUTH);
getContentPane().add(pan1);
setVisible(true);
}
public static void main(String args[])
{
new GUI();
}
}
Here is the code for creating the shape which is completley fine:
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class draw extends JPanel{
public void paint(Graphics g) {
Image img = createImage();
g.drawImage(img, 20,20,this);
}
private Image createImage(){
BufferedImage bufferedImage = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.getGraphics();
return bufferedImage;
}
}
The code does compile, i appreciate any help.
Regards
Custom painting is done by overriding the paintComponent() method, not the paint() method. Also, don't forget to invoke super.paintComponent().
Read the section from the Swing tutorial on Custom Painting for more information and examples.
Here is the code for creating the shape which is completley fine:
I don't see how it can be fine. As far as I can tell it doesn't do anything. First of all don't create the image in the paintComponent() method. This method gets called whenever Swing determines a component needs to be repainted. Secondly, all the code does is create an blank image.
Read the tutorial and post an actual SSCCE if you still have problems.

Java Swing add component for game

I'm writing a game in Java swing, and have a few layers of classes that I need to implement.
Here are the classes:
Main() //Sets up window, makes a Game, and setVisible
Game() //Draws main game canvas, maintains data about the game, tells each object to draw itself
Board() //Draws the rooms and background graphics
Room() //Draws the stuff inside the room, keeps track of location
Items() //Location, color, function, etc
CollectibleItems() //extends Items
Creatures() //extends Items
ControlPanel() //Put a button in that does something
StatePanel() //Put text in the panel of the room, and whether or not its locked
Main class:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class Main extends JFrame {
public static void main (String [] args) {
new Main ();
}
public Main () {
// Window setup
setSize (700, 450);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container content = getContentPane();
content.setLayout(new BorderLayout());
// Put a Game in
Game myGame=new Game ();
myGame.setBorder(new LineBorder(Color.black, 9));
content.add(myGame, BorderLayout.CENTER);
setVisible (true);
}
This is my Game class. From here I want to add the Board and Panels, and I want the Board to add the Rooms, etc. I don't know how to encapsulate classes and still add them and setVisible. I know how to do it within main, but is there a way to add stuff to Game using a similar content.add() type of thing?
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class Game extends JComponent {
public void paintComponent (Graphics g) {
JPanel ControlPanel=new JPanel();
ControlPanel.setLayout(new FlowLayout());
ControlPanel.setBorder(new LineBorder(Color.red, 9));
}
}
TL;DR- how do I encapsulate and display different classes? New to JavaSwing...
To start with...DON'T DO THIS!! EVER!!
public void paintComponent (Graphics g) {
JPanel ControlPanel=new JPanel();
ControlPanel.setLayout(new FlowLayout());
ControlPanel.setBorder(new LineBorder(Color.red, 9));
}
Also you MUST call super.paintComponent as well, unless you have a REALLY, REALLY good reason not to. These methods do a lot of important background work.
Never modify any component from within the context of the any paintXxx method. This will put you into an infinite loop and eventually consuming all you CPU.
I would start by having a read through
Creating a GUI With JFC/Swing
Performing Custom Painting
2D Graphics

How do you add a JPanel onto another JPanel that has graphics?

Basically what im trying to do is to add a JPanel onto another JPanel that has painted graphics on it using the paintComponent() method. But the JPanel I am trying to add is not shown because it is covered up by the JPanel w/ Graphics on it.
How can I make it so that when I add the JPanel to the one w/ graphics it will show the JPanel in the front instead of being covered up by the Graphics?
All answers are appreciated! :)
If you need the code just tell me and I will gladly put it on here.
Alright here is the code:
package javavideogame;
public class Game extends JPanel implements ActionListener, Runnable
{
public Game(MainCharacter character)
{
setLayout(null);
setFocusable(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(ground, 0, 0, this);
g.drawImage(character.getImage(), character.getX(), character.getY(), this);
g.setColor(Color.RED);
g.drawRect(10, 10, character.getMaxHealth(), 10);
g.fillRect(10, 10, character.getHealth(), 10);
g.dispose();
}
public void getInventoryScreen()
{
Main.inv = new Inventory();
Main.game.add(Main.inv);
}
}
And here is the code for the JPanel that I'm adding to the Game JPanel
public class Inventory extends JPanel
{
public Inventory()
{
setLayout(null);
setSize(400, 300);
setBackground(Color.BLACK);
addKeyListener(this);
setFocusable(true);
}
}
Custom painting is done by overriding the paintComponent(...) method. My guess is that you are overriding the paint() method.
Read this section from the Swing tutorial on Custom Painting. Because you are overriding the wrong method, you end up painting the children first and then the custom painting is done on top.
If you need more help than post your SSCCE demonstrating the problem.
Just a reminder: java.awt and javax.swing don't mix well. When you're painting stuff on one panel AND trying to add a JPanel to it, you are bound to run into problems somewhere. A far better solution is to have 2 different JPanels, one for your graphics, and one for your inventory.
Something like this:
JPanel mainPanel = new JPanel(); //will hold BOTH panels
JPanel gamePanel = new Game(myCharacter); //declare game panel
JPanel inventoryPanel = new Inventory(); //declare inventory panel
//set up some layout
mainPanel.setLayout(new GridLayout(2, 1));
//add the graphics panel, then add the inventory
mainPanel.add(gamePanel);
mainPanel.add(inventoryPanel);
This will keep your swing and awt components from mixing and save you a lot of headaches.

Categories