根据用户Java Swing绘制多个形状

时间:2012-11-12 15:35:58

标签: java swing jframe jpanel

我正在尝试实现一个基于菜单的图形 - 其中我将用圆圈表示一个顶点,每个圆圈将有一个由用户提供的索引。用户必须转到文件菜单并单击Addvertex以创建一个新的带有索引的节点。但问题是 - 圆圈只绘制一次 - 任何后续点击addVertex都不会导致绘制圆圈 - 不明白为什么......

这是我的代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.*;
import java.util.*;

public class FileChoose extends JFrame {

    public FileChoose() {
        JMenuBar l=new JMenuBar();
        JMenu file=new JMenu("File");
        JMenuItem open=new JMenuItem("Addvertex");
        open.addActionListener(new Drawer());
        JMenuItem close=new JMenuItem("Exit");
        close.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        JMenu tools=new JMenu("Tools");
        file.add(open);
        file.add(close);

        this.setJMenuBar(l);
        l.add(tools);
        l.add(file);

        this.setSize(new Dimension(200, 200));
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
    }

    void HelloHere(String p) {
        Draw d = new Draw(p);
        this.add(d);
        setExtendedState(MAXIMIZED_BOTH);
    }

    class Drawer extends JFrame implements ActionListener {

        Integer index;

        public void actionPerformed(ActionEvent e) {
            JPanel pn = new JPanel();
            JTextField jt = new JTextField(5);
            JTextField jt1 = new JTextField(5);
            pn.add(jt);
            pn.add(jt1);
            int result=JOptionPane.showConfirmDialog(null, pn, "Enter the values", JOptionPane.OK_CANCEL_OPTION);
            if (result == JOptionPane.OK_OPTION) {
                index = Integer.parseInt(jt.getText());
                System.out.println(jt1.getText());
            }

            this.setVisible(true);
            this.setSize(500, 500);
            this.setLocationRelativeTo(null);

            HelloHere(index.toString());
        }
    }

    public static void main(String [] args) {
        FileChoose f = new FileChoose();
        f.setVisible(true);
    }
}

class Draw extends JPanel {

    String inp;

    public Draw(String gn) {
        inp = gn;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        Random r = new Random();
        int x = r.nextInt(100);

        g2.drawOval(x, x * 2, 100, 100);
        g2.drawString(inp, x + (x / 2), x + (x / 2));
    }
}

2 个答案:

答案 0 :(得分:4)

一些指示:

  • 使用EDT创建和操作Swing组件。

  • 不要不必要地延长JFrame课程。

  • 尽可能使用anonymous Listeners

  • 确保JFrame#setVisible(..)JFrame实例上最后一次专门指向此处的电话:

        this.setVisible(true);
        this.setSize(500, 500);
        this.setLocationRelativeTo(null);
        HelloHere(index.toString());
    
  • pack()个实例上致电JFrame而不是setSize(..)

  • 请勿使用多个JFrame,请参阅:The Use of Multiple JFrames: Good or Bad Practice?

  • 您遇到的问题是:

    Draw d = new Draw(p);
    this.add(d);
    

    您每次都在创建Draw JPanel的新实例,然后覆盖添加了新JPanel的新BorderLayout(默认情况下为revalidate()的行为) 。要解决这个问题,请阅读以下2点:

  • 在添加组件以显示新添加的组件后,在实例上调用repaint()import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.*; import javax.swing.*; public class FileChoose { JFrame frame; public FileChoose() { frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JMenuBar l = new JMenuBar(); JMenu file = new JMenu("File"); JMenuItem open = new JMenuItem("Addvertex"); open.addActionListener(new ActionListener() { Integer index; @Override public void actionPerformed(ActionEvent e) { JPanel pn = new JPanel(); JTextField jt = new JTextField(5); JTextField jt1 = new JTextField(5); pn.add(jt); pn.add(jt1); int result = JOptionPane.showConfirmDialog(null, pn, "Enter the values", JOptionPane.OK_CANCEL_OPTION); if (result == JOptionPane.OK_OPTION) { index = Integer.parseInt(jt.getText()); System.out.println(jt1.getText()); } HelloHere(index.toString()); } }); JMenuItem close = new JMenuItem("Exit"); close.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } }); JMenu tools = new JMenu("Tools"); file.add(open); file.add(close); frame.setJMenuBar(l); l.add(tools); l.add(file); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } void HelloHere(String p) { Draw d = new Draw(p); frame.add(d); frame.setExtendedState(JFrame.MAXIMIZED_BOTH); frame.revalidate(); frame.repaint(); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { FileChoose f = new FileChoose(); } }); } } class Draw extends JPanel { String inp; public Draw(String gn) { inp = gn; } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; Random r = new Random(); int x = r.nextInt(100); g2.drawOval(x, x * 2, 100, 100); g2.drawString(inp, x + (x / 2), x + (x / 2)); } }

  • 使用appropriate LayoutManager

由于我不确定您预期的结果,我已尽可能多地修复代码,因为我希望它有所帮助:

Random r=new Random();

<强>更新

在Draw类中全局声明这个:paintComponent()就好像每次调用{{1}}时都要使用新的Random实例一样,分布不会很大/足够随机

答案 1 :(得分:2)

每次用户创建新节点时,您都​​会创建一个添加到应用程序JPanel的新JFrame。在没有特定布局的情况下,它使用BorderLayoutBorderLayout不允许在每个位置添加多个组件。您对add的其他来电可能会被忽略。