Components aren't showing in Applet until I resize - java

I've looked at the other examples on here but the revalidate() or repaint() after I create all of my components. I've also tried the this.setVisible(this); and that didn't work. I've tried creating my components in a createGUI() method and running that from the init() method within a try/catch statement.
EDIT
I tried all of your examples, as you can see in the comments. But from what everyone has said why does this now work?
package basic;
import java.awt.*;
//import java.applet.*;
import java.applet.Applet;
import javax.swing.*;
import java.awt.event.*;
public class Shapes extends Applet implements ActionListener
{
JButton rectBtn = new JButton("Rectangle");
JButton circBtn = new JButton("Circle");
JLabel rectLbl = new JLabel("Rectangle"), circLbl = new JLabel("Circle");
JLabel widthLbl = new JLabel("Width"), heightLbl = new JLabel("Height");
JTextField widthTF = new JTextField(6), heightTF = new JTextField(6), colorTF;
boolean rectOn;
boolean circOn;
int x,y, width, height;
String xcord, ycord, widthSize, heightSize;
public void init()
{
JPanel TotalGUI = new JPanel(new GridLayout(2,0));
TotalGUI.add(rectLbl); TotalGUI.add(rectBtn);
rectBtn.addActionListener(this);
TotalGUI.add(circLbl); TotalGUI.add(circBtn);
circBtn.addActionListener(this);
TotalGUI.add(widthLbl); TotalGUI.add(widthTF);
TotalGUI.add(heightLbl); TotalGUI.add(heightTF);
add(TotalGUI, BorderLayout.WEST);
//this.setVisible(true);
TotalGUI.repaint();
//pack();
}
//#Override
public void paintComponent(Graphics g)
{
//super.paintComponent(g);
//Graphics g2 = getGraphics();
if(rectOn)//if Rectangle has been pressed
{
g.drawRect(x,y, width,height);
}
if(circOn)//if Circle has been pressed
{
g.drawOval(x,y, width, height);
}
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == rectBtn)
{
rectOn = true;
}
if(e.getSource() == circBtn)
{
circOn = true;
}
//Reads coordinates and sizes as Strings and converts to integers
try{
widthSize = widthTF.getText();
width = Integer.parseInt(widthSize);
heightSize = heightTF.getText();
height = Integer.parseInt(heightSize);
}
catch(Exception err) { JOptionPane.showMessageDialog(null, "Enter a number!"); }
repaint();
}
}
Thank you for your help!

The main problem with your original code was that your overrode the paint() method without invoking super.paint(g). When you changed that method to paintComponent() the code worked because that method doesn't even exits in an Applet so it was dead code.
The problems with your code:
You should be extending JApplet for a Swing applet
You should NOT override the paint() (or paintComponent()) method of an Applet. If you need to do custom painting then you override the paintComponent() method of a JPanel (or JComponent) and add the panel to the content pane of the applet.
The code should be executed on the EDT.
The applet will display the components automatically, there is no need to invoke repaint)
Never use getGraphics() to do custom painting. Use the Graphics object of the paintComponent() method.
When you attempt to override a method don't forget to use the #Override annontation before the method signature to make sure you override the method correctly.
Start by reading the Swing tutorial for a better explanation and working example. Start with the sections on:
How to Make Applets
Performing Custom Painting

You should call repaint() on TotalGUI.
The reason your gui refreshes after resize, is that resize automatically calls repaint() for you. However, if you want you gui changes to appear instantly, you should call repaint();
A preferred approach, however, is to use in your totalGUI's paint(Graphics g)/paintComponent(Graphics g) method/s:
super.paintComponent(g);
as described by these posts:
JPanel repaint issue
http://www.sitepoint.com/forums/showthread.php?273522-super.paintComponent()

Related

Why am I not able to "draw" on my JFrame?

I am trying to draw on my JFrame, but I can't get my super.paintComponents(g); to work. Also, nothing is drawing on my JFrame when I tell it to in my paintComponent() method.
Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class MTGSAMPServerReference extends JFrame implements ActionListener {
public static Toolkit tk = Toolkit.getDefaultToolkit();
static int ScrnWidth = ((int) tk.getScreenSize().getWidth());
static int ScrnHeight = ((int) tk.getScreenSize().getHeight());
private static final long serialVersionUID = 1L;
private static JList list1;
private static JButton next;
public MTGSAMPServerReference() {
// set flow layout for the frame
this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEADING));
Object[]mainData = {"Vehicles", "Bikes/Bicycles", "Boats", "Houses", "Businesses", "Objects", "Jobs", "Ranks", "Licenses", "VIP"};
JPanel controls = new JPanel(new BorderLayout(5,5));
list1 = new JList<Object>(mainData);
list1.setVisibleRowCount(10);
next = new JButton("Next");
next.addActionListener(this);
controls.add(new JScrollPane(list1));
controls.add(next, BorderLayout.PAGE_END);
controls.setBorder(new EmptyBorder(25,25,0,0));
add(controls);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Next")) {
int index = list1.getSelectedIndex();
System.out.println("Index Selected: " + index);
String s = (String) list1.getSelectedValue();
System.out.println("Value Selected: " + s);
}
}
public void createAndShowGUI() {
//Create and set up the window.
JFrame f = new MTGSAMPServerReference();
//Display the window.
f.pack();
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1200, 800);
f.setLocationRelativeTo(null);
list1.setSize(250, 250);
list1.setLocation(0, 0);
next.setSize(75, 25);
next.setLocation(251, 276);
MTGSAMPServerReference.this.repaint();
}
protected void paintComponent(Graphics g) {
//super.paintComponent(g); << Can't seem to get this to work.
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawRect(0, 0, 50, 50);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
MTGSAMPServerReference gui = new MTGSAMPServerReference();
gui.createAndShowGUI();
}
});
}
}
I have worked with paintComponent() before, but still can't seem to figure out what I am doing wrong. I know that it has got to be a simple fix, but can't spot it for the life of me. Any ideas?
Any and all help is appreciated.
Thanks in advance!
Use the #Override annotation on your paintComponent method for a rude surprise. This is why using this annotation is very helpful, since it will flag you at compile time if you are not overriding a method when you think that you should be.
Solution: never "paint" in a JFrame for many reasons. Instead do what the tutorials tell you to do -- paint in a JPanel or JComponent's paintComponent(...) method. If you search this site you will find that we have told many folks here the same thing, and in fact I suggest that you do just that. I wouldn't be surprised if this question is closed as a duplicate since this is a fairly common question.
Note this won't "work" (and actually won't compile):
super.paintComponent(g); << Can't seem to get this to work.
for the same reason -- there is no super.paintComponent(g) for a JFrame.
Also, regarding,
I have worked with paintComponent() before, but still can't seem to figure out what I am doing wrong.
But if you look at your prior code, you'll see that this method was never used directly in a JFrame, and nor should it.
paintComponent() is a member of the JPanel class, not the JFrame class in which you are trying to call it.
That is why you are unable to call super.paintComponent(Graphics g). The compiler thinks you are creating your own completely unrelated method that also happens to be called paintComponent().
Create a class that inherits JPanel and copy and paster your paintComponent() method there.
Like Hovercraft Full Of Eels commented, you can check that you are correctly overriding methods by adding the #Override tag directly over the method header; if you receive an error, you are doing something wrong.
For more information about JPanel and JFrame, see my answer to this question.

Java drawn objects not updating properly

I have been playing around with Java's 2d painting tools and have hit a snag. I am attempting to move the objects. Here is the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test extends JPanel{
private int[] location = new int[2];
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillArc(location[0], location[1], 100, 100, 45, 90);
g.setColor(Color.black);
g.fillArc((location[0]+50-10),(location[1]+50-10), 20, 20, 0, 360);
new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setLocation((location[0]+50),50);
repaint();
System.out.println("repainting");
}
}).start();
}
public void setLocation(int x, int y){
this.location[0] = x;
this.location[1] = y;
}
public static void main(String[] args){
JFrame jf=new JFrame();
jf.setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
jf.setPreferredSize(new Dimension(300,500));
jf.setLocation(100,100);
jf.add(new Test());
jf.pack();
jf.setVisible(true);
}
}
This only paints one of the two objects to the screen... it seems to be the second one as when I change the parameters of setLocation on [1] the one object it does paint moves. Any thoughts? Thanks
Edit: Edited above code to reflect what was said below.
You are adding two components to the JFrame in a default way. This will add the components BorderLayout.CENTER and so the second component will cover and obscure the first. You will want to read up on layout managers to fix this. Also read up on Swing Timers for simple animations, since your code, even if written correctly would do no animation.
If you want to move the drawing, then
Use only one Test JPanel
Override JPanel's paintComponent(...) method, not paint(...) method.
call the super.paintComponent(g) method first thing in your paintComponent method override.
Give the Test JPanel public methods to allow outside classes to change the location without having them directly futz with the field. Make the location field (name should begin with a lower-case letter) private just to be safe.
Use a Swing Timer to periodically call this method and change location, then call repaint() on the JPanel.

I neither see the label on the button nor see it painted in green. Why is that ?

The following code places a button onto the panel. But there is a problem.I neither see the label Click Me on the button nor I see the button painted in green. Why is that ?
import javax.swing.*;
import java.awt.*;
class Tester extends JButton {
public Tester(String label) {
super(label);
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
}
public static void main(String args[]) {
JFrame fr = new JFrame();
JPanel p = new JPanel();
JButton button = new Tester("Click Me !");
p.add(button);
fr.add(p);
fr.setVisible(true);
fr.setSize(400,400);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
You need to call
super.paintComponent(g);
This will paint all child components. However, custom painting is unnecessary here as JButton provides a method setBackground to set the background color directly. You can use
button.setBackground(Color.GREEN);
See: Performing Custom Painting
First you need to call: super.paintComponent(g); in paintComponent() if you want to override any of its behavior. But if you want just change the background color then do that in your constructor. There is no need to override paintComponent for a property change.

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