Reputation:
I have to produce a randomly-sized shape (from 50 to 300 pixels) in a java GUI. There is a JList of 3 shapes (rectangle, square, circle) that the user can choose from, and when they choose one, a randomly-sized rectangle, square, or circle should appear in the GUI.
I guess I'm just having trouble figuring out where and how to implement the list selection listeners.
Here is my code so far:
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
public class ShapeSelectionWindow extends JPanel implements ListSelectionListener{
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
width = (int)Math.floor(Math.random()*250) + 50;
height = (int)Math.floor(Math.random()*250) + 50;
x = (int)Math.floor((615 - width) / 2);
y = (int)Math.floor((661 - height) / 2);
g.fillRect(x, y, width, height);
}
public static void main(String[] args) {
ShapeSelectionWindow ssw = new ShapeSelectionWindow();
JFrame jf = new JFrame();
JPanel shapeListPanel = new JPanel();
shapeListPanel.setBackground(Color.WHITE);
DefaultListModel<String> dlm = new DefaultListModel<String>();
dlm.addElement("Rectangle");
dlm.addElement("Square");
dlm.addElement("Circle");
JList<String> shapeList = new JList<String>(dlm);
shapeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
shapeListPanel.add(shapeList);
jf.getContentPane().setLayout(new BorderLayout());
jf.getContentPane().add(ssw, BorderLayout.CENTER);
jf.getContentPane().add(shapeListPanel, BorderLayout.EAST);
jf.setTitle("Simple Drawing GUI");
jf.setSize(700, 700);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
@Override
public void valueChanged(ListSelectionEvent e) {
// TODO Auto-generated method stub
}
}
The current paintComponent method is for painting a rectangle. Like I said, I'm not sure how to implement the list selection listeners for this project in order to produce different shapes based on the user's selection.
Upvotes: 0
Views: 252
Reputation: 347194
Your current approach is placing too many eggs in a single basket. Why would ShapeSelectionWindow
be responsible for managing the JList
? It's sole responsibility is to draw a random shape.
Instead, you should break your design down.
I would start by defining a simple "shape" entity...
public enum Shape {
RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
private String name;
private Shape(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
This just provides a limit set of options which can be used.
I would then update the "shape pane" to support these options...
public class ShapePane extends JPanel {
private Shape shape;
public void setShape(Shape shape) {
this.shape = shape;
repaint();
}
public Shape getShape() {
return shape;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
Shape shape = getShape();
if (shape == null) {
return;
}
width = (int) Math.floor(Math.random() * 250) + 50;
height = (int) Math.floor(Math.random() * 250) + 50;
x = (int) Math.floor((615 - width) / 2);
y = (int) Math.floor((661 - height) / 2);
switch (shape) {
case RECTANGLE:
g.fillRect(x, y, width, height);
break;
case SQUARE:
break;
case CIRCLE:
break;
}
}
}
The ShapePane
doesn't care "how" the Shape
is specified, it only cares when it changes and wants to paint it
I would then use another component to act as the primary controller between the JList
and the ShapePane
...
public class MainPane extends JPanel {
private JList<Shape> list;
private ShapePane shapePane;
public MainPane() {
setLayout(new BorderLayout());
DefaultListModel<Shape> model = new DefaultListModel<>();
model.addElement(Shape.SQUARE);
model.addElement(Shape.RECTANGLE);
model.addElement(Shape.CIRCLE);
shapePane = new ShapePane();
list = new JList<Shape>(model);
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
Shape shape = list.getSelectedValue();
shapePane.setShape(shape);
}
});
add(list, BorderLayout.WEST);
add(shapePane, BorderLayout.CENTER);
}
}
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Shape {
RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
private String name;
private Shape(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
public class MainPane extends JPanel {
private JList<Shape> list;
private ShapePane shapePane;
public MainPane() {
setLayout(new BorderLayout());
DefaultListModel<Shape> model = new DefaultListModel<>();
model.addElement(Shape.SQUARE);
model.addElement(Shape.RECTANGLE);
model.addElement(Shape.CIRCLE);
shapePane = new ShapePane();
list = new JList<Shape>(model);
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
Shape shape = list.getSelectedValue();
shapePane.setShape(shape);
}
});
add(list, BorderLayout.WEST);
add(shapePane, BorderLayout.CENTER);
}
}
public class ShapePane extends JPanel {
private Shape shape;
public void setShape(Shape shape) {
this.shape = shape;
repaint();
}
public Shape getShape() {
return shape;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
Shape shape = getShape();
if (shape == null) {
return;
}
width = (int) Math.floor(Math.random() * 250) + 50;
height = (int) Math.floor(Math.random() * 250) + 50;
x = (int) Math.floor((615 - width) / 2);
y = (int) Math.floor((661 - height) / 2);
switch (shape) {
case RECTANGLE:
g.fillRect(x, y, width, height);
break;
case SQUARE:
break;
case CIRCLE:
break;
}
}
}
}
Upvotes: 1