Results 1 to 10 of 10
  1. #1
    Moncleared is offline Member
    Join Date
    Jan 2009
    Posts
    92
    Rep Power
    0

    Default JFrame/Swing Question

    Greetings,

    I've never posted here before but I have a quick question for you guys. I'm beginning my Senior Seminar at my college and our idea is to make a rather simple game engine (for what we are doing, game engine is probably not even close to what we're actually doing). I'm creating a Frame/jpanel that displays a grid at the moment. I'm going to have some code running on the side that may need to update the paint. When I was doing an Applet I had used a Runnable and had all my stuff running in the public void run() that would repaint at the very last.

    So far I've yet to figure out how I can simply get my screen to repaint at an interval rather it needs to be repainted or not. I've looked at threading tutorials but it doesn't seem like I can get a thread going in the JPanel class that I created.

    So I've been rather all over the place with this post let me review what I'd like.

    1. I'd like to be able to create a thread inside the JPanel class so that if I need to do anything with the painting I can.

    Here is my code:
    Java Code:
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    
    public class Main{
    	    public static void main(String[] args) {
            //Schedule a job for the event-dispatching thread:
            //creating and showing this application's GUI.
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    openWindow();
                    System.out.println("Amazing Test");
                }
            });
            
        }
    	private static void openWindow() {
            //Create and set up the window.
            JFrame frame = new JFrame("Project Gensis");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
            frame.add(new paintPanel());
            frame.pack();
            frame.setLocation(400, 200);
            frame.setResizable(false);
            frame.setVisible(true);
            
    	}
    	
    }
    /*
     * paintPanel maintains all painting done. Any paint that needs to be done
     * is done in some way in this class. this class specifically handles painting.
     */
    	class paintPanel extends JPanel implements Runnable{
    		private int squareX = 50;
    		private int squareY = 50;
    		private int squareW = 20;
    		private int squareH = 20;
    		private static final long serialVersionUID = 4571873835675940359L;
    
    		
    		public void run(){
    			System.out.println("Still Running");
    			try {
    				Thread.sleep(200);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		public paintPanel(){
    			setBorder(BorderFactory.createLineBorder(Color.black));
    			
    			/** Example Mouse Listener Events (Pressed/Dragged Respectively)
    			 * Notice variable e is the variable for the mouse
    			 * e.getX()/e.getY() calls the location of the cursor currently.
    			 */
    			addMouseListener(new MouseAdapter() {
    	            public void mousePressed(MouseEvent e) {
    	                moveSquare(e.getX(),e.getY());
    	            }
    	        });
    	        addMouseMotionListener(new MouseAdapter() {
    	            public void mouseDragged(MouseEvent e) {
    	                moveSquare(e.getX(),e.getY());
    	            }
    	        });
    		}
    		public Dimension getPreferredSize() {
    			return new Dimension(500,500);
    		}
    		public void paintComponent(Graphics g){
    			super.paintComponent(g);     
    	        drawEnviroment(g);
    	        g.setColor(Color.red);
    			g.drawString("Welcome to Project Gensis",180,450);
    	        g.setColor(Color.RED);
    	        g.fillRect(squareX,squareY,squareW,squareH);
    	        g.setColor(Color.BLACK);
    	        g.drawRect(squareX,squareY,squareW,squareH);
    		}
    	    private void moveSquare(int x, int y) {
    	        int OFFSET = 1;
    	        if ((squareX!=x) || (squareY!=y)) {
    	            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
    	            squareX=x;
    	            squareY=y;
    	            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
    	        } 
    	        System.out.println("Cursor Location: (" + x + "," + y + ")");
    	    }
    	    private void drawEnviroment(Graphics g){
    	    	int x=20;
    	    	int y=20;
    	    	int width=460;
    	    	int height=460;
    	    	g.fillRect(x,y, width, height);
    	    	g.setColor(Color.red);
    	    	for(int x1=64,y1=430,x2=64,y2=64, i=0;i<9;x1=x1+46,x2=x2+46,i++)
    	    		g.drawLine(x1, y1, x2, y2);
    	    	for(int x1=64,y1=64,x2=430,y2=64, i=0;i<9;y1=y1+46,y2=y2+46,i++)
    	    		g.drawLine(x1, y1, x2, y2);
    	    }
    	}

    Thanks for any help. I've been going through a lot of tutorials so some of the code may look familiar!

  2. #2
    Moncleared is offline Member
    Join Date
    Jan 2009
    Posts
    92
    Rep Power
    0

    Default Its me again

    I've created a thread now and I'd like to be able to use the graphics g in it. It might be as simple as passing it graphics g but somehow I am missing something. Here is the new code:

    Java Code:
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    
    public class Main {
    	    public static void main(String[] args) {
            //Schedule a job for the event-dispatching thread:
            //creating and showing this application's GUI.
    //	    Thread thread1 = new Thread(new RunnableThread(), "thread1");
    //	    thread1.start();
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    openWindow();
                    System.out.println("Amazing Test");
                }
            });
        }
    	private static void openWindow() {
            //Create and set up the window.
            JFrame frame = new JFrame("Project Gensis");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
            frame.add(new paintPanel());
            frame.pack();
            frame.setLocation(400, 200);
            frame.setResizable(false);
            frame.setVisible(true);
            
    	}	
    }
    class RunnableThread implements Runnable {
    	Thread runner;
    	public RunnableThread() {
    	}
    	public RunnableThread(String threadName) {
    		runner = new Thread(this, threadName); // (1) Create a new thread.
    		System.out.println(runner.getName());
    		runner.start(); // (2) Start the thread.
    	}
    	public void run() {
    		//Display info about this particular thread
    		while(true){
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		System.out.println(Thread.currentThread());
    		}
    	}
    
    }
    
    /*
     * paintPanel maintains all painting done. Any paint that needs to be done
     * is done in some way in this class. this class specifically handles painting.
     */
    	class paintPanel extends JPanel{
    		private int squareX = 50;
    		private int squareY = 50;
    		private int squareW = 20;
    		private int squareH = 20;
    		private static final long serialVersionUID = 4571873835675940359L;
    
    		public paintPanel(){
    			setBorder(BorderFactory.createLineBorder(Color.black));
    			Thread thread1 = new Thread(new RunnableThread(), "thread1");
    		    thread1.start();
    			/** Example Mouse Listener Events (Pressed/Dragged Respectively)
    			 * Notice variable e is the variable for the mouse
    			 * e.getX()/e.getY() calls the location of the cursor currently.
    			 */
    			addMouseListener(new MouseAdapter() {
    	            public void mousePressed(MouseEvent e) {
    	                moveSquare(e.getX(),e.getY());
    	            }
    	        });
    	        addMouseMotionListener(new MouseAdapter() {
    	            public void mouseDragged(MouseEvent e) {
    	                moveSquare(e.getX(),e.getY());
    	            }
    	        });
    		}
    		public Dimension getPreferredSize() {
    			return new Dimension(500,500);
    		}
    		public void paintComponent(Graphics g){
    			super.paintComponent(g);     
    	        drawEnviroment(g);
    	        g.setColor(Color.red);
    			g.drawString("Welcome to Project Gensis",180,450);
    	        g.setColor(Color.RED);
    	        g.fillRect(squareX,squareY,squareW,squareH);
    	        g.setColor(Color.BLACK);
    	        g.drawRect(squareX,squareY,squareW,squareH);
    		}
    	    private void moveSquare(int x, int y) {
    	        int OFFSET = 1;
    	        if ((squareX!=x) || (squareY!=y)) {
    	            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
    	            squareX=x;
    	            squareY=y;
    	            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
    	        } 
    	        System.out.println("Cursor Location: (" + x + "," + y + ")");
    	    }
    	    private void drawEnviroment(Graphics g){
    	    	int x=20;
    	    	int y=20;
    	    	int width=460;
    	    	int height=460;
    	    	g.fillRect(x,y, width, height);
    	    	g.setColor(Color.red);
    	    	for(int x1=64,y1=430,x2=64,y2=64, i=0;i<9;x1=x1+46,x2=x2+46,i++)
    	    		g.drawLine(x1, y1, x2, y2);
    	    	for(int x1=64,y1=64,x2=430,y2=64, i=0;i<9;y1=y1+46,y2=y2+46,i++)
    	    		g.drawLine(x1, y1, x2, y2);
    	    }
    	}
    Is it not possible at all to do any graphic related stuff inside that thread's public void run() ?

  3. #3
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    For timer issues where something needs to be done every xxx milliseconds, I mainly use a Swing Timer. For background processes that hog a lot of the CPU, I often use either a background thread or a SwingWorker. I've done projects where I have to use both the Timer and the SwingWorker. Have you used these constructs before, and are you familiar with them?

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    I've created a thread now and I'd like to be able to use the graphics g in it. It might be as simple as passing it graphics g but somehow I am missing something.
    I would advise you strongly not to do this. All work with graphics must be done on one thread and one thread only: the EDT. Sure, use a background thread to do complicated calculations, then use the calculations to update class variables, and then call repaint to have your paintComponent method use those class variables to draw something, but do not do the drawing itself in the background thread.

  5. #5
    Moncleared is offline Member
    Join Date
    Jan 2009
    Posts
    92
    Rep Power
    0

    Default

    I'm not familiar with Swing Timer, I will look into it though, I'm sure there are plenty of tutorials out there.

    Thanks!

  6. #6
    Moncleared is offline Member
    Join Date
    Jan 2009
    Posts
    92
    Rep Power
    0

    Default

    I believe the Swing Timer will work, it was a lot easier to implement. I can also call the repaint() from it, theres nothing wrong with doing that correct? As you suggested I can put inside my EventLIstener any variable changes and then call the repaint() to update any drawing I need.

    Thanks

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Yes, that should work. It's great for timing but does not replace background threads when needed. Everything done in the Swing Timer's ActionListener is done on the EDT. So if it initiates a big mammoth calculation or a file read or write, all this could potentially slow or stall the EDT crippling your program. In those situations, you could use a Swing Timer and a background thread such as a SwingWorker.

    Good luck.

  8. #8
    Moncleared is offline Member
    Join Date
    Jan 2009
    Posts
    92
    Rep Power
    0

    Default

    Thanks again,

    I'll probably be around with more silly questions as the semester thickens, but hopefully Google won't fail me too much!

    Monc

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Another suggestion: get rid of your magic numbers. For instance, what if your requirements change and rather than your grid having 9 lines in each direction and 8 rows and columns, you're supposed to have 11 lines and 10 rows and columns: how hard would it be to make the changes? Now contrast that to this code:

    Java Code:
    class GraphicPanel
    {
      private static final int WIDTH = 500;
      private static final Dimension GRAPHIC_PANEL_PSIZE = new Dimension(WIDTH, WIDTH);
      private static final int BORDER = 20;
      private static final int LINE_COUNT = 9;
      private static final double GAP = ((double)WIDTH - 2*BORDER)/((double)LINE_COUNT + 1); 
      private static final double X0 = BORDER + GAP;
      private static final double XMAX = WIDTH - X0;
      private JPanel mainPanel = new JPanel()
      {
        @Override
        protected void paintComponent(Graphics g)
        {
          super.paintComponent(g);
          myPaint(g);
        }
      };
    
      public GraphicPanel()
      {
        mainPanel.setPreferredSize(GRAPHIC_PANEL_PSIZE);
      }
    
      protected void myPaint(Graphics g)
      {
        drawEnviroment(g);
      }
      
      private void drawEnviroment(Graphics g)
      {
        int width = WIDTH - 2*BORDER;
        int height = WIDTH - 2*BORDER;
        g.setColor(Color.black);
        g.fillRect(BORDER, BORDER, width, height);
        g.setColor(Color.red);
        double x1 = X0;
        for (int i = 0; i < LINE_COUNT; i++)
        {
          g.drawLine((int)x1, (int)XMAX, (int)x1, (int)X0);
          g.drawLine((int)XMAX, (int)x1, (int)X0, (int)x1);
          x1 += GAP;
        }
      }
    
      public JComponent getComponent()
      {
        return mainPanel;
      }
      
    }
    To change this code requires changing one constant, LINE_COUNT from 9 to 11. Do you see the power here?

  10. #10
    Moncleared is offline Member
    Join Date
    Jan 2009
    Posts
    92
    Rep Power
    0

    Default

    I see the power for sure. Problem is when I'm in a rush and trying to get a very sketch makeup done so I can see what it looks like I have a bad tendency of not going back and making those variables!

Similar Threads

  1. Question mark colon operator question
    By orchid in forum Advanced Java
    Replies: 9
    Last Post: 12-19-2010, 08:49 AM
  2. Swing Question, can you help?
    By Silentstormz in forum AWT / Swing
    Replies: 4
    Last Post: 09-21-2008, 03:02 AM
  3. JFrame Question ?
    By Mindhunter74 in forum New To Java
    Replies: 2
    Last Post: 12-21-2007, 10:45 PM
  4. JFrame question
    By Try2Live4God in forum New To Java
    Replies: 2
    Last Post: 10-15-2007, 01:52 AM
  5. map javax.swing.text.Element to javax.swing.text.View
    By elizabeth in forum New To Java
    Replies: 1
    Last Post: 07-30-2007, 07:02 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •