Java Buttons disappear when using paint()

Discussion in 'Mac Programming' started by jsmwoolf, Sep 7, 2011.

  1. jsmwoolf macrumors regular

    Joined:
    Aug 17, 2011
    #1
    I'm trying to create a window that contain JButtons and JTextFields. In addition, I have the paint() function which will draw the functions. However, it appears that the all the JTextFields and all but one JButtons disappear. If I remove the paint function, all the Buttons and TextFields are visible. Putting the setVisible in the paint function doesn't work and leaving paint blank doesn't draw anything but all the JButtons and JTextFields will appear.

    Code:
    import javax.swing.*;
    import java.awt.event.*;
    import java.awt.geom.Line2D;
    import java.awt.*;
    
    public class Graph_Function extends JFrame implements ActionListener, WindowListener{
    	Control control;
    	Drawing_Function Draw = null;
    	JPanel row1 = new JPanel();
    	JButton buttonDraw = new JButton("Draw");
    	JButton buttonTable = new JButton("Table");
    	JPanel row2 = new JPanel();
    	JButton redraw = new JButton("Redraw margins");
    	JTextField sizeMarginX = new JTextField(3);
    	JTextField sizeMarginY = new JTextField(3);
    	
    	boolean redrawingMargin=false;
    	int marginX = 40;
    	int marginY = 40;
    	int currentFunction = 0;
    	
    	public Graph_Function(Control control)
    	{
    		super("Graph");
    		this.control = control;
    		Draw = new Drawing_Function(this);
    		setSize(400,500);
    		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    		setResizable(false);
    		GridLayout layout = new GridLayout(12,1,1,1);
    		setLayout(layout);
    		
    		FlowLayout layout1 = new FlowLayout();
    		row1.setLayout(layout1);
    		row1.add(buttonDraw);
    		row1.add(buttonTable);
    		add(row1);
    		
    		FlowLayout layout2 = new FlowLayout();
    		row2.setLayout(layout2);
    		row2.add(sizeMarginX);
    		row2.add(sizeMarginY);
    		row2.add(redraw);
    		add(row2);
    		
    		redraw.addActionListener(this);
    		buttonDraw.addActionListener(this);
    		addWindowListener(this);
    		setVisible(false);
    	}
    	
    	public void paint(Graphics g)
    	{
    		//Declaring all nessecary Objects
    		Dimension size = new Dimension(400,300);
    		Point startingRectangle = new Point(0,150);
    		Rectangle window = new Rectangle(startingRectangle,size);
    		Point origin = new Point(window.width/2,(window.height/2) +150);
    		
    		//Gives info
    		System.out.println(window.x + " " + window.y + " " + (window.width+window.x) + " " + (window.height+window.y));
    		System.out.println("The origin is " + origin.x + " " + origin.y);
    		//Draws
    		g.clearRect(window.x, window.y, window.width, window.height);
    		g.drawRect(window.x, window.y, window.width, window.height); //Draws the border
    		g.drawLine(window.width/2,150, window.width/2, window.height+150);
    		g.drawLine(0, (window.height/2)+150, 400, (window.height/2)+150);
    		drawMargins();
    	}
    
    	void drawMargins()
    	{
    		Graphics g = getGraphics();
    		boolean goingUp=true;
    		for(int x = 200;;)
    		{
    			g.drawLine(x, 295, x, 305);
    			if(goingUp==true)
    			{
    				x+=marginX;
    			}
    			else
    			{
    				x-=marginX;
    			}
    			if(x>=400)
    			{
    				x=200;
    				goingUp=false;
    			}
    			if(x<=0)
    			{
    				break;
    			}
    		}
    		goingUp=true;
    		for(int y = 300;;)
    		{
    			g.drawLine(195, y, 205, y);
    			if(goingUp==true)
    			{
    				y+=marginY;
    			}
    			else
    			{
    				y-=marginY;
    			}
    			if(y>=450)
    			{
    				y=300;
    				goingUp=false;
    			}
    			if(y<=150)
    			{
    				break;
    			}
    		}
    	}
    	
    	public void actionPerformed(ActionEvent event) {
    		Object current = event.getSource();
    		if(current.equals(redraw))
    		{
    			marginX = Integer.parseInt(sizeMarginX.getText());
    			marginY = Integer.parseInt(sizeMarginY.getText());
    			Graphics g = getGraphics();
    			paint(g);
    		}
    		if(current.equals(buttonDraw))
    		{
    			setVisible(false);
    			Draw.setVisible(true);
    		}
    	}
    	
    	/*void drawALine()
    	{
    	Draw.Dline.lineEquation();
    	Line2D.Double line = new Line2D.Double();
    	line.setLine(0, Draw.Dline.firstY, 400, Draw.Dline.secondY);
    	Graphics g = getGraphics();
    	Graphics2D g2d = (Graphics2D)g;
    	g2d.draw(line);
    	System.out.println(0 + "," + Draw.Dline.firstY + "  " + 400 + ","+ Draw.Dline.secondY);
    	}*/
    	
    	@Override
    	public void windowActivated(WindowEvent arg0) {
    	}
    
    	@Override
    	public void windowClosed(WindowEvent arg0) {
    	}
    
    	@Override
    	public void windowClosing(WindowEvent arg0) {
    		setVisible(false);
    		control.gui.setVisible(true);
    	}
    
    	@Override
    	public void windowDeactivated(WindowEvent arg0) {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void windowDeiconified(WindowEvent arg0) {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void windowIconified(WindowEvent arg0) {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void windowOpened(WindowEvent arg0) {
    		// TODO Auto-generated method stub
    		
    	}
    }
    The only possible reason why one of the JButtons would be because I added that button before I worked on the paint function.
     
  2. chown33, Sep 7, 2011
    Last edited: Sep 7, 2011

    chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    The design and implementation is completely wrong.

    To paint a JComponent, you don't override paint(). You override paintComponent().

    Also, your class structure so weird I have no idea how to make it work, so I'm simply going to call it wrong. The JFrame should not be responsible for painting a graph component.

    There should be a GraphComponent class, which is a JPanel subclass, and it alone is responsible for painting the graph. You then add a GraphComponent instance into the JFrame, e.g. at the CENTER position of a BorderLayout. You then couple the action-events from the buttons, through the listener (which can be the JFrame, but is more likely the GraphComponent), so that the JButton actions go directly to where the action is triggered.

    You shouldn't need to override paint() or paintComponent() in the JFrame at all. The only override should be paintComponent() in the GraphComponent.


    What you call the "margins" are actually the axes, where the axis labels are drawn. I recommend putting it in your GraphComponent, as separate objects or methods that simply draw the axis labels on the Graphics passed to paintComponent(). For example, GraphComponent.paintComponent() would be:
    Code:
      this.drawXAxis(g);
      this.drawYAxis(g);
      this.drawGraph(g);
    

    Here's a quick summary of how custom painting should be implemented:
    http://download.oracle.com/javase/tutorial/uiswing/painting/closer.html
    I suggest reading the entire tutorial there, and also looking for other tutorials that will walk you through how to make custom subclasses for drawing graphs.

    One of the reasons I posted links to existing Java graphing components was so you could look at how they do things, and then pattern your code the same way. I suggest looking at existing examples, so you at least see which methods to override.


    EDIT
    There are some other implementation errors, such as here:
    Code:
    	public void actionPerformed(ActionEvent event) {
    		Object current = event.getSource();
    		if(current.equals(redraw))
    		{
    			marginX = Integer.parseInt(sizeMarginX.getText());
    			marginY = Integer.parseInt(sizeMarginY.getText());
    [COLOR="Red"]			Graphics g = getGraphics();
    			paint(g);
    [/COLOR]		}
    
    The red-hilited code is wrong. You should never call paint() directly, and certainly not for any JComponent.

    Painting is event-driven. You call one of the repaint() methods of the component that needs repainting (there are several repaint() forms with different args, the simplest has no args). AWT then calls paint() when it decides to, using a Graphics that it determines.
     

Share This Page