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:
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.super.paintComponent
inside paintComponent
override. This should be the first call, because it will clear the panel for you from previous drawings.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.SwingUtilities.invokeLater
, SwingUtilities.invokeAndWait
, EventQueue.invokeLater
and so on... There is enough material on the Internet about this topic. For example here . 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.