简体   繁体   中英

Calling the methods in a class in Java

I have a very basic question: my MainDriver class wishes to run the Line class when a button Line is pressed; however, I know we cannot run a whole class, so if there's another way to implement this, please let me know.

The following is the MainDriver class; I've highlighted the relevant bit in astericks.

package javafx.scene;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
//import java.awt.*;
class MainDriver extends JFrame implements ActionListener { 
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    // create a frame 
    static JFrame frame; 


    // main function 
    public static void main(String args[]) 
    { 
        // create a frame 
        frame = new JFrame("DrawShapes"); 

        try { 
            // set look and feel 
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
        } 
        catch (Exception e) { 
            System.err.println(e.getMessage()); 
        } 

        // create a object of class 
        Line line = new Line(); 

        // create number buttons and some operators 
        JButton b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bs, bd, bm, be, beq; 

        // create number buttons 
        b0 = new JButton("line"); 
        b1 = new JButton("circle"); 
        b2 = new JButton("triangle"); 
        b3 = new JButton("rectangle"); 
        b4 = new JButton("quadrilateral"); 
        b5 = new JButton("move"); 
        b6 = new JButton("copy"); 
        b7 = new JButton("delete"); 
        b8 = new JButton("random"); 
        b9 = new JButton("import");
        ba = new JButton("export"); 
        bs = new JButton(""); 
        bd = new JButton("/"); 
        bm = new JButton("*"); 
        beq = new JButton("C"); 

        // create . button 
        be = new JButton("."); 

        // create a panel 
        JPanel p = new JPanel(); 

        // add action listeners 
        b0.addActionListener(line); 
   //add more later 


        // add elements to panel 
        p.add(b0); 
        p.add(ba); 
        p.add(b1); 
        p.add(b2); 
        p.add(b3); 
        p.add(bs); 
        p.add(b4); 
        p.add(b5); 
        p.add(b6); 
        p.add(bm); 
        p.add(b7); 
        p.add(b8); 
        p.add(b9); 
        p.add(bd); 
        p.add(be); 
        p.add(b0); 
        p.add(beq); 


        // set Background of panel 
        p.setBackground(Color.blue); 

        // add panel to frame 
        frame.add(p); 

        frame.setSize(450, 400); 

    } 
    public void actionPerformed(ActionEvent e) 
    { 
        String s = e.getActionCommand(); 
            *************************
            if (s.equals("line")) {
                //Im not sure how to implement the object here
            }
            ***************************


        } 

} 

And here's the Line class

package javafx.scene;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

@SuppressWarnings("serial")
public class Line extends JPanel implements MouseListener,ActionListener{

    private int x,y,x2,y2,a=1;
    public Line(){
        super();
        addMouseListener(this);   
    }

    public void paint(Graphics g){
        int w = x2 - x ;
        int h = y2 - y ;
        int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0 ;
        if (w<0) dx1 = -1 ; else if (w>0) dx1 = 1 ;
        if (h<0) dy1 = -1 ; else if (h>0) dy1 = 1 ;
        if (w<0) dx2 = -1 ; else if (w>0) dx2 = 1 ;
        int longest = Math.abs(w) ;
        int shortest = Math.abs(h) ;
        if (!(longest>shortest)) {
            longest = Math.abs(h) ;
            shortest = Math.abs(w) ;
            if (h<0) dy2 = -1 ; else if (h>0) dy2 = 1 ;
            dx2 = 0 ;            
        }
        int numerator = longest >> 1 ;
        for (int i=0;i<=longest;i++) {
            g.fillRect(x,y,1,1);
            numerator += shortest ;
            if (!(numerator<longest)) {
                numerator -= longest ;
                x += dx1 ;
                y += dy1 ; 
            } else {
                x += dx2 ;
                y += dy2 ;
            }
        }
    }

    public void mouseClicked(MouseEvent mouse) {
        if (a == 1) {
            a = 0;
            x = x2 = mouse.getX();
            y = y2 = mouse.getY();
        } else {
            a = 1;
            x = x2;
            y = y2;
            x2 = mouse.getX();
            y2 = mouse.getY();
            repaint();
        }
    }

    public void mouseEntered(MouseEvent mouse){ }   
    public void mouseExited(MouseEvent mouse){ }
    public void mousePressed(MouseEvent mouse){ }
    public void mouseReleased(MouseEvent mouse){ }


    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub

    }
}

Here is an example on how to go about it:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;

public class Main {

    private static void drawPoint(final Graphics g, final Point p) {
        g.drawLine(p.x - 10, p.y, p.x + 10, p.y);
        g.drawLine(p.x, p.y - 10, p.x, p.y + 10);
    }

    private static void drawLine(final Graphics g, final Point p1, final Point p2) {
        g.drawLine(p1.x, p1.y, p2.x, p2.y);
    }

    public static interface ShapeByPoints {
        int getPointCount();
        void draw(final Graphics g, final Point... points);
    }

    public static class DrawPanel extends JPanel {
        private final ArrayList<Point> points;
        private ShapeByPoints s;

        public DrawPanel() {
            points = new ArrayList<>();
            s = null;
        }

        public void setShape(final ShapeByPoints s) {
            this.s = s;
            points.clear();
            repaint();
        }

        public void modifyLastPoint(final Point p) {
            points.get(points.size() - 1).setLocation(p);
            repaint();
        }

        public void addPoint(final Point p) {
            if (s != null && points.size() == s.getPointCount())
                points.clear();
            points.add(p);
            repaint();
        }

        @Override
        protected void paintComponent(final Graphics g) {
            super.paintComponent(g);
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            if (s != null && s.getPointCount() == points.size())
                s.draw(g, points.toArray(new Point[s.getPointCount()]));
            else {
                points.forEach(p -> drawPoint(g, p));
                for (int i = 1; i < points.size(); ++i)
                    drawLine(g, points.get(i - 1), points.get(i));
            }
        }
    }

    public static class EllipseByPoints implements ShapeByPoints {
        @Override
        public int getPointCount() {
            return 2;
        }

        @Override
        public void draw(final Graphics g, final Point... points) {
            g.drawOval(Math.min(points[0].x, points[1].x), Math.min(points[0].y, points[1].y), Math.abs(points[1].x - points[0].x), Math.abs(points[1].y - points[0].y));
        }
    }

    public static class PolygonByPoints implements ShapeByPoints {
        private final int points;

        public PolygonByPoints(final int points) {
            this.points = points;
        }

        @Override
        public int getPointCount() {
            return points;
        }

        @Override
        public void draw(final Graphics g, final Point... points) {
            for (int i = 1; i < this.points; ++i)
                drawLine(g, points[i - 1], points[i]);
            drawLine(g, points[this.points - 1], points[0]);
        }
    }

    public static class LineByPoints extends PolygonByPoints {
        public LineByPoints() {
            super(2);
        }
    }

    public static class RectangleByPoints implements ShapeByPoints {
        @Override
        public int getPointCount() {
            return 2;
        }

        @Override
        public void draw(final Graphics g, final Point... points) {
            g.drawRect(Math.min(points[0].x, points[1].x), Math.min(points[0].y, points[1].y), Math.abs(points[1].x - points[0].x), Math.abs(points[1].y - points[0].y));
        }
    }

    private static JRadioButton createButton(final String buttonText, final ButtonGroup bg, final DrawPanel dp, final ShapeByPoints s) {
        final JRadioButton btn = new JRadioButton(buttonText);
        btn.addActionListener(e -> dp.setShape(s));
        bg.add(btn);
        return btn;
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(() -> {
            final DrawPanel dp = new DrawPanel();

            final MouseAdapter ma = new MouseAdapter() {
                @Override
                public void mousePressed(final MouseEvent mevt) {
                    dp.addPoint(mevt.getPoint());
                }

                @Override
                public void mouseDragged(final MouseEvent mevt) {
                    dp.modifyLastPoint(mevt.getPoint());
                }

                @Override
                public void mouseReleased(final MouseEvent mevt) {
                    dp.modifyLastPoint(mevt.getPoint());
                }
            };

            dp.setPreferredSize(new Dimension(500, 350));
            dp.addMouseListener(ma);
            dp.addMouseMotionListener(ma);

            final ButtonGroup bg = new ButtonGroup();

            final JPanel buttons = new JPanel();
            buttons.add(createButton("Line", bg, dp, new LineByPoints()));
            buttons.add(createButton("Ellipse", bg, dp, new EllipseByPoints()));
            buttons.add(createButton("Rectangle", bg, dp, new RectangleByPoints()));
            buttons.add(createButton("Triangle", bg, dp, new PolygonByPoints(3)));
            buttons.add(createButton("Pentagon", bg, dp, new PolygonByPoints(5)));
            //... keep creating buttons here ...

            final JPanel contents = new JPanel(new BorderLayout());
            contents.add(dp, BorderLayout.CENTER);
            contents.add(buttons, BorderLayout.PAGE_START);

            final JFrame frame = new JFrame("Clicking shapes.");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(contents);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}

Notes:

  1. Don't use paint unless there is good reason, which usually isn't. In most cases you want to draw the panel, in which case paintComponent should be enough.
  2. Dont' forget to firstly call super.paintComponent inside paintComponent override. This should be the first call, because it will clear the panel for you from previous drawings.
  3. Decide if you want to add JComponent s which will draw the shapes, or draw the shapes yourself in a sub-classed panel. In this case, it seems like you are trying both (because Line extends JPanel and you also override paint ). In my opinion, in this case, using an abstraction of a shape to be drawn between some points will do the job. That's why I created ShapeByPoints interface.
  4. Swing is not thread safe, which means there can be conditions between competing accesses of the same variable. To avoid such scenarios, you can run every Swing related operation at the Event Dispatch Thread (or EDT for short). To explicitly make a call in the EDT, invoke a method like SwingUtilities.invokeLater , SwingUtilities.invokeAndWait , EventQueue.invokeLater and so on... There is enough material on the Internet about this topic. For example here .
  5. Basically everything is redesigned from scratch in my approach (ie I did not modify your example code, because I guessed it would take a little bit more time, but that's just a guess).

I just created the ShapeByPoints interface which specifies how a shape is supposedly drawn (ie number of points it needs, and a draw method to do the drawing).

Then I created a DrawPanel extends JPanel which contains the state of each operation. For example if the user selects a pentagon to be drawn, he needs 5 points, but what happens when he/she has clicked only twice?... The DrawPanel is responsible for such scenarios and also for drawing the given shape when all the points are completed/clicked.

I added an instance of a DrawPanel in the frame, a MouseAdapter for user interaction and a couple of buttons to demonstrate this logic.

All you need to do now, is to implement ShapeByPoints as you like and supply an instance of it to the DrawPanel depending of the button pressed. I already did some examples on how to do it in the code (like an EllipseByPoints , LineByPoints , RectangleByPoints and PolygonByPoints ).

Finally, as a bonus, I added the ability to drag the clicked points (ie not only click them, but click-and-drag them).

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM