制作一个简单的Swing GUI应用程序,让用户选择一个形状,通过JSlider选择形状的一侧的长度,应用然后计算面积/周长和绘制形状到屏幕,但我似乎无法得到它画出形状。我错过了什么或做错了什么?
对于糟糕的编码标准感到抱歉,这只是一个草稿,并且当我开始工作时计划重写也会忽略自动代码。
第一堂课,MyFrame。这只是一个让用户通过JMenu选择圆形,方形和三角形的JFrame。
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class MyFrame extends javax.swing.JFrame
implements ActionListener {
MyShape circle, square, shape, triangle;
MyControlPanel panel;
float area, perimeter;
public MyFrame() {
//initComponents();
panel = new MyControlPanel();
panel.setOpaque(true);
this.setSize(800,800);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
JMenuBar menuBar = new JMenuBar();
JMenu menuShape = new JMenu("Shape");
panel.getDimension();
JMenuItem menuItemSquare = new JMenuItem("Square");
menuItemSquare.addActionListener(this);
JMenuItem menuItemTriangle = new JMenuItem("Triangle");
menuItemTriangle.addActionListener(this);
JMenuItem menuItemCircle = new JMenuItem("Circle");
menuItemCircle.addActionListener(this);
menuShape.add(menuItemSquare);
menuShape.add(menuItemTriangle);
menuShape.add(menuItemCircle);
menuBar.add(menuShape);
this.setJMenuBar(menuBar);
//this.add(panel, BorderLayout.SOUTH);
this.add(panel, BorderLayout.CENTER);
}
@Override
public void actionPerformed(ActionEvent e)
{
String event = e.getActionCommand();
//not too sure if the standard is to use a switch or if statements?
switch(event)
{
case "Circle":
circle = new Circle();
panel.sendShape(circle, event);
panel.setSlider(50);
break;
case "Square":
square = new Square();
panel.sendShape(square, event);
panel.setSlider(50);
break;
case "Triangle":
triangle = new Triangle();
panel.sendShape(triangle, event);
panel.setSlider(50);
break;
}
}
public float getArea()
{
return area;
}
public float getPerimeter()
{
return perimeter;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
MyFrame frame = new MyFrame();
frame.setVisible(true);
}
}
下一个类MyControlPanel,包含JSlider,两个JTextFields和一个Canvas类的实例
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.NumberFormatter;
public class MyControlPanel extends JPanel implements ChangeListener {
static final int MIN = 0;
static final int MAX = 100;
static final int INIT = 50;
MyShape circle, square, triangle;
Canvas graphicPane;
JSlider lengthSlider;
JFormattedTextField pField, aField;
String menuSelection;
int sliderValue;
float size;
private MyShape shape;
public MyControlPanel() {
//initComponents();
BorderLayout layout = new BorderLayout();
this.setLayout(layout);
graphicPane = new Canvas();
this.add(graphicPane, BorderLayout.NORTH);
this.setLayout(new FlowLayout());
lengthSlider = new JSlider();
NumberFormat numberFormat = NumberFormat.getNumberInstance();
NumberFormatter formatter = new NumberFormatter(numberFormat);
formatter.setMinimum(new Float(MIN));
formatter.setMaximum(new Float(MAX));
pField = new JFormattedTextField(formatter);
pField.setValue(new Float(INIT));
pField.setColumns(5); //get some space
aField = new JFormattedTextField(formatter);
aField.setValue(new Float(INIT));
aField.setColumns(5); //get some space
JLabel sliderLabel = new JLabel("Shape Dimension");
JLabel pLabel = new JLabel("Boundary Lenght = ");
JLabel aLabel = new JLabel("Area = ");
lengthSlider.setMaximum(100);
lengthSlider.setMajorTickSpacing(10);
lengthSlider.setPaintLabels(true);
lengthSlider.setPaintTicks(true);
lengthSlider.addChangeListener(this);
this.add(lengthSlider, BorderLayout.SOUTH);
this.add(sliderLabel);
this.add(pLabel);
this.add(pField);
this.add(aLabel);
this.add(aField);
graphicPane.setVisible(true);
graphicPane.setOpaque(true);
}
@Override
public void stateChanged(ChangeEvent e)
{
// again not to sure if this can be a switch or does it have to be a if statement?
try{
switch(menuSelection)
{
// could i put the setAField and setPField out side of the switch?
case "Circle":
//shape = new Circle
float area = circle.getArea(getSliderValue());
float perimeter = circle.getBoundaryLength(getSliderValue());
this.setAfield(String.valueOf(area));
this.setPfield(String.valueOf(perimeter));
graphicPane.setLength(sliderValue);
break;
case "Square":
area = square.getArea(getSliderValue());
perimeter = square.getBoundaryLength(getSliderValue());
this.setAfield(String.valueOf(area));
this.setPfield(String.valueOf(perimeter));
graphicPane.setLength(sliderValue);
//JOptionPane.showMessageDialog(this, "area: " + area + " perimeter: " + perimeter);
break;
case "Triangle":
area = triangle.getArea(getSliderValue());
perimeter = triangle.getBoundaryLength(getSliderValue());
this.setAfield(String.valueOf(area));
this.setPfield(String.valueOf(perimeter));
graphicPane.setLength(sliderValue);
//JOptionPane.showMessageDialog(this, "area: " + area + " perimeter: " + perimeter);
break;
default:
JOptionPane.showMessageDialog(this, "you broke it");
break;
}
}
catch(NullPointerException npe)
{
if (sliderValue == 0)
{
sliderValue = 50;
}
else
{
JOptionPane.showMessageDialog(this, "you broke it "
+ "error code: "+ npe);
//JOptionPane.showMessageDialog(this, "area: " + area + " perimeter: " + perimeter);
}
}
catch (Exception ex)
{
JOptionPane.showMessageDialog(this, "you broke it "
+ "error code: "+ ex);
//JOptionPane.showMessageDialog(this, "area: " + area + " perimeter: " + perimeter);
}
}
public float getDimension()
{
return size;
}
public void sendShape(MyShape aShape, String pickedItem)
{
menuSelection = pickedItem;
switch(menuSelection)
{
case "Circle":
circle = aShape;
//graphicPane.setShape(pickedItem);
// or try
graphicPane.setShape("Circle");
break;
case "Square":
square = aShape;
//does it have to be "Square" or will it work this way?
graphicPane.setShape(pickedItem);
break;
case "Triangle":
triangle = aShape;
graphicPane.setShape(pickedItem);
break;
default:
JOptionPane.showMessageDialog(this, "you broke it");
}
}
public void setSlider(int value)
{
lengthSlider.setValue(value);
}
public int getSliderValue()
{
sliderValue = lengthSlider.getValue();
return sliderValue;
}
public void setPfield(String input)
{
pField.setText(input);
}
public void setAfield(String input)
{
aField.setText(input);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>
// Variables declaration - do not modify
// End of variables declaration
}
最后一个类Canvas,持有paintComponents
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Canvas extends JPanel{
private String selectedShape = "";
private int dimension = 0;
public Canvas(){
initComponents();
}
private void initComponents(){
this.setPreferredSize(new Dimension(600,400));
this.setBorder(BorderFactory.createTitledBorder("Shapes"));
this.setBackground(Color.green);
this.setOpaque(true);
}
@Override
public void paintComponents(Graphics g)
{
super.paintComponent(g);
switch(selectedShape)
{ //again what is the coding standards, should it be a switch or if?
case "Circle":
g.setColor(Color.RED); //trying anything to make it draw
g.drawOval(50, 50, dimension, dimension);
repaint();
g.fillOval(50, 50, dimension, dimension);
this.repaint();
break;
case "Square":
g.setColor(Color.BLUE);
//square = new Rectangle(10, 10, dimension, dimension);
g.drawRect(50, 50, dimension, dimension);
repaint();
g.fillRect(50, 50, dimension, dimension);
this.repaint();
break;
case "Triangle":
g.setColor(Color.WHITE);
int[] xCoOrd = {50, 50, 50+dimension};
int[] yCoOrd = {50, 50+dimension, 50+dimension};
//triangle = new Polygon (xCoOrd, yCoOrd, 3);
g.drawPolygon(xCoOrd, yCoOrd, 3);
repaint();
g.fillPolygon(xCoOrd, yCoOrd, 3);
this.repaint();
break;
default:
JOptionPane.showMessageDialog(this, "you broke it");
repaint();
this.repaint();
break;
}
repaint();
this.repaint();
}
public void setShape(String newShape)
{
selectedShape = newShape;
}
public void setLength(int newLength)
{
dimension = newLength;
}
}
先谢谢。
答案 0 :(得分:1)
你必须覆盖
JComponent.paintComponent(final Graphics g)
而不是
Container.paintComponents(final Graphics g)
它们有两个不同的用途。而且无需致电repaint()
。
编辑 - 让我试着澄清一点:
您的Canvas
课程延伸JPanel
,JComponent
延伸Container
...
因此,您的类继承了这些类的所有方法。此外,可以覆盖它们以改变它们的行为。您已经使用了这种机制。
你的陷阱只是选择了错误的方法(当然是因为它们的名字非常相似)。