Java PaintComponents 不绘制形状

标签 java

制作一个简单的 Swing GUI 应用程序,让用户选择一个形状,通过 JSlider 选择形状一侧的长度,然后应用程序计算面积/周长并将形状绘制到屏幕上,但我似乎无法让它绘制形状。我错过了什么或做错了什么?

抱歉,编码标准不佳,这只是一个草案,当我让它工作时,我将计划重写,并忽略自动代码。

一流,MyFrame。这只是一个 JFrame,允许用户通过 JMenu 选择圆形、正方形和三角形。

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、两个 JTextField 和 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;
}

}

提前致谢。

最佳答案

你必须覆盖

JComponent.paintComponent(final Graphics g) 

而不是

Container.paintComponents(final Graphics g)

它们有两个不同的目的。并且无需调用repaint()

编辑 - 让我尝试澄清一下:

您的Canvas类扩展了JPanel,它又扩展了JComponent,而JComponent又扩展了Container ...

因此,您的类继承了这些类的所有方法。此外,可以覆盖它们来改变它们的行为。您已经使用了此机制。

您的陷阱只是选择了错误的方法(当然是因为它们的名称非常相似)。

关于Java PaintComponents 不绘制形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20058953/

相关文章:

java.lang.NoSuchMethodError : org. apache.spark.sql.DataFrameReader.parquet

Java:回滚数据库更新?

java - 尝试分割长字符串并将其数据用于列表

Java - 打印 10 亿到 20 亿

java - 如何读取 Data Matrix 条形码

java - Soap 消息生成器返回字符串而不是发出请求

java - ActiveMQ:使用PooledConnectionFactory不会提高性能

java - Hibernate 6 Left Join 集合的最新成员

java - RabbitMQ - 只有一个队列,多个消费者接收不同的消息

java - Hibernate 无法初始化代理