CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 31
  1. #1
    Join Date
    Dec 2003
    Posts
    593

    Basic style of my assignment

    Hi everyone. After christmas I have to hand in a Java assignment that consists of a GUI that can show either a square or a circle in a white viewing area, and alows the user to alter various attributes of the shape using various widgets at the side of the viewing area. I've finished the assignment, but because it's such a basic task a lot of marks will be handed out for style and sensible implementation. If any of you have some time could you please give my code a quick check through and let me know if my style is ok. I think i've followed all the guidelines to the letter, but i'm quite new to java.

    Also, is my implementation of the square and circle class sensible? I've implemented them both as extensions of JPanel and given them their own paintComponent() methods to draw the corresponding shapes. I've then put them in a cardLayout stored in the viewing area JPanel.

    Any pointers on my code would be much appreciated, thanks. If you run the code nothing will happen until you press the reset button (part of the specification).

    Thanks
    Attached Files Attached Files

  2. #2
    I'm no expert, but that looks like a very good job to me. Very neat, logical and easy to follow.
    Note: I am a novice, take anything I say as coming from such.

  3. #3
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163
    Looks good to me - very good...

    My only comments would be that the application class name (mjbarr_shapes) should be capitalized, you don't need to redeclare the default constructor and call super() if you're not going to do anything extra there, and I'd probably make the duplicated calculations in the shape drawing [(int) ((getWidth() - shapeWidth) / 2), etc.] into private methods just for tidiness and elegance (always eliminate duplicate code where possible).

    Out of clutter, find simplicity. From discord, find harmony. In the middle of difficulty, lies opportunity...
    A. Einstein
    Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  4. #4
    Join Date
    Dec 2003
    Posts
    593
    I don't like the application class name at all, but we were told to name it that (mjbarr is my username at university) so he can identify what it is and who wrote it.

    I'll write those private methods, silly me for not thinking of that. Thanks for the help.

  5. #5
    Join Date
    Dec 2003
    Posts
    593
    Originally posted by Barancle
    I'm no expert, but that looks like a very good job to me. Very neat, logical and easy to follow.
    Thanks Barancle, nice to know i'm on the right track. As long as my lecturer agrees i'll be happy
    Last edited by mikeBarr81; January 5th, 2004 at 06:59 PM.

  6. #6
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104
    observations, that may or may not be relevant based on your university in-house style. feel free to ignore observations that do not apply:



    no javadoc comments?

    some minor spelling errors in comments (i was always picked up on them)

    use of tabs instead of spaces for indentation; tab size varies per machine. space size is fixed. tab of 8+ can make code really ugly

    indentation problems within abstract class Shapes, method: (constructor)
    indentation problems within class ShapesWindow, method: (constructor)

    use of plural "shapes" as a class name imples collection of objects: compare "Circle extends Shape" vs "Circle extends Shapes"
    see: http://java.sun.com/docs/books/tutor.../abstract.html

    in the interests of future expansion, you should consider adding attributes for the Height (though for circles and squares they are the same as the width). you can then say the program may be easily modified to draw another shape by writing a class for it

    additionally, i think you reference the square and the circle directly and draw them using individual lines of code:
    Code:
    				//set the width to the shape
    				square.setShapeWidth(newWidth);
    				circle.setShapeWidth(newWidth);
    if your project is as a teaching point of inheritance, code re-use and abstraction, you will have only one shape; declared to be of type Shapes, but instantiated to be either a square or a circle:
    Code:
    private Shapes theShape;
    theShape = new Square();
    in either case you can set the width, height, and tell it to draw; both shapes have a draw method, and if theShape is of type Square, a square will be drawn, if it is of type Circle, a circle will be drawn. This makes adding new shapes a doddle; you extend the abstract class, and add them to the radiobutton group. clicking a radio button makes a new instance of the specific shape, but all code calls theShape generic class. THis is also partly why i recommended having a height attribute in the shape, even if it is set = to width for circle/square (or ignored, and use width only in fillRect/Oval)..

    _______

    Excellent job overall
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

  7. #7
    Join Date
    Dec 2003
    Posts
    593
    Thanks for the reply Cjard.

    I'm not sure what a javadoc comment is, how is it different to the comments i have in my assignment? I don't remember my lecturer mentioning them, but it may be that i'm just being forgetful.

    I wrote the assignment in textpad (the text editor the university uses and recommends), and it automatically indents code if it is in a .java file. I tried to clean it up when i posted it as a .text file but i guess it didn't work.

    About the rest of your posts, I think I understand what you mean but I don't have my assignment here with me so I can't work on it. As soon as i get home i'll try adn do what you said. Again, thanks for your help

  8. #8
    Join Date
    Dec 2003
    Posts
    593
    Ok, i think i've made the changes you suggested about having just one Shapes object but i'm having trouble getting it to display now the shapeArea.add(...) statement isn't in the constructor. I've altered the resetButton listener to this:-

    Code:
    public void actionPerformed(ActionEvent e)
    {
        if (e.getSource() instanceof JButton)
        {
            if (!resetPressed)
            {
                resetPressed = true;
            }
    
            theShape = new Square();
            shapeArea.add(theShape, BorderLayout.CENTER);
            theShape.repaint();
    
    .....plus various lines of code to set the widget settings as before
        
        }
    }
    the lines that set the widget settings work fine as before, but nothing the shape is no longer shown. Does the shapeArea.add() statement only work in the constructor, and if so how do I go about adding theShape to shapeArea and getting it to display? I tried the above method with and without the call to repaint() and neither worked. Can anyone tell me where i'm going wrong?

    (The code compiles fine, and it runs without runtime errors. No errors are produced on the console when the reset button is pressed either. It simply fails to display the shape. The widget settings are changed to the correct values, so the handler is being called fine).

    Thanks in advance

  9. #9
    Join Date
    Apr 2003
    Location
    Los Angeles area
    Posts
    776
    Javadoc.exe is in your SDK/bin folder. It is used to turn your source files into html class documentation like you see in the SDK documentation. I know the Netbeans IDE and the Sun Studio both support auto commenting GUI/tags into your source code to handle the Javadoc parser. It's intuitive and easy on the eyes.

    I think this assignment to draw shapes using inheritance is in every first java course. You might consider that a shape is not a Jpanel but is its own base type. All it has to do is draw itself which if you look at your existing code boils down to the drawing function having access to a Graphics object. This allows you to paint a square and a circle on the same pane if you want, overlapping them. This removes extra object overhead of jPanel and allows you to paint a shape on anything that can supply a graphics panel to the draw function.

  10. #10
    Join Date
    Dec 2003
    Posts
    593
    i get your point about it not needing to be a JPanel, but i'm not sure how to get it to draw on another JPanel. It wouldn't have the paintComponent method if it didn't extend something like JPanel would it?

  11. #11
    This is a really lame example and I'm sure there are a dozen things wrong with it, but it does show how one might paint an object that is not a Component.
    Code:
    import javax.swing.*;
    import java.awt.*;
    
    class Tester{
      public static void main(String[] args){
        Sample sample = new Sample();
        
        JFrame myJFrame = new JFrame("Test");
        myJFrame.setSize(300, 300);
        myJFrame.setContentPane(sample);
        myJFrame.show();
      }
    }
    class Sample extends JPanel{
      Square mySquare;
      Sample(){
        mySquare = new Square();
      }
      public void paint(Graphics page){
        page.setColor(Color.BLACK);
        mySquare.doThing(page, 100);
      }
    }
    class Square{
      public void doThing(Graphics page, int size){
        page.fillRect(0,0,size,size);
      }
    }
    Note: I am a novice, take anything I say as coming from such.

  12. #12
    Join Date
    Apr 2003
    Location
    Los Angeles area
    Posts
    776
    To display shapes you need to pass the Graphics object of your container. Every AWT or SWING component has a member function called getGraphics() which returns a Graphics object. Say you have JPanel you want to put the shapes on.

    Code:
    public class myshapesapp extends JFrame
    {
         private JPanel displaypanel = new Jpanel();
         
         myshapesapp() {
               Shape shapes[] = new Shape[10];
               shapes[0] = new Circle();
               shapes[1] = new Square();
               shapes[2] = new Triangle();
               
                add(displaypanel);
                /// now you can call drawmyshapes()
                drawmyshapes();
          }
       
          drawmyshapes(){
                Graphics g = displaypanel.getGraphics(g);
                for(int i=0;i<10;i++)
                    shapes[i].draw(g);
          }
    }
    I'm a little rusty on the java code but this is the basic idea. Since all shapes must be able to draw themselves you could be "more object oriented" by declaring an ABSTRACT draw(Graphics g) function. Derived classes (circle,square,etc) will override this draw function. If you don't understand this then leave it out as your instructor may ask you why you would do something like this.

    The only thing about this code is that drawmyshapes() only draws the shapes once per call. Thats to say if another window covers it then uncovers the java app you will need to make another call to drawmyshapes(). Since this is school work I leave to you to work out the specifics of making your displaypanel draw the shapes on demand. There are a couple approaches, one you have already done.

  13. #13
    Join Date
    Dec 2003
    Posts
    593
    Originally posted by cjard
    if your project is as a teaching point of inheritance, code re-use and abstraction, you will have only one shape; declared to be of type Shapes, but instantiated to be either a square or a circle:

    code:--------------------------------------------------------------------------------
    private Shapes theShape;
    theShape = new Square();
    --------------------------------------------------------------------------------
    I understand why I should do it in this way, but how do I change the object from square to circle and vice versa when the radio button is pressed? We were specifically told not to rediscover them from the values of the widgets (ie they should be stored in the shape object, and only update specific values when they change). I originally thought i'd be able to cast between square and circle because the object is of type Shapes but when i tried that i got a scroll of runtime messages on the dos prompt. Is there an easy way to do it?

  14. #14
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163
    how do I change the object from square to circle and vice versa when the radio button is pressed?
    I haven't been following very closely, but I would suggest simply creating an instance of each shape (Square or Circle) at the start, then when the radiobutton switches between them, simply hide the current shape and show the hidden shape. That way, you can keep your shape hierarchy tidy and you separate display considerations from shape creation:
    Code:
    Circle circle = new Circle(...);
    Square square = new Square(...);
    ...
    Shape currentShape = circle;   // default
    ...
    // toggle shape:
    currentShape = (currentShape instanceof Square) ? circle : square;
    ...
    displayShape(currentShape);
    Or whatever...

    Everything should be made as simple as possible, but not simpler...
    A. Einstein
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  15. #15
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104
    Originally posted by mikeBarr81

    I originally thought i'd be able to cast between square and circle because the object is of type Shapes but when i tried that i got a scroll of runtime messages on the dos prompt. Is there an easy way to do it?
    casting for these purposes works in only one direction: downwards from the generic to the specific.

    You declare an object of type Shape. and it is very general. it has height, width and filled properties. ALL shapes have these

    Then when you make a specific example of a circle, or square, it has specific properties of that particular shape, but you can still refer to it as a Shape. There is a separation here though.. and you cannot say:
    Circle is-a Shape. Square is-a Shape, therefore a Circle is-a Square. In taking your generic shape object, you can cast it into what it is suppsoed to be, but you cannot convert it from one thing to another

    A real world example. Imagine there is a blue bus, a cyan car and a violet van in the university car park. You point to them and tell a friend
    "there are 3 vehicles out there" - no problem.
    "Look at that blue bus." - no problem.
    "look at that cyan vehicle" - no problem.
    "look at that violet car" - your mate looks at you like you had too many joints last night

    java works in the same way; you can have 3 shapes, all of which are of type Shape, all of which have changeable generic properties, and all of which can be told to draw() themselves.. but theres where the implementation changes. a circle specifically takes the width and draw()s a circle, a square specifically draw()s a square, but using the same set of attributes that a circle has (width, height and fill)

    hence, you have in your project:

    a area reserved in your GUI, for a JPanel
    the area with the JPanel will actually be given a Shape, because a Shape is-a JPanel
    when the the JPanel is add()ed to the gui where it should be, java will tell it to draw()
    at this moment, if the JPanel is of type Shape is of type Circle, a circle will be drawn
    and if its a JPanel of type Shape of type Square,a square will be drawn. can you see how this works?

    remember: to your gui, youre supposed to add the generic supertype "Shape"
    you can then, so long as you keep a reference to that, set it to be either a circle or a square, simply by re-pointing to the relevant shape. Joe Nellis is actually pretty close with his code, some scope problems, and probably mine isnt perfect, but it outlines the idea:

    Code:
    public class myshapesapp extends JFrame
    {
      private JPanel toBeDrawn = new Jpanel();
    
      //this will make it easier for our program to support
      //up to 10 different shapes
      Shape[] allShapes = new Shape[10];
    
      //these will be array indexes
      final int CIRCLE_TYPE = 0;
      final int SQUARE_TYPE = 1;
    
      myshapesapp() {
    
        //add the drawing area
        this.add(toBeDrawn);
    
        //add the radio buttons, sliders etc
        this.add(...)
      }
    
      actionlistener(source){
        if(source == circle_radiobutton){
          //check to see if we made a circle already
          if(allShapes[CIRCLE_TYPE] == null)
            allShapes[CIRCLE_TYPE] = new Circle(...);
    
          //now we cause java to draw the Circle
          toBeDrawn = allShapes[CIRCLE_TYPE];
    
          //remember, toBeDrawn is-a JPanel
          //and Circle is-a Shape, which is-a JPanel
          //so java knows it can call paint() / repaint() on the JPanel
          //Because Shape is-a JPanel, it is also guaranteed to
          // have a paint() and repaint() method
          //Now the trick of it is, that Circle has a paint() that should
          // paint a circle.
          //Java doesnt care what paint() does.. it just calls it
          toBeDrawn.repaint();
        }
    
        else if(source == square_radiobutton){
          //check if we made a square already?
          if(allShapes[SQUARE_TYPE] == null)
            allShapes[SQUARE_TYPE] = new Square(...);
    
          //its guaranteed not to be null now, so we draw it
          toBeDrawn = allShapes[SQUARE_TYPE];
          toBeDrawn.repaint();
        }
    
      }
    }
    do you see, how easy it would be to add a triangle?
    You just make another FINAL INT for the triangle, numbered 2 (or anything up to 9)
    add a radiobutton for the triangle
    make that clicking on the radiobutton first checks if a triangle exists already, if not, make it
    then draw it

    the idea of making the triangle in the radiobutton check code, is that we dont have to make it eslewhere; sure you can make it in the constructor for jFrame, just like all the other shapes can be made there too, but then youre ending up where youre editing line 6 of the code, then line 15, then line 27, then line 42....

    its easier to maintain your code if you say "to add a new shape, make a final int for it, then do the rest of the code in the radiobutton handler" - it keeps it all together

    the idea of keeping your "hidden" Shapes in an array, is that you can use a loop to iterate over the array when you change a slider/checkbox- move the slider and all the shape sizes change.. remmeber, that a Circle/Square/Triangle/Rectangle is guaranteed to have a setWidth and setHeight, because they are all of type Shape, and Shape has those methods. Those methods always do identical things. It is the draw method that uses them in disfferent ways. The draw method is always called by java. and java doesnt care what is drawn

    do you see how the inheritance works?
    Last edited by cjard; January 15th, 2004 at 07:08 AM.
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

Page 1 of 3 123 LastLast

Posting Permissions

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





Click Here to Expand Forum to Full Width

Featured