我正在尝试实现一个基于菜单的图形 - 其中我将用圆圈表示一个顶点,每个圆圈将有一个由用户提供的索引。用户必须转到文件菜单并单击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));
}
}
答案 0 :(得分:4)
一些指示:
使用EDT创建和操作Swing组件。
不要不必要地延长JFrame
课程。
尽可能使用anonymous Listener
s
确保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));
}
}
。
由于我不确定您预期的结果,我已尽可能多地修复代码,因为我希望它有所帮助:
Random r=new Random();
<强>更新强>:
在Draw类中全局声明这个:paintComponent()
就好像每次调用{{1}}时都要使用新的Random实例一样,分布不会很大/足够随机
答案 1 :(得分:2)
每次用户创建新节点时,您都会创建一个添加到应用程序JPanel
的新JFrame
。在没有特定布局的情况下,它使用BorderLayout
。 BorderLayout
不允许在每个位置添加多个组件。您对add
的其他来电可能会被忽略。