Drawing to a nested panel using BorderLayout - java

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.

Related

Weird Swing Glitch?

I don't understand this, I'm currently making a main menu for a game i'm making but for some reason when I hover over a JButton, it flashes up on the top left side of the JFrame. I don't have any mouseAction methods or anything, is it the gif i'm using? I'm not sure...
Here is a screengrab of the error
Here is my code :
import javax.swing.*;
import java.awt.*;
public class MainMenu {
JFrame frame = new JFrame("Frasergatchi");
public void display(){
frame.setSize(400,400);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
}
public void addComponents(){
JButton play = new JButton("Play");
JButton instructions = new JButton("Instructions");
JButton exit = new JButton("Exit");
JPanel panel = new JPanel();
paintMenu paintMenu = new paintMenu();
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
frame.add(panel);
play.setAlignmentX(Component.CENTER_ALIGNMENT);
instructions.setAlignmentX(Component.CENTER_ALIGNMENT);
exit.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(paintMenu);
panel.add(play);
panel.add(instructions);
panel.add(exit);
}
public class paintMenu extends JPanel{
public void paintComponent(Graphics graphics){
Image dog = new ImageIcon(getClass().getResource("DogMenuImage.gif")).getImage();
graphics.drawImage(dog,170,240,this);
}
}
}
The first statement in the paintComponent() method should always be:
super.paintComponent(g);
to make sure the background gets cleared.
Also:
Don't do I/O in a painting method. Painting methods are for painting only. Read the image in the constructor of your class and same the image in an instance variable.
Class names SHOULD start with an upper case character. Think of all the classes in the JDK and follow the standards.
There is no need to create a custom class to paint the image. Just use a JLabel with an Icon.

How to draw shapes from a class to an applet?

total programming beginner here, trying to learn some Java over school holidays. Been making simple things and have started looking at GUIs and drawing shapes using Graphics. I've mostly been following tutorials and heaps of answers posted here.
I'm having trouble drawing shapes from my Draw class into my DrawTest applet; as below
import java.awt.*;
import java.applet.*;
import javax.swing.*;
public class DrawTest extends Applet
{
Draw circle = new Draw();
public void init()
{
Panel mainPanel = new Panel();
mainPanel.setLayout(new GridLayout(0,2)); //a left and right panel
JPanel drawPanel = new JPanel(); //left panel to draw shapes into
drawPanel.setBackground(Color.BLACK);
JLabel headerLabel = new JLabel("Draw shapes from another class");
headerLabel.setForeground(Color.GREEN);
drawPanel.add(headerLabel);
drawPanel.add(circle);
circle.drawing();
JPanel textPanel = new JPanel(); //right panel for text
TextArea output = new TextArea("Circle and oval");
textPanel.add(output);
mainPanel.add(drawPanel);
mainPanel.add(textPanel);
add(mainPanel);
}
}
And the Draw class
import java.awt.*;
import java.awt.Graphics;
import java.awt.Color;
import javax.swing.*;
public class Draw extends JPanel
{
public void drawing()
{
repaint();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
// a circle (int x, int y, int width, int height,int startAngle, int arcAngle);
g.fillArc(20,20,50,50,0,360);
//this will draw a oval of width 60 & height 40 at (10,30)
g.setColor(Color.RED);
g.drawOval(10,30,60,40);
}
}
Thanks in advance for any pointers.
You have that problems because you use swing and awt components together. Use only swing components.
Use JApplet instead of Applet.
Use JPanel instead of Panel.
Use JTextArea instead of TextArea.
Also wrap JtextArea with JSrollPane, and as mentioned by dehlen you needn't drawing() method.
For example change your init() method like next :
public void init() {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new GridLayout(0, 2)); // a left and right panel
JPanel drawPanel = new JPanel(new BorderLayout());
drawPanel.setBackground(Color.BLACK);
JLabel headerLabel = new JLabel("Draw shapes from another class");
headerLabel.setForeground(Color.GREEN);
drawPanel.add(headerLabel,BorderLayout.EAST);
circle.setBackground(Color.BLACK);
drawPanel.add(circle);
JPanel textPanel = new JPanel(new BorderLayout()); // right panel for text
JTextArea output = new JTextArea("Circle and oval");
textPanel.add(new JScrollPane(output));
mainPanel.add(drawPanel);
mainPanel.add(textPanel);
add(mainPanel);
setSize(600,200);
}
First of all you are mixing awt and swing components. Please type JTextArea and JPanel and JApplet instead of TextArea, Applet and Panel. Also you might want to do something like this:
JPanel drawPanel = new Draw();
but your solution should work too. Again i think your problem occurs because of mixing awt and swing components.
Also the circle.drawing(); is unnecessary since the panel calls paintComponent() when initializing.

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

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

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)

I can't see my JPanel and its components in the JApplet

I want to put a JPanel in a JApplet, the problem is that I can't see it :( I've overridden the paintComponent of my JPanel in order to have a background image, but I can't see anything. When I remove the paintComponenet method that I had overriden, and set a color to the background of this panel, it seems that JPanel fills the JApplet and still no component is visible :-S I've tried different layouts. I also put my panel in the center of another panel which fills my JApplet but nothing changed, and still no component and no background image is visible :(
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Main extends JApplet implements Runnable{
private JTextArea display;
private Thread outputThread;
JPanel boardPanel;
private ClientViewManager view;
#Override
public void init() {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createGUI();
}
});
} catch (Exception e) {
System.err.println("createGUI didn't successfully complete");
}
}
private void createGUI() {
display = new JTextArea(4, 30);
display.setEditable(false);
getContentPane().add(new JScrollPane(display), BorderLayout.SOUTH);
setFocusable(true);
setVisible(true);
setName("CE Tanks");
setSize(600, 600);
setLocation(100, 100);
boardPanel = new JPanel();
boardPanel.setLayout(null);
boardPanel.setBackground(new java.awt.Color(128, 255, 255));
getContentPane().add(boardPanel, BorderLayout.CENTER);
}
public void start() {
outputThread = new Thread(this);
outputThread.start();
}
public void run() {
view = new ClientViewManager();
boardPanel.add(view);
boardPanel.repaint();
repaint();
}
}
class ClientViewManager extends JPanel {
private int rows=8;
private int columns=8;
public ClientViewManager() {
super(null);
JLabel lb= new JLabel("lb.jpg");
lb.setLocation(10, 10);
lb.setSize(50, 50);
lb.setOpaque(false);
lb.setVisible(true);
this.add(lb);
}
public void paintComponent(Graphics g) {
g.drawImage(new ImageIcon("ground.jpg").getImage(), 0, 0, columns * 50,
rows * 50, this);
}
}
The code above can be compiled. I cant even add Keylistener to neither my JPanel nor to my JApplet. I used java.awt.KeyEventDispatcher and in dispatchKeyEvent(KeyEvent e) I printed something in console but, it was printed 3 times. :(
I've overridden the paintComponent of my JPanel inorder to have a background image,
But you didn't add the custom component to your applet:
//boardPanel = new JPanel();
boardPanel = new ClientViewManager();
Also:
get rid of setVisible(). This is not required for any of the controls in your program. By default all components except top level Container (Jframe, JDialog etc) are already visible. In the case of JApplet, you don't need to make it visible as this is part of the process of displaying an applet.
get rid of setSize() and setLocation() you can't control the position of the applet this way.
Don't read the image file in the paintComponent() method. This is not efficient as this method is invoked whenever Swing determines the component needs to be repainted.
JLabels are opaque by default so there is not need to invoke the setOpaque method.
When doing custom painting you should also override the getPreferredSize() method of the component to return the proper size of the custom painting so layout managers can use this information. It works in this case because you added the panel to the CENTER of the BorderLayout. Try adding the panel to the NORTH to see what happens.
Edit:
Now I see where you are adding the ClientViewManager. I'm not sure why you are trying to do this with a Thread but once again there are several problems.
When you add/remove components from a visble GUI then the basic code is:
panel.add(...);
panel.revalidate();
panel.repaint();
However this still won't work because you are using a null layout and the size of the panel is 0. Use a proper layout manager and implement the getPreferredSize() method as suggest above and the component will be displayed properly.
I recommend you to use the GUI Builder of Netbeans to build a GUI like that, and then compare the generated code to your code. Netbeans results really useful to help you create swing code.

Categories